diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 320197b88e..ef729a779f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/cache@v3 with: path: ${{ github.workspace }}/inspectcode - key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', '.editorconfig', '.globalconfig', 'CodeAnalysis/*') }} + key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }} - name: Dotnet code style run: dotnet build -c Debug -warnaserror osu.Desktop.slnf -p:EnforceCodeStyleInBuild=true @@ -82,7 +82,7 @@ jobs: run: dotnet build -c Debug -warnaserror osu.Desktop.slnf - name: Test - run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" + run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" shell: pwsh # Attempt to upload results even if test fails. @@ -96,27 +96,20 @@ jobs: build-only-android: name: Build only (Android) - runs-on: macos-latest + runs-on: windows-latest timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v2 - # Pin Xamarin.Android version to 11.2 for now to avoid build failures caused by a Xamarin-side regression. - # See: https://github.com/xamarin/xamarin-android/issues/6284 - # This can be removed/reverted when the fix makes it to upstream and is deployed on github runners. - - name: Set default Xamarin SDK version - run: | - $VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2 - - name: Install .NET 6.0.x uses: actions/setup-dotnet@v1 with: dotnet-version: "6.0.x" - # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono - # cannot accept .sln(f) files as arguments. - # Build just the main game for now. + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1 + - name: Build run: msbuild osu.Android/osu.Android.csproj /restore /p:Configuration=Debug diff --git a/CodeAnalysis/BannedSymbols.txt b/CodeAnalysis/BannedSymbols.txt index b72df0a306..e779ee6658 100644 --- a/CodeAnalysis/BannedSymbols.txt +++ b/CodeAnalysis/BannedSymbols.txt @@ -16,3 +16,10 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Linq.IQueryable M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Generic.IList{``0},Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IList,NotificationCallbackDelegate) instead. M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks. P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks. +M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever. +M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString. +M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString. +M:Humanizer.InflectorExtensions.Pascalize(System.String);Humanizer's .Pascalize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToPascalCase() instead. +M:Humanizer.InflectorExtensions.Camelize(System.String);Humanizer's .Camelize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToCamelCase() instead. +M:Humanizer.InflectorExtensions.Underscore(System.String);Humanizer's .Underscore() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToSnakeCase() instead. +M:Humanizer.InflectorExtensions.Kebaberize(System.String);Humanizer's .Kebaberize() extension method changes behaviour depending on CultureInfo.CurrentCulture. Use StringDehumanizeExtensions.ToKebabCase() instead. diff --git a/Directory.Build.props b/Directory.Build.props index 73a150d3e3..235feea8ce 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,9 @@  - 8.0 + 9.0 true + enable $(MSBuildThisFileDirectory)app.manifest diff --git a/Gemfile.lock b/Gemfile.lock index ddab497657..cae682ec2b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,20 +8,20 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.570.0) - aws-sdk-core (3.130.0) + aws-partitions (1.601.0) + aws-sdk-core (3.131.2) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) - jmespath (~> 1.0) - aws-sdk-kms (1.55.0) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.57.0) aws-sdk-core (~> 3, >= 3.127.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.113.0) + aws-sdk-s3 (1.114.0) aws-sdk-core (~> 3, >= 3.127.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) - aws-sigv4 (1.4.0) + aws-sigv4 (1.5.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) claide (1.1.0) @@ -36,7 +36,7 @@ GEM unf (>= 0.0.5, < 1.0.0) dotenv (2.7.6) emoji_regex (3.2.3) - excon (0.92.1) + excon (0.92.3) faraday (1.10.0) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -56,8 +56,8 @@ GEM faraday-em_synchrony (1.0.0) faraday-excon (1.1.0) faraday-httpclient (1.0.1) - faraday-multipart (1.0.3) - multipart-post (>= 1.2, < 3) + faraday-multipart (1.0.4) + multipart-post (~> 2) faraday-net_http (1.0.1) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) @@ -66,7 +66,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.205.1) + fastlane (2.206.2) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -110,9 +110,9 @@ GEM souyuz (= 0.11.1) fastlane-plugin-xamarin (0.6.3) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.16.0) - google-apis-core (>= 0.4, < 2.a) - google-apis-core (0.4.2) + google-apis-androidpublisher_v3 (0.23.0) + google-apis-core (>= 0.6, < 2.a) + google-apis-core (0.6.0) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -121,19 +121,19 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-iamcredentials_v1 (0.10.0) - google-apis-core (>= 0.4, < 2.a) - google-apis-playcustomapp_v1 (0.7.0) - google-apis-core (>= 0.4, < 2.a) - google-apis-storage_v1 (0.11.0) - google-apis-core (>= 0.4, < 2.a) + google-apis-iamcredentials_v1 (0.12.0) + google-apis-core (>= 0.6, < 2.a) + google-apis-playcustomapp_v1 (0.9.0) + google-apis-core (>= 0.6, < 2.a) + google-apis-storage_v1 (0.16.0) + google-apis-core (>= 0.6, < 2.a) google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) google-cloud-errors (1.2.0) - google-cloud-storage (1.36.1) + google-cloud-storage (1.36.2) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) @@ -141,7 +141,7 @@ GEM google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.1.2) + googleauth (1.2.0) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -149,12 +149,12 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.4) + http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.1) - json (2.6.1) - jwt (2.3.0) + json (2.6.2) + jwt (2.4.1) memoist (0.16.2) mini_magick (4.11.0) mini_mime (1.1.2) @@ -169,10 +169,10 @@ GEM optparse (0.1.1) os (1.1.4) plist (3.6.0) - public_suffix (4.0.6) + public_suffix (4.0.7) racc (1.6.0) rake (13.0.6) - representable (3.1.1) + representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) @@ -182,9 +182,9 @@ GEM ruby2_keywords (0.0.5) rubyzip (2.3.2) security (0.1.3) - signet (0.16.1) + signet (0.17.0) addressable (~> 2.8) - faraday (>= 0.17.5, < 3.0) + faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) simctl (1.6.8) @@ -205,11 +205,11 @@ GEM uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8.1) + unf_ext (0.0.8.2) unicode-display_width (1.8.0) webrick (1.7.0) word_wrap (1.0.0) - xcodeproj (1.21.0) + xcodeproj (1.22.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index bc285dbe11..011a37cbdc 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -9,7 +9,6 @@ false - diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs index baf503085d..00754c6346 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformRuleset.cs @@ -1,6 +1,7 @@ // Copyright (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; @@ -41,7 +42,7 @@ namespace osu.Game.Rulesets.EmptyFreeform return new[] { new EmptyFreeformModAutoplay() }; default: - return new Mod[] { null }; + return Array.Empty(); } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 718ada1905..c04f6132f3 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -9,7 +9,6 @@ false - diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs index 15e988f466..7dcdac7019 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs @@ -1,6 +1,7 @@ // Copyright (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.Sprites; @@ -37,7 +38,7 @@ namespace osu.Game.Rulesets.Pippidon return new[] { new PippidonModAutoplay() }; default: - return new Mod[] { null }; + return Array.Empty(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index 6b9c3f4d63..529054fd4f 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -9,7 +9,6 @@ false - diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs index b9bed74c88..c8f0c07724 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingRuleset.cs @@ -1,6 +1,7 @@ // Copyright (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.Sprites; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.EmptyScrolling return new[] { new EmptyScrollingModAutoplay() }; default: - return new Mod[] { null }; + return Array.Empty(); } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 718ada1905..c04f6132f3 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -9,7 +9,6 @@ false - diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs index ea94ceb4b5..d4566477db 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonRuleset.cs @@ -1,6 +1,7 @@ // Copyright (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.Sprites; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Pippidon return new[] { new PippidonModAutoplay() }; default: - return new Mod[] { null }; + return Array.Empty(); } } diff --git a/osu.Android.props b/osu.Android.props index aad8cf10d0..c83b7872ac 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,8 +51,8 @@ - - + + diff --git a/osu.Android/AndroidJoystickSettings.cs b/osu.Android/AndroidJoystickSettings.cs new file mode 100644 index 0000000000..26e921a426 --- /dev/null +++ b/osu.Android/AndroidJoystickSettings.cs @@ -0,0 +1,76 @@ +// Copyright (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.Android.Input; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Localisation; +using osu.Game.Overlays.Settings; + +namespace osu.Android +{ + public class AndroidJoystickSettings : SettingsSubsection + { + protected override LocalisableString Header => JoystickSettingsStrings.JoystickGamepad; + + private readonly AndroidJoystickHandler joystickHandler; + + private readonly Bindable enabled = new BindableBool(true); + + private SettingsSlider deadzoneSlider = null!; + + private Bindable handlerDeadzone = null!; + + private Bindable localDeadzone = null!; + + public AndroidJoystickSettings(AndroidJoystickHandler joystickHandler) + { + this.joystickHandler = joystickHandler; + } + + [BackgroundDependencyLoader] + private void load() + { + // use local bindable to avoid changing enabled state of game host's bindable. + handlerDeadzone = joystickHandler.DeadzoneThreshold.GetBoundCopy(); + localDeadzone = handlerDeadzone.GetUnboundCopy(); + + Children = new Drawable[] + { + new SettingsCheckbox + { + LabelText = CommonStrings.Enabled, + Current = enabled + }, + deadzoneSlider = new SettingsSlider + { + LabelText = JoystickSettingsStrings.DeadzoneThreshold, + KeyboardStep = 0.01f, + DisplayAsPercentage = true, + Current = localDeadzone, + }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + enabled.BindTo(joystickHandler.Enabled); + enabled.BindValueChanged(e => deadzoneSlider.Current.Disabled = !e.NewValue, true); + + handlerDeadzone.BindValueChanged(val => + { + bool disabled = localDeadzone.Disabled; + + localDeadzone.Disabled = false; + localDeadzone.Value = val.NewValue; + localDeadzone.Disabled = disabled; + }, true); + + localDeadzone.BindValueChanged(val => handlerDeadzone.Value = val.NewValue); + } + } +} diff --git a/osu.Android/AndroidMouseSettings.cs b/osu.Android/AndroidMouseSettings.cs new file mode 100644 index 0000000000..54b787fd17 --- /dev/null +++ b/osu.Android/AndroidMouseSettings.cs @@ -0,0 +1,97 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Android.OS; +using osu.Framework.Allocation; +using osu.Framework.Android.Input; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Configuration; +using osu.Game.Localisation; +using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections.Input; + +namespace osu.Android +{ + public class AndroidMouseSettings : SettingsSubsection + { + private readonly AndroidMouseHandler mouseHandler; + + protected override LocalisableString Header => MouseSettingsStrings.Mouse; + + private Bindable handlerSensitivity = null!; + + private Bindable localSensitivity = null!; + + private Bindable relativeMode = null!; + + public AndroidMouseSettings(AndroidMouseHandler mouseHandler) + { + this.mouseHandler = mouseHandler; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager osuConfig) + { + // use local bindable to avoid changing enabled state of game host's bindable. + handlerSensitivity = mouseHandler.Sensitivity.GetBoundCopy(); + localSensitivity = handlerSensitivity.GetUnboundCopy(); + + relativeMode = mouseHandler.UseRelativeMode.GetBoundCopy(); + + // High precision/pointer capture is only available on Android 8.0 and up + if (Build.VERSION.SdkInt >= BuildVersionCodes.O) + { + AddRange(new Drawable[] + { + new SettingsCheckbox + { + LabelText = MouseSettingsStrings.HighPrecisionMouse, + TooltipText = MouseSettingsStrings.HighPrecisionMouseTooltip, + Current = relativeMode, + Keywords = new[] { @"raw", @"input", @"relative", @"cursor", @"captured", @"pointer" }, + }, + new MouseSettings.SensitivitySetting + { + LabelText = MouseSettingsStrings.CursorSensitivity, + Current = localSensitivity, + }, + }); + } + + AddRange(new Drawable[] + { + new SettingsCheckbox + { + LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust, + TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip, + Current = osuConfig.GetBindable(OsuSetting.MouseDisableWheel), + }, + new SettingsCheckbox + { + LabelText = MouseSettingsStrings.DisableMouseButtons, + Current = osuConfig.GetBindable(OsuSetting.MouseDisableButtons), + }, + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + relativeMode.BindValueChanged(relative => localSensitivity.Disabled = !relative.NewValue, true); + + handlerSensitivity.BindValueChanged(val => + { + bool disabled = localSensitivity.Disabled; + + localSensitivity.Disabled = false; + localSensitivity.Value = val.NewValue; + localSensitivity.Disabled = disabled; + }, true); + + localSensitivity.BindValueChanged(val => handlerSensitivity.Value = val.NewValue); + } + } +} diff --git a/osu.Android/GameplayScreenRotationLocker.cs b/osu.Android/GameplayScreenRotationLocker.cs index 2e83f784d3..9e849bdc7c 100644 --- a/osu.Android/GameplayScreenRotationLocker.cs +++ b/osu.Android/GameplayScreenRotationLocker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android.Content.PM; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index eebd079f68..be40db7508 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs index 050bf2b787..062f2ce10c 100644 --- a/osu.Android/OsuGameAndroid.cs +++ b/osu.Android/OsuGameAndroid.cs @@ -1,11 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Android.App; using Android.OS; using osu.Framework.Allocation; +using osu.Framework.Android.Input; +using osu.Framework.Input.Handlers; +using osu.Framework.Platform; using osu.Game; +using osu.Game.Overlays.Settings; using osu.Game.Updater; using osu.Game.Utils; using Xamarin.Essentials; @@ -73,10 +79,31 @@ namespace osu.Android LoadComponentAsync(new GameplayScreenRotationLocker(), Add); } + public override void SetHost(GameHost host) + { + base.SetHost(host); + host.Window.CursorState |= CursorState.Hidden; + } + protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager(); protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo(); + public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler) + { + switch (handler) + { + case AndroidMouseHandler mh: + return new AndroidMouseSettings(mh); + + case AndroidJoystickHandler jh: + return new AndroidJoystickSettings(jh); + + default: + return base.CreateSettingsSubsectionFor(handler); + } + } + private class AndroidBatteryInfo : BatteryInfo { public override double ChargeLevel => Battery.ChargeLevel; diff --git a/osu.Android/Properties/AssemblyInfo.cs b/osu.Android/Properties/AssemblyInfo.cs index c0ba324d6e..f65b1b239f 100644 --- a/osu.Android/Properties/AssemblyInfo.cs +++ b/osu.Android/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android; using Android.App; diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index fc50ca9fa1..004cc8c39c 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -26,6 +26,8 @@ true + + diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index d87b25a4c7..d0b6953c30 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Text; using DiscordRPC; @@ -9,6 +11,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Extensions; using osu.Game.Online.API; @@ -30,6 +33,9 @@ namespace osu.Desktop private IBindable user; + [Resolved] + private IAPIProvider api { get; set; } + private readonly IBindable status = new Bindable(); private readonly IBindable activity = new Bindable(); @@ -41,7 +47,7 @@ namespace osu.Desktop }; [BackgroundDependencyLoader] - private void load(IAPIProvider provider, OsuConfigManager config) + private void load(OsuConfigManager config) { client = new DiscordRpcClient(client_id) { @@ -51,13 +57,14 @@ namespace osu.Desktop client.OnReady += onReady; // safety measure for now, until we performance test / improve backoff for failed connections. - client.OnConnectionFailed += (_, __) => client.Deinitialize(); + client.OnConnectionFailed += (_, _) => client.Deinitialize(); client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network); config.BindWith(OsuSetting.DiscordRichPresence, privacyMode); - (user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u => + user = api.LocalUser.GetBoundCopy(); + user.BindValueChanged(u => { status.UnbindBindings(); status.BindTo(u.NewValue.Status); @@ -95,6 +102,22 @@ namespace osu.Desktop { presence.State = truncate(activity.Value.Status); presence.Details = truncate(getDetails(activity.Value)); + + if (getBeatmap(activity.Value) is IBeatmapInfo beatmap && beatmap.OnlineID > 0) + { + presence.Buttons = new[] + { + new Button + { + Label = "View beatmap", + Url = $@"{api.WebsiteRootUrl}/beatmapsets/{beatmap.BeatmapSet?.OnlineID}#{ruleset.Value.ShortName}/{beatmap.OnlineID}" + } + }; + } + else + { + presence.Buttons = null; + } } else { @@ -106,7 +129,12 @@ namespace osu.Desktop if (privacyMode.Value == DiscordRichPresenceMode.Limited) presence.Assets.LargeImageText = string.Empty; else - presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty); + { + if (user.Value.RulesetsStatistics != null && user.Value.RulesetsStatistics.TryGetValue(ruleset.Value.ShortName, out UserStatistics statistics)) + presence.Assets.LargeImageText = $"{user.Value.Username}" + (statistics.GlobalRank > 0 ? $" (rank #{statistics.GlobalRank:N0})" : string.Empty); + else + presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty); + } // update ruleset presence.Assets.SmallImageKey = ruleset.Value.IsLegacyRuleset() ? $"mode_{ruleset.Value.OnlineID}" : "mode_custom"; @@ -136,6 +164,20 @@ namespace osu.Desktop }); } + private IBeatmapInfo getBeatmap(UserActivity activity) + { + switch (activity) + { + case UserActivity.InGame game: + return game.BeatmapInfo; + + case UserActivity.Editing edit: + return edit.BeatmapInfo; + } + + return null; + } + private string getDetails(UserActivity activity) { switch (activity) diff --git a/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationRequest.cs b/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationRequest.cs index d6ef390a8f..7b0bd69363 100644 --- a/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationRequest.cs +++ b/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Desktop.LegacyIpc { /// diff --git a/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationResponse.cs b/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationResponse.cs index 7b9fae5797..6d36cbc4b6 100644 --- a/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationResponse.cs +++ b/osu.Desktop/LegacyIpc/LegacyIpcDifficultyCalculationResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Desktop.LegacyIpc { /// diff --git a/osu.Desktop/LegacyIpc/LegacyIpcMessage.cs b/osu.Desktop/LegacyIpc/LegacyIpcMessage.cs index 0fa60e2068..4df477191d 100644 --- a/osu.Desktop/LegacyIpc/LegacyIpcMessage.cs +++ b/osu.Desktop/LegacyIpc/LegacyIpcMessage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Platform; using Newtonsoft.Json.Linq; diff --git a/osu.Desktop/LegacyIpc/LegacyTcpIpcProvider.cs b/osu.Desktop/LegacyIpc/LegacyTcpIpcProvider.cs index 10761bc315..5d950eef55 100644 --- a/osu.Desktop/LegacyIpc/LegacyTcpIpcProvider.cs +++ b/osu.Desktop/LegacyIpc/LegacyTcpIpcProvider.cs @@ -15,8 +15,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; -#nullable enable - namespace osu.Desktop.LegacyIpc { /// diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index be8159a7cc..524436235e 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -18,25 +18,36 @@ using osu.Framework; using osu.Framework.Logging; using osu.Game.Updater; using osu.Desktop.Windows; +using osu.Framework.Input.Handlers; +using osu.Framework.Input.Handlers.Joystick; +using osu.Framework.Input.Handlers.Mouse; +using osu.Framework.Input.Handlers.Tablet; +using osu.Framework.Input.Handlers.Touch; using osu.Framework.Threading; using osu.Game.IO; +using osu.Game.IPC; +using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections; +using osu.Game.Overlays.Settings.Sections.Input; namespace osu.Desktop { internal class OsuGameDesktop : OsuGame { - public OsuGameDesktop(string[] args = null) + private OsuSchemeLinkIPCChannel? osuSchemeLinkIPCChannel; + + public OsuGameDesktop(string[]? args = null) : base(args) { } - public override StableStorage GetStorageForStableInstall() + public override StableStorage? GetStorageForStableInstall() { try { if (Host is DesktopGameHost desktopHost) { - string stablePath = getStableInstallPath(); + string? stablePath = getStableInstallPath(); if (!string.IsNullOrEmpty(stablePath)) return new StableStorage(stablePath, desktopHost); } @@ -49,11 +60,11 @@ namespace osu.Desktop return null; } - private string getStableInstallPath() + private string? getStableInstallPath() { static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg")); - string stableInstallPath; + string? stableInstallPath; if (OperatingSystem.IsWindows()) { @@ -81,15 +92,15 @@ namespace osu.Desktop } [SupportedOSPlatform("windows")] - private string getStableInstallPathFromRegistry() + private string? getStableInstallPathFromRegistry() { - using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) + using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu")) return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); } protected override UpdateManager CreateUpdateManager() { - string packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER"); + string? packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER"); if (!string.IsNullOrEmpty(packageManaged)) return new NoActionUpdateManager(); @@ -116,6 +127,8 @@ namespace osu.Desktop LoadComponentAsync(new GameplayWinKeyBlocker(), Add); LoadComponentAsync(new ElevatedPrivilegesChecker(), Add); + + osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this); } public override void SetHost(GameHost host) @@ -132,8 +145,29 @@ namespace osu.Desktop desktopWindow.DragDrop += f => fileDrop(new[] { f }); } + public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler) + { + switch (handler) + { + case ITabletHandler th: + return new TabletSettings(th); + + case MouseHandler mh: + return new MouseSettings(mh); + + case JoystickHandler jh: + return new JoystickSettings(jh); + + case TouchHandler th: + return new InputSection.HandlerSection(th); + + default: + return base.CreateSettingsSubsectionFor(handler); + } + } + private readonly List importableFiles = new List(); - private ScheduledDelegate importSchedule; + private ScheduledDelegate? importSchedule; private void fileDrop(string[] filePaths) { @@ -166,5 +200,11 @@ namespace osu.Desktop Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning); } } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + osuSchemeLinkIPCChannel?.Dispose(); + } } } diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 405f0a8006..19cf7f5d46 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Runtime.Versioning; @@ -9,8 +11,10 @@ using osu.Framework; using osu.Framework.Development; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Game; using osu.Game.IPC; using osu.Game.Tournament; +using SDL2; using Squirrel; namespace osu.Desktop @@ -26,7 +30,27 @@ namespace osu.Desktop { // run Squirrel first, as the app may exit after these run if (OperatingSystem.IsWindows()) + { + var windowsVersion = Environment.OSVersion.Version; + + // While .NET 6 still supports Windows 7 and above, we are limited by realm currently, as they choose to only support 8.1 and higher. + // See https://www.mongodb.com/docs/realm/sdk/dotnet/#supported-platforms + if (windowsVersion.Major < 6 || (windowsVersion.Major == 6 && windowsVersion.Minor <= 2)) + { + // If users running in compatibility mode becomes more of a common thing, we may want to provide better guidance or even consider + // disabling it ourselves. + // We could also better detect compatibility mode if required: + // https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730 + SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, + "Your operating system is too old to run osu!", + "This version of osu! requires at least Windows 8.1 to run.\n" + + "Please upgrade your operating system or consider using an older version of osu!.\n\n" + + "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!", IntPtr.Zero); + return; + } + setupSquirrel(); + } // Back up the cwd before DesktopGameHost changes it string cwd = Environment.CurrentDirectory; @@ -63,19 +87,8 @@ namespace osu.Desktop { if (!host.IsPrimaryInstance) { - if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args - { - var importer = new ArchiveImportIPCChannel(host); - - foreach (string file in args) - { - Console.WriteLine(@"Importing {0}", file); - if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000)) - throw new TimeoutException(@"IPC took too long to send"); - } - + if (trySendIPCMessage(host, cwd, args)) return; - } // we want to allow multiple instances to be started when in debug. if (!DebugUtils.IsDebugBuild) @@ -106,18 +119,49 @@ namespace osu.Desktop } } + private static bool trySendIPCMessage(IIpcHost host, string cwd, string[] args) + { + if (args.Length == 1 && args[0].StartsWith(OsuGameBase.OSU_PROTOCOL, StringComparison.Ordinal)) + { + var osuSchemeLinkHandler = new OsuSchemeLinkIPCChannel(host); + if (!osuSchemeLinkHandler.HandleLinkAsync(args[0]).Wait(3000)) + throw new IPCTimeoutException(osuSchemeLinkHandler.GetType()); + + return true; + } + + if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args + { + var importer = new ArchiveImportIPCChannel(host); + + foreach (string file in args) + { + Console.WriteLine(@"Importing {0}", file); + if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000)) + throw new IPCTimeoutException(importer.GetType()); + } + + return true; + } + + return false; + } + [SupportedOSPlatform("windows")] private static void setupSquirrel() { - SquirrelAwareApp.HandleEvents(onInitialInstall: (version, tools) => + SquirrelAwareApp.HandleEvents(onInitialInstall: (_, tools) => { tools.CreateShortcutForThisExe(); tools.CreateUninstallerRegistryEntry(); - }, onAppUninstall: (version, tools) => + }, onAppUpdate: (_, tools) => + { + tools.CreateUninstallerRegistryEntry(); + }, onAppUninstall: (_, tools) => { tools.RemoveShortcutForThisExe(); tools.RemoveUninstallerRegistryEntry(); - }, onEveryRun: (version, tools, firstRun) => + }, onEveryRun: (_, _, _) => { // While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently // causes the right-click context menu to function incorrectly. diff --git a/osu.Desktop/Security/ElevatedPrivilegesChecker.cs b/osu.Desktop/Security/ElevatedPrivilegesChecker.cs index ba37a14442..f0d95ba194 100644 --- a/osu.Desktop/Security/ElevatedPrivilegesChecker.cs +++ b/osu.Desktop/Security/ElevatedPrivilegesChecker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Security.Principal; using osu.Framework; diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index c09cce1235..4e5f8d37b1 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.Versioning; using System.Threading.Tasks; @@ -152,7 +154,7 @@ namespace osu.Desktop.Updater Activated = () => { updateManager.PrepareUpdateAsync() - .ContinueWith(_ => updateManager.Schedule(() => game?.GracefullyExit())); + .ContinueWith(_ => updateManager.Schedule(() => game?.AttemptExit())); return true; }; } diff --git a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs index 4acaf61cea..0cb4ba9c04 100644 --- a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs +++ b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Desktop/Windows/WindowsKey.cs b/osu.Desktop/Windows/WindowsKey.cs index fdca2028d3..c69cce6200 100644 --- a/osu.Desktop/Windows/WindowsKey.cs +++ b/osu.Desktop/Windows/WindowsKey.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.InteropServices; diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index a4f9e2671b..c67017f175 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.Game.Benchmarks/BenchmarkHitObject.cs b/osu.Game.Benchmarks/BenchmarkHitObject.cs new file mode 100644 index 0000000000..65c78e39b3 --- /dev/null +++ b/osu.Game.Benchmarks/BenchmarkHitObject.cs @@ -0,0 +1,166 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using BenchmarkDotNet.Attributes; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Benchmarks +{ + public class BenchmarkHitObject : BenchmarkTest + { + [Params(1, 100, 1000)] + public int Count { get; set; } + + [Params(false, true)] + public bool WithBindableAccess { get; set; } + + [Benchmark] + public HitCircle[] OsuCircle() + { + var circles = new HitCircle[Count]; + + for (int i = 0; i < Count; i++) + { + circles[i] = new HitCircle(); + + if (WithBindableAccess) + { + _ = circles[i].PositionBindable; + _ = circles[i].ScaleBindable; + _ = circles[i].ComboIndexBindable; + _ = circles[i].ComboOffsetBindable; + _ = circles[i].StackHeightBindable; + _ = circles[i].LastInComboBindable; + _ = circles[i].ComboIndexWithOffsetsBindable; + _ = circles[i].IndexInCurrentComboBindable; + _ = circles[i].SamplesBindable; + _ = circles[i].StartTimeBindable; + } + else + { + _ = circles[i].Position; + _ = circles[i].Scale; + _ = circles[i].ComboIndex; + _ = circles[i].ComboOffset; + _ = circles[i].StackHeight; + _ = circles[i].LastInCombo; + _ = circles[i].ComboIndexWithOffsets; + _ = circles[i].IndexInCurrentCombo; + _ = circles[i].Samples; + _ = circles[i].StartTime; + _ = circles[i].Position; + _ = circles[i].Scale; + _ = circles[i].ComboIndex; + _ = circles[i].ComboOffset; + _ = circles[i].StackHeight; + _ = circles[i].LastInCombo; + _ = circles[i].ComboIndexWithOffsets; + _ = circles[i].IndexInCurrentCombo; + _ = circles[i].Samples; + _ = circles[i].StartTime; + } + } + + return circles; + } + + [Benchmark] + public Hit[] TaikoHit() + { + var hits = new Hit[Count]; + + for (int i = 0; i < Count; i++) + { + hits[i] = new Hit(); + + if (WithBindableAccess) + { + _ = hits[i].TypeBindable; + _ = hits[i].IsStrongBindable; + _ = hits[i].SamplesBindable; + _ = hits[i].StartTimeBindable; + } + else + { + _ = hits[i].Type; + _ = hits[i].IsStrong; + _ = hits[i].Samples; + _ = hits[i].StartTime; + } + } + + return hits; + } + + [Benchmark] + public Fruit[] CatchFruit() + { + var fruit = new Fruit[Count]; + + for (int i = 0; i < Count; i++) + { + fruit[i] = new Fruit(); + + if (WithBindableAccess) + { + _ = fruit[i].OriginalXBindable; + _ = fruit[i].XOffsetBindable; + _ = fruit[i].ScaleBindable; + _ = fruit[i].ComboIndexBindable; + _ = fruit[i].HyperDashBindable; + _ = fruit[i].LastInComboBindable; + _ = fruit[i].ComboIndexWithOffsetsBindable; + _ = fruit[i].IndexInCurrentComboBindable; + _ = fruit[i].IndexInBeatmapBindable; + _ = fruit[i].SamplesBindable; + _ = fruit[i].StartTimeBindable; + } + else + { + _ = fruit[i].OriginalX; + _ = fruit[i].XOffset; + _ = fruit[i].Scale; + _ = fruit[i].ComboIndex; + _ = fruit[i].HyperDash; + _ = fruit[i].LastInCombo; + _ = fruit[i].ComboIndexWithOffsets; + _ = fruit[i].IndexInCurrentCombo; + _ = fruit[i].IndexInBeatmap; + _ = fruit[i].Samples; + _ = fruit[i].StartTime; + } + } + + return fruit; + } + + [Benchmark] + public Note[] ManiaNote() + { + var notes = new Note[Count]; + + for (int i = 0; i < Count; i++) + { + notes[i] = new Note(); + + if (WithBindableAccess) + { + _ = notes[i].ColumnBindable; + _ = notes[i].SamplesBindable; + _ = notes[i].StartTimeBindable; + } + else + { + _ = notes[i].Column; + _ = notes[i].Samples; + _ = notes[i].StartTime; + } + } + + return notes; + } + } +} diff --git a/osu.Game.Benchmarks/BenchmarkMod.cs b/osu.Game.Benchmarks/BenchmarkMod.cs index c5375e9f09..994300df36 100644 --- a/osu.Game.Benchmarks/BenchmarkMod.cs +++ b/osu.Game.Benchmarks/BenchmarkMod.cs @@ -9,7 +9,7 @@ namespace osu.Game.Benchmarks { public class BenchmarkMod : BenchmarkTest { - private OsuModDoubleTime mod; + private OsuModDoubleTime mod = null!; [Params(1, 10, 100)] public int Times { get; set; } diff --git a/osu.Game.Benchmarks/BenchmarkRealmReads.cs b/osu.Game.Benchmarks/BenchmarkRealmReads.cs index 615e2e964d..1df77320d2 100644 --- a/osu.Game.Benchmarks/BenchmarkRealmReads.cs +++ b/osu.Game.Benchmarks/BenchmarkRealmReads.cs @@ -15,9 +15,9 @@ namespace osu.Game.Benchmarks { public class BenchmarkRealmReads : BenchmarkTest { - private TemporaryNativeStorage storage; - private RealmAccess realm; - private UpdateThread updateThread; + private TemporaryNativeStorage storage = null!; + private RealmAccess realm = null!; + private UpdateThread updateThread = null!; [Params(1, 100, 1000)] public int ReadsPerFetch { get; set; } @@ -29,7 +29,7 @@ namespace osu.Game.Benchmarks realm = new RealmAccess(storage, OsuGameBase.CLIENT_DATABASE_FILENAME); - realm.Run(r => + realm.Run(_ => { realm.Write(c => c.Add(TestResources.CreateTestBeatmapSetInfo(rulesets: new[] { new OsuRuleset().RulesetInfo }))); }); @@ -74,7 +74,7 @@ namespace osu.Game.Benchmarks } }); - done.Wait(); + done.Wait(60000); } [Benchmark] @@ -113,7 +113,7 @@ namespace osu.Game.Benchmarks } }); - done.Wait(); + done.Wait(60000); } [Benchmark] @@ -133,9 +133,9 @@ namespace osu.Game.Benchmarks [GlobalCleanup] public void Cleanup() { - realm?.Dispose(); - storage?.Dispose(); - updateThread?.Exit(); + realm.Dispose(); + storage.Dispose(); + updateThread.Exit(); } } } diff --git a/osu.Game.Benchmarks/BenchmarkRuleset.cs b/osu.Game.Benchmarks/BenchmarkRuleset.cs index 2835ec9499..7d318e043b 100644 --- a/osu.Game.Benchmarks/BenchmarkRuleset.cs +++ b/osu.Game.Benchmarks/BenchmarkRuleset.cs @@ -11,9 +11,9 @@ namespace osu.Game.Benchmarks { public class BenchmarkRuleset : BenchmarkTest { - private OsuRuleset ruleset; - private APIMod apiModDoubleTime; - private APIMod apiModDifficultyAdjust; + private OsuRuleset ruleset = null!; + private APIMod apiModDoubleTime = null!; + private APIMod apiModDifficultyAdjust = null!; public override void SetUp() { diff --git a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs index d8b729576d..64c71c9ecd 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs index 39fe3dac25..64ff3f7151 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs +++ b/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Foundation; using osu.Framework.iOS; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs index e44868e133..71d943ece1 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.iOS; using UIKit; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index baca8166d1..b6cb351c1e 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs index 48d46636df..cf030f6e13 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Difficulty; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs index eae07daa3d..b9d6f28228 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; @@ -22,21 +24,24 @@ namespace osu.Game.Rulesets.Catch.Tests new object[] { LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime) } }, new object[] { LegacyMods.Relax, new[] { typeof(CatchModRelax) } }, new object[] { LegacyMods.HalfTime, new[] { typeof(CatchModHalfTime) } }, - new object[] { LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) } }, new object[] { LegacyMods.Flashlight, new[] { typeof(CatchModFlashlight) } }, new object[] { LegacyMods.Autoplay, new[] { typeof(CatchModAutoplay) } }, - new object[] { LegacyMods.Perfect, new[] { typeof(CatchModPerfect) } }, - new object[] { LegacyMods.Cinema, new[] { typeof(CatchModCinema) } }, new object[] { LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(CatchModHardRock), typeof(CatchModDoubleTime) } } }; + [TestCaseSource(nameof(catch_mod_mapping))] + [TestCase(LegacyMods.Cinema, new[] { typeof(CatchModCinema) })] + [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(CatchModCinema) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(CatchModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })] + public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods); + [TestCaseSource(nameof(catch_mod_mapping))] [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(CatchModCinema) })] [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })] [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })] - public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods); - - [TestCaseSource(nameof(catch_mod_mapping))] public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods); protected override Ruleset CreateRuleset() => new CatchRuleset(); diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs index bb3a724b91..f30b216d8d 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.IO.Stores; using osu.Game.Rulesets.Catch.Skinning; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs index 378772fea3..be6622f06e 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs index 158c8edba5..78f56b4937 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs index 1d30ae34cd..9060fa5aa0 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchPlacementBlueprintTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs index 88fd3b36ba..ea17fa400c 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/Checks/TestCheckBananaShowerGap.cs b/osu.Game.Rulesets.Catch.Tests/Editor/Checks/TestCheckBananaShowerGap.cs index 055c8429d7..16361d12c6 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/Checks/TestCheckBananaShowerGap.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/Checks/TestCheckBananaShowerGap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs index fec253924f..d08acc90cd 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs index 2be0b7e9b2..405bab971c 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs index 161c685043..9ecfd5f5c5 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs index 4b1c45ae2f..94574b564d 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index b1adc4901c..691ebc7efc 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index 22a839d847..8635a88d79 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs b/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs index 5248d5a96a..0de992c1df 100644 --- a/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -90,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.Tests new JuiceStreamPathVertex(20, -5) })); - removeCount = path.RemoveVertices((_, i) => true); + removeCount = path.RemoveVertices((_, _) => true); Assert.That(removeCount, Is.EqualTo(1)); Assert.That(path.Vertices, Is.EqualTo(new[] { diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs index fbbfee6b60..19321a48b9 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/CatchModMirrorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs index bbe543e73e..ffc5734f01 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModNoScope.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs index 3e06e78dba..886822f9a5 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs index c01aff0aa0..3209be12d5 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 1014158fc1..202228c9e7 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs index 96ac5c4bf2..0ddc58eb25 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs index 09362929d2..7e1c39f6a8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs index 31d0831fae..16942f3f35 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs index b7cd6737b1..8dd6f82c57 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; @@ -27,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("change component scale", () => Player.ChildrenOfType().First().Scale = new Vector2(2f)); AddStep("update target", () => Player.ChildrenOfType().ForEach(LegacySkin.UpdateDrawableTarget)); AddStep("exit player", () => Player.Exit()); - CreateTest(null); + CreateTest(); } AddAssert("legacy HUD combo counter hidden", () => diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs index a10371b0f7..6e12dacf29 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs index 8ae2bcca0e..6ecbf58a52 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchSkinConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index 0a4ef49e19..1405e0018d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 4f527e9a0f..956d0e0c14 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 7cae9b18b9..150c1f8406 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs index b720ab1e97..7f513728af 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneComboCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 4b8fede369..94c870a444 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs index 62fe5dca2c..868f498e8c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Catch.Mods; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs index 12b98dc93c..7d72633e34 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index c888dc0a65..c7d130b440 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs index 9446e864a1..f7abd8d519 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index a5b44dc605..4886942dc6 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -31,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Tests hyperDashCount = 0; // this needs to be done within the frame stable context due to how quickly hyperdash state changes occur. - Player.DrawableRuleset.FrameStableComponents.OnUpdate += d => + Player.DrawableRuleset.FrameStableComponents.OnUpdate += _ => { var catcher = Player.ChildrenOfType().FirstOrDefault(); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index 14a4d02396..cf49b7fe12 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index 4601234669..81589459c4 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs index bc3daca16f..786353bb00 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; 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 b957ade952..3ac1491946 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 @@ -1,7 +1,6 @@  - diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs index f009c10a9c..ac39b91f00 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 7774a7da09..9f5d007114 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index ab61b14ac4..835f7c2d27 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 021d7a7efe..86f35c8cee 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 80b9436b2c..f832d99807 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Catch.Mods; diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs index 8bf53e53e3..e79da667da 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponent.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch @@ -14,6 +16,6 @@ namespace osu.Game.Rulesets.Catch protected override string RulesetPrefix => "catch"; // todo: use CatchRuleset.SHORT_NAME; - protected override string ComponentName => Component.ToString().ToLower(); + protected override string ComponentName => Component.ToString().ToLowerInvariant(); } } diff --git a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs index 371e901c69..7587de5803 100644 --- a/osu.Game.Rulesets.Catch/CatchSkinComponents.cs +++ b/osu.Game.Rulesets.Catch/CatchSkinComponents.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch { public enum CatchSkinComponents diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs index 8e069d7d16..2d01153f98 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch.Difficulty @@ -29,9 +30,9 @@ namespace osu.Game.Rulesets.Catch.Difficulty yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values) + public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values); + base.FromDatabaseAttributes(values, onlineInfo); StarRating = values[ATTRIB_ID_AIM]; ApproachRate = values[ATTRIB_ID_APPROACH_RATE]; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 0054047573..b64d860417 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -49,6 +51,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty { CatchHitObject lastObject = null; + List objects = new List(); + // In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream. foreach (var hitObject in beatmap.HitObjects .SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects.AsEnumerable() : new[] { obj }) @@ -60,10 +64,12 @@ namespace osu.Game.Rulesets.Catch.Difficulty continue; if (lastObject != null) - yield return new CatchDifficultyHitObject(hitObject, lastObject, clockRate, halfCatcherWidth); + objects.Add(new CatchDifficultyHitObject(hitObject, lastObject, clockRate, halfCatcherWidth, objects, objects.Count)); lastObject = hitObject; } + + return objects; } protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs index 1335fc2d23..ccdfd30200 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch.Difficulty diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index b30b85be2d..2a07b8019e 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs index b22ec93b43..c44480776f 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; +using System.Collections.Generic; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Objects; @@ -24,8 +27,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing /// public readonly double StrainTime; - public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth) - : base(hitObject, lastObject, clockRate) + public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth, List objects, int index) + : base(hitObject, lastObject, clockRate, objects, index) { // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. float scalingFactor = normalized_hitobject_radius / halfCatcherWidth; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index cfb3fe40be..827c28f7de 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs index 31075db7d1..e64a51f03a 100644 --- a/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/BananaShowerCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs index 039008f901..86fdf09a72 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Input.Events; using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs index 9132b1a9e8..7e4aca180c 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Edit.Blueprints diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs index 5a32d241ad..8a1ced7eea 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs index 7e566c810c..e7c04cd132 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/CatchSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs index e038562b4b..44d14ec330 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs index 0c03068e26..86006a99fc 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/FruitOutline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs index cf916b27a4..431ba331ac 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/NestedOutlineContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs index 511aec5e5d..27df064be4 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/PlacementEditablePath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Catch.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs index cfaca2f9a4..3a62b07816 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/ScrollingPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs index b4c353313c..4576e9f8ee 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/SelectionEditablePath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs index 65dfce0493..2586a81ef5 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/TimeSpanOutline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs index 5ef86b6074..236d27753a 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexState.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexState.cs index 3f240c7944..1ddffc10a5 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexState.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/VertexState.cs @@ -3,8 +3,6 @@ using osu.Game.Rulesets.Catch.Objects; -#nullable enable - namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components { /// diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs index e169e3b75c..686840ae55 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs index 150297badb..b5a25dbf62 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/FruitSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Edit.Blueprints.Components; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs index b5dcb62543..fcdd055b56 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs index 12054a1d16..fc2b5e08fe 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs b/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs index c7a41a4e22..6570a19a92 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBeatmapVerifier.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Catch.Edit.Checks; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs index 7f2782a474..58f493b4b8 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Edit.Blueprints; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs index 9a78c7ff86..718c76abfc 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchDistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs index 046ba0ebce..b9a875fe8a 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchEditorPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.UI; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 6f59b3e543..f31dc3ef9c 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -133,15 +135,15 @@ namespace osu.Game.Rulesets.Catch.Edit { switch (BlueprintContainer.CurrentTool) { - case SelectTool _: + case SelectTool: if (EditorBeatmap.SelectedHitObjects.Count == 0) return null; double minTime = EditorBeatmap.SelectedHitObjects.Min(hitObject => hitObject.StartTime); return getLastSnappableHitObject(minTime); - case FruitCompositionTool _: - case JuiceStreamCompositionTool _: + case FruitCompositionTool: + case JuiceStreamCompositionTool: if (!CursorInPlacementArea) return null; diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs index b059926668..889d3909bd 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectUtils.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Catch.Objects; @@ -40,10 +42,10 @@ namespace osu.Game.Rulesets.Catch.Edit case Droplet droplet: return droplet is TinyDroplet ? PositionRange.EMPTY : new PositionRange(droplet.OriginalX); - case JuiceStream _: + case JuiceStream: return GetPositionRange(hitObject.NestedHitObjects); - case BananaShower _: + case BananaShower: // A banana shower occupies the whole screen width. return new PositionRange(0, CatchPlayfield.WIDTH); diff --git a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs index dd5835b4ed..5aac521d0b 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchSelectionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -129,7 +131,7 @@ namespace osu.Game.Rulesets.Catch.Edit { switch (hitObject) { - case BananaShower _: + case BananaShower: return false; case JuiceStream juiceStream: diff --git a/osu.Game.Rulesets.Catch/Edit/Checks/CheckBananaShowerGap.cs b/osu.Game.Rulesets.Catch/Edit/Checks/CheckBananaShowerGap.cs index 4b2933c0e1..00fd74c9a8 100644 --- a/osu.Game.Rulesets.Catch/Edit/Checks/CheckBananaShowerGap.cs +++ b/osu.Game.Rulesets.Catch/Edit/Checks/CheckBananaShowerGap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs b/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs index 9a7528d90c..c81afafae5 100644 --- a/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs +++ b/osu.Game.Rulesets.Catch/Edit/DrawableCatchEditorRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.UI; diff --git a/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs index f776fe39c1..5c13692b51 100644 --- a/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/FruitCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs b/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs index cb66e2952e..85cf89f700 100644 --- a/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs +++ b/osu.Game.Rulesets.Catch/Edit/JuiceStreamCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Catch/Edit/PositionRange.cs b/osu.Game.Rulesets.Catch/Edit/PositionRange.cs index e61603e5e6..482295a357 100644 --- a/osu.Game.Rulesets.Catch/Edit/PositionRange.cs +++ b/osu.Game.Rulesets.Catch/Edit/PositionRange.cs @@ -3,8 +3,6 @@ using System; -#nullable enable - namespace osu.Game.Rulesets.Catch.Edit { /// diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index b919102215..15f6e4a64d 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 8fd7b93e4c..90aa6f41a1 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Judgements diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index ccafe0abc4..e5d6429660 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs index c09355d59c..6cc79f9619 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgementResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index d957d4171b..c9052e3c39 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Judgements diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 50e48101d3..c5ca595fd6 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Replays; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs index 7eda6b37d3..10a0809e05 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModClassic.cs b/osu.Game.Rulesets.Catch/Mods/CatchModClassic.cs index 9624e84018..904656993e 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModClassic.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModClassic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs index cae19e9468..8d4b57c244 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index e59a0a0431..6927d7953f 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs index 178909387f..c58ce9b07d 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs @@ -1,12 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods { public class CatchModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs b/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs index 16ef56d845..bea9b094fa 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs index d576ea3df8..d166646eaf 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; @@ -14,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModFlashlight : ModFlashlight { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; [SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")] public override BindableFloat SizeMultiplier { get; } = new BindableFloat diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs index 63203dd57c..1fe892c9b5 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs index ce06b841aa..0c7886be10 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs index 68b6ce96a3..39b992b3f5 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; @@ -9,7 +11,7 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModHardRock : ModHardRock, IApplicableToBeatmapProcessor { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; public void ApplyToBeatmapProcessor(IBeatmapProcessor beatmapProcessor) { diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs index 4b6f79df88..b4fbc9d566 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects; @@ -15,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Mods public class CatchModHidden : ModHidden, IApplicableToDrawableRuleset { public override string Description => @"Play with fading fruits."; - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; private const double fade_out_offset_multiplier = 0.6; private const double fade_out_duration_multiplier = 0.44; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs index a97e940a64..89fc40356d 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMirror.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs b/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs index 6d2565440a..6b28d1a127 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModMuted.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs index c07087efaf..1fd2227eb7 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Mods; @@ -8,6 +10,6 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModNightcore : ModNightcore { - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs index 3c02646e99..89e7e4bcd6 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs index a24a6227fe..385d4c50c0 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNoScope.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs index fb92399102..0a74ee4fbb 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index d0a94767d1..f4d6fb9ab3 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs b/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs index 68e01391ce..d98829137c 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Mods diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index e5a36d08db..af03c9acab 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index b45f95a8e6..e5541e49c1 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Game.Rulesets.Judgements; 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 ee10cf9711..6e01c44e1f 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -17,7 +19,9 @@ namespace osu.Game.Rulesets.Catch.Objects { public const float OBJECT_RADIUS = 64; - public readonly Bindable OriginalXBindable = new Bindable(); + private HitObjectProperty originalX; + + public Bindable OriginalXBindable => originalX.Bindable; /// /// The horizontal position of the hit object between 0 and . @@ -29,18 +33,20 @@ namespace osu.Game.Rulesets.Catch.Objects [JsonIgnore] public float X { - set => OriginalXBindable.Value = value; + set => originalX.Value = value; } - public readonly Bindable XOffsetBindable = new Bindable(); + private HitObjectProperty xOffset; + + public Bindable XOffsetBindable => xOffset.Bindable; /// /// A random offset applied to the horizontal position, set by the beatmap processing. /// public float XOffset { - get => XOffsetBindable.Value; - set => XOffsetBindable.Value = value; + get => xOffset.Value; + set => xOffset.Value = value; } /// @@ -52,8 +58,8 @@ namespace osu.Game.Rulesets.Catch.Objects /// public float OriginalX { - get => OriginalXBindable.Value; - set => OriginalXBindable.Value = value; + get => originalX.Value; + set => originalX.Value = value; } /// @@ -67,59 +73,71 @@ namespace osu.Game.Rulesets.Catch.Objects public double TimePreempt { get; set; } = 1000; - public readonly Bindable IndexInBeatmapBindable = new Bindable(); + private HitObjectProperty indexInBeatmap; + + public Bindable IndexInBeatmapBindable => indexInBeatmap.Bindable; public int IndexInBeatmap { - get => IndexInBeatmapBindable.Value; - set => IndexInBeatmapBindable.Value = value; + get => indexInBeatmap.Value; + set => indexInBeatmap.Value = value; } public virtual bool NewCombo { get; set; } public int ComboOffset { get; set; } - public Bindable IndexInCurrentComboBindable { get; } = new Bindable(); + private HitObjectProperty indexInCurrentCombo; + + public Bindable IndexInCurrentComboBindable => indexInCurrentCombo.Bindable; public int IndexInCurrentCombo { - get => IndexInCurrentComboBindable.Value; - set => IndexInCurrentComboBindable.Value = value; + get => indexInCurrentCombo.Value; + set => indexInCurrentCombo.Value = value; } - public Bindable ComboIndexBindable { get; } = new Bindable(); + private HitObjectProperty comboIndex; + + public Bindable ComboIndexBindable => comboIndex.Bindable; public int ComboIndex { - get => ComboIndexBindable.Value; - set => ComboIndexBindable.Value = value; + get => comboIndex.Value; + set => comboIndex.Value = value; } - public Bindable ComboIndexWithOffsetsBindable { get; } = new Bindable(); + private HitObjectProperty comboIndexWithOffsets; + + public Bindable ComboIndexWithOffsetsBindable => comboIndexWithOffsets.Bindable; public int ComboIndexWithOffsets { - get => ComboIndexWithOffsetsBindable.Value; - set => ComboIndexWithOffsetsBindable.Value = value; + get => comboIndexWithOffsets.Value; + set => comboIndexWithOffsets.Value = value; } - public Bindable LastInComboBindable { get; } = new Bindable(); + private HitObjectProperty lastInCombo; + + public Bindable LastInComboBindable => lastInCombo.Bindable; /// /// The next fruit starts a new combo. Used for explodey. /// public virtual bool LastInCombo { - get => LastInComboBindable.Value; - set => LastInComboBindable.Value = value; + get => lastInCombo.Value; + set => lastInCombo.Value = value; } - public readonly Bindable ScaleBindable = new Bindable(1); + private HitObjectProperty scale = new HitObjectProperty(1); + + public Bindable ScaleBindable => scale.Bindable; public float Scale { - get => ScaleBindable.Value; - set => ScaleBindable.Value = value; + get => scale.Value; + set => scale.Value = value; } /// diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs index 8a91f82437..31a27b6047 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Skinning.Default; namespace osu.Game.Rulesets.Catch.Objects.Drawables diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs index 4a3397feff..6d5dd0ed25 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Skinning.Default; namespace osu.Game.Rulesets.Catch.Objects.Drawables diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs index 7c88090a20..89757748ab 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Skinning.Default; namespace osu.Game.Rulesets.Catch.Objects.Drawables diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index d8bce9bb6d..fd0ffbd032 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index c1b41a7afc..b46a452bd0 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs index 9b2f95e221..f061f206ff 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBananaShower.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 0c065948ef..23264edf3d 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index 2dce9507a5..d367ad0a00 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 0af7ee6c30..ce4c7e5aff 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs index a496a35842..12a44c909e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableJuiceStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index 27cd7ed2bc..5de372852b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs index 8f5a04dfda..8c48b62c7e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableTinyDroplet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; namespace osu.Game.Rulesets.Catch.Objects.Drawables diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index be0ee2821e..93c80b09db 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index 9c1004a04b..ecaa4bfaf4 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 4818fe2cad..bdf8b3f28d 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs b/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs index 7ec7050245..e5d013dafc 100644 --- a/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs +++ b/osu.Game.Rulesets.Catch/Objects/FruitVisualRepresentation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.Objects { public enum FruitVisualRepresentation diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index d34452cdbb..311e15116e 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStreamPath.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStreamPath.cs index 61f4c580ae..0633151ddd 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStreamPath.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStreamPath.cs @@ -9,8 +9,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; -#nullable enable - namespace osu.Game.Rulesets.Catch.Objects { /// diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStreamPathVertex.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStreamPathVertex.cs index afef2e637f..96ed82bca3 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStreamPathVertex.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStreamPathVertex.cs @@ -3,8 +3,6 @@ using System; -#nullable enable - namespace osu.Game.Rulesets.Catch.Objects { /// diff --git a/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs index 4001a4ea76..c9bc9ca2ac 100644 --- a/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/PalpableCatchHitObject.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using osu.Framework.Bindables; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using osuTK.Graphics; @@ -22,12 +25,14 @@ namespace osu.Game.Rulesets.Catch.Objects /// public float DistanceToHyperDash { get; set; } - public readonly Bindable HyperDashBindable = new Bindable(); + private HitObjectProperty hyperDash; + + public Bindable HyperDashBindable => hyperDash.Bindable; /// /// Whether this fruit can initiate a hyperdash. /// - public bool HyperDash => HyperDashBindable.Value; + public bool HyperDash => hyperDash.Value; private CatchHitObject hyperDashTarget; diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 1bf160b5a6..6bd5f0ac2a 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 26f20b223a..6c7f0478a7 100644 --- a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index 1a80adb584..e30e535e9b 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Replays { } - public CatchReplayFrame(double time, float? position = null, bool dashing = false, CatchReplayFrame lastFrame = null) + public CatchReplayFrame(double time, float? position = null, bool dashing = false, CatchReplayFrame? lastFrame = null) : base(time) { Position = position ?? -1; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Replays } } - public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) + public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame? lastFrame = null) { Position = currentFrame.Position.X; Dashing = currentFrame.ButtonState == ReplayButtonState.Left1; diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 51b1ccaaba..ba3d529212 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Scoring diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchSkinColour.cs b/osu.Game.Rulesets.Catch/Skinning/CatchSkinColour.cs index 4506111498..d038ccb31c 100644 --- a/osu.Game.Rulesets.Catch/Skinning/CatchSkinColour.cs +++ b/osu.Game.Rulesets.Catch/Skinning/CatchSkinColour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.Skinning { public enum CatchSkinColour diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs b/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs index ea8d742b1a..65d6acd88d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs +++ b/osu.Game.Rulesets.Catch/Skinning/CatchSkinConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.Skinning { public enum CatchSkinConfiguration diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs index 8da18a668a..27252594af 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs index ee1cc68f7d..ffeed80615 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BananaPulpFormation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; namespace osu.Game.Rulesets.Catch.Skinning.Default diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs index 8d8ee49af7..60a13bee59 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/BorderPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index 2db3bae034..6cc5220699 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs index e423f21b98..4148fed11c 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultCatcher.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs index f6b3c3d665..7ea99b3ed9 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DefaultHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs index 8b1052dfe2..6b7f25eed1 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/DropletPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index cfe0df0c97..8fb5c8f84a 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs index f097361d2a..db51195f11 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPulpFormation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Catch.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs index c8895f32f4..42b0b85495 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/HyperBorderPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.UI; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs index 53a487b97f..29cb339625 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/HyperDropletBorderPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.Skinning.Default { public class HyperDropletBorderPiece : HyperBorderPiece diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs index 96c6233b41..8ea54617d9 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/Pulp.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs index 8753aa4077..aa5ef5fb66 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/PulpFormation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs index 04b522b404..c5e5e59dd2 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/CatchLegacySkinTransformer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs index 5bd5b0d4bb..9f64a2129e 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyBananaPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Textures; namespace osu.Game.Rulesets.Catch.Skinning.Legacy diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs index b4d29988d9..b2dd29841b 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Catch.UI; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs index f78724615a..5a5288105d 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchHitObjectPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs index 9df87c92ea..93d79f00d3 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherNew.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs index 3e679171b2..736e9cfddf 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatcherOld.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs index 2c5cbe1e41..f99cedab3f 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyDropletPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Textures; using osuTK; diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs index f002bab219..125a96a446 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch.Skinning.Legacy diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs index c262b0a4ac..0630de9156 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs index ad344ff2dd..e9c289e46a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchComboDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index df32d917ce..dad22fbe69 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs index efc1b24ed5..82b85f54e4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfieldAdjustmentContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs b/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs index a7879846df..c118c14e3f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchReplayRecorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 04708c8796..efc841dfac 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; @@ -387,13 +389,13 @@ namespace osu.Game.Rulesets.Catch.UI { switch (source) { - case Fruit _: + case Fruit: return caughtFruitPool.Get(); - case Banana _: + case Banana: return caughtBananaPool.Get(); - case Droplet _: + case Droplet: return caughtDropletPool.Get(); default: diff --git a/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs b/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs index 566e9d1911..82591eb47f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherAnimationState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.UI { public enum CatcherAnimationState diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 37002d1051..7a29ba9801 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -118,10 +120,10 @@ namespace osu.Game.Rulesets.Catch.UI lastHyperDashState = Catcher.HyperDashing; } - public void SetCatcherPosition(float X) + public void SetCatcherPosition(float x) { float lastPosition = Catcher.X; - float newPosition = Math.Clamp(X, 0, CatchPlayfield.WIDTH); + float newPosition = Math.Clamp(x, 0, CatchPlayfield.WIDTH); Catcher.X = newPosition; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs index 6d2ac7e488..afaa037574 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Rulesets.Objects.Pooling; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs index 0a5281cd10..02bc5be863 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.UI { public enum CatcherTrailAnimation diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index 0f2530e56a..6ab6a59293 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs index 3a40ab26cc..78d6979b78 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Performance; using osuTK; diff --git a/osu.Game.Rulesets.Catch/UI/Direction.cs b/osu.Game.Rulesets.Catch/UI/Direction.cs index 65f064b7fb..15e4aed86b 100644 --- a/osu.Game.Rulesets.Catch/UI/Direction.cs +++ b/osu.Game.Rulesets.Catch/UI/Direction.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Catch.UI { public enum Direction diff --git a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index a8ec9f1d2f..b6cea92173 100644 --- a/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Input; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs b/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs index b44b0caae4..1e4da479d2 100644 --- a/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/DroppedObjectContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Catch.Objects.Drawables; diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs index 955b1e6edb..1ea188d463 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosion.cs @@ -6,8 +6,6 @@ using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Skinning; -#nullable enable - namespace osu.Game.Rulesets.Catch.UI { public class HitExplosion : PoolableDrawableWithLifetime diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs index 6df13e52ef..2004c971ad 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Objects.Pooling; diff --git a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs index 88871c77f6..f265da149a 100644 --- a/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs +++ b/osu.Game.Rulesets.Catch/UI/HitExplosionEntry.cs @@ -6,8 +6,6 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; using osuTK.Graphics; -#nullable enable - namespace osu.Game.Rulesets.Catch.UI { public class HitExplosionEntry : LifetimeEntry diff --git a/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs b/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs index cfb6879067..5d027edbaa 100644 --- a/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/UI/ICatchComboCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs b/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs index c744c00d9a..4a9d7e8ac0 100644 --- a/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs +++ b/osu.Game.Rulesets.Catch/UI/IHitExplosion.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.Rulesets.Catch.UI { /// diff --git a/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs b/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs index 8d707a4beb..25bbc814bf 100644 --- a/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs +++ b/osu.Game.Rulesets.Catch/UI/SkinnableCatcher.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs index 518071fd49..789fc9e22d 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs index 9cd1e47023..a528634f3b 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs +++ b/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Foundation; using osu.Framework.iOS; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs index ec3db17e97..2d1015387a 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.iOS; using UIKit; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs index 94f385bbf1..6e6e83f9cf 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaPlacementBlueprintTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 124e1a35f9..679a15e8cb 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs index 5300747633..99850f33b8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs index 87c74a12cf..ddec1f3432 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs index 9953b8e3c0..b70d4e4fa6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs index 6130a80bb4..ec96205067 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs index 746bdae02e..15b38b39ba 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs index 9788dfe844..4ad27348fc 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs index a162c5ec44..28c002eef8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNotePlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs index 3586eecc44..f61d416e3b 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 837474ad9e..ef6dca620a 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs index 9c690f360a..51f35d3c3d 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapSampleConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs index 66fe6d8cc5..e53deb5269 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaColumnTypeTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Mania.Beatmaps; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs index a5bd126782..9e4db1f1c9 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index 9049bb3a82..eb380c07a6 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs index a28c188051..9dee861e66 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; @@ -21,10 +23,8 @@ namespace osu.Game.Rulesets.Mania.Tests new object[] { LegacyMods.SuddenDeath, new[] { typeof(ManiaModSuddenDeath) } }, new object[] { LegacyMods.DoubleTime, new[] { typeof(ManiaModDoubleTime) } }, new object[] { LegacyMods.HalfTime, new[] { typeof(ManiaModHalfTime) } }, - new object[] { LegacyMods.Nightcore, new[] { typeof(ManiaModNightcore) } }, new object[] { LegacyMods.Flashlight, new[] { typeof(ManiaModFlashlight) } }, new object[] { LegacyMods.Autoplay, new[] { typeof(ManiaModAutoplay) } }, - new object[] { LegacyMods.Perfect, new[] { typeof(ManiaModPerfect) } }, new object[] { LegacyMods.Key4, new[] { typeof(ManiaModKey4) } }, new object[] { LegacyMods.Key5, new[] { typeof(ManiaModKey5) } }, new object[] { LegacyMods.Key6, new[] { typeof(ManiaModKey6) } }, @@ -32,7 +32,6 @@ namespace osu.Game.Rulesets.Mania.Tests new object[] { LegacyMods.Key8, new[] { typeof(ManiaModKey8) } }, new object[] { LegacyMods.FadeIn, new[] { typeof(ManiaModFadeIn) } }, new object[] { LegacyMods.Random, new[] { typeof(ManiaModRandom) } }, - new object[] { LegacyMods.Cinema, new[] { typeof(ManiaModCinema) } }, new object[] { LegacyMods.Key9, new[] { typeof(ManiaModKey9) } }, new object[] { LegacyMods.KeyCoop, new[] { typeof(ManiaModDualStages) } }, new object[] { LegacyMods.Key1, new[] { typeof(ManiaModKey1) } }, @@ -43,12 +42,18 @@ namespace osu.Game.Rulesets.Mania.Tests }; [TestCaseSource(nameof(mania_mod_mapping))] + [TestCase(LegacyMods.Cinema, new[] { typeof(ManiaModCinema) })] [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(ManiaModCinema) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(ManiaModNightcore) })] [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(ManiaModPerfect) })] [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(ManiaModPerfect) })] public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods); [TestCaseSource(nameof(mania_mod_mapping))] + [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(ManiaModCinema) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(ManiaModPerfect) })] public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods); protected override Ruleset CreateRuleset() => new ManiaRuleset(); diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs index 40bb83aece..b64006316e 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Replays; diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs index 60363aaeef..538c8b13d1 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModConstantSpeed.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs index 7970d5b594..4222be0359 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModHoldOff.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs index f2cc254e38..4c97f65b07 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModInvert.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs index 2e3b21aed7..9612543483 100644 --- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs +++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs index 8ba58e3af3..1a3513d46c 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs index 68cf3b67df..fd82041ad8 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index ddfd057cd8..9f235689b4 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs index 106b2d188d..cd26e2a9de 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs index 8034341d15..1fb9d448a9 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs index d033676ec7..8b12d37fe9 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Extensions; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs index 9e6e0a7776..744721f1a3 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs index e88ff8e2ac..0947ddfeb0 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneKeyArea.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneKeyArea.cs index 7564bd84ad..bbbd7edb7b 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneKeyArea.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneKeyArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs index bc3bdf0bcb..85995e6994 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs index c7dc5fc8b5..62dadbc3dd 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs index 7804261906..f3f1b9416f 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs index 410a43fc73..687b3a747d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Beatmaps; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs index 27e97152bc..6cbc172755 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageForeground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Beatmaps; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index cffec3dfd5..21ec85bbe6 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs index d9b1ad22fa..2922d18713 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs index 92c95b8fde..223f8dae44 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableManiaHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index f973cb5ed3..8f776ff507 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs index ea57e51d1c..00f0fcefd9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Reflection; using NUnit.Framework; using osu.Framework.IO.Stores; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs index a399b90585..9abedc22f9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 706268e478..df831d8c9f 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs index 89e13acad6..a563dc3106 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs index 8698ba3abd..64e7eafb1b 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 7376a90f17..cf8947c1ed 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs index 4c688520ef..e84d02775a 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; 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 d3b4b378c0..d07df75864 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 @@ -1,7 +1,6 @@  - diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ColumnType.cs b/osu.Game.Rulesets.Mania/Beatmaps/ColumnType.cs index 8f904530bc..0114987e3c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ColumnType.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ColumnType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Beatmaps { public enum ColumnType diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index 0058f6f884..4879ce6748 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 207c6907c8..90cd7f57b5 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mania.Objects; using System; using System.Linq; @@ -171,7 +173,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps switch (original) { - case IHasDistance _: + case IHasDistance: { var generator = new DistanceObjectPatternGenerator(Random, original, beatmap, lastPattern, originalBeatmap); conversion = generator; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index dafe65f415..2bdd0e16ad 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 2265d3d347..630fdf7ae2 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 41d4c9322b..912cac4fe4 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index d5689c047a..308238d87a 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs index e4a28167ec..bf54dc3179 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs index 828f2ec393..4b3902657f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 71b3f6ecf2..b2e89c3410 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs index 3052fc7d34..54e2d4686f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index 8e09a01469..35ad21442e 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Configuration.Tracking; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs index c35a3dcdc2..d259c2af8e 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Mania.Difficulty @@ -18,12 +19,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty [JsonProperty("great_hit_window")] public double GreatHitWindow { get; set; } - /// - /// The score multiplier applied via score-reducing mods. - /// - [JsonProperty("score_multiplier")] - public double ScoreMultiplier { get; set; } - public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() { foreach (var v in base.ToDatabaseAttributes()) @@ -32,17 +27,15 @@ namespace osu.Game.Rulesets.Mania.Difficulty yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); yield return (ATTRIB_ID_DIFFICULTY, StarRating); yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); - yield return (ATTRIB_ID_SCORE_MULTIPLIER, ScoreMultiplier); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values) + public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values); + base.FromDatabaseAttributes(values, onlineInfo); MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; StarRating = values[ATTRIB_ID_DIFFICULTY]; GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; - ScoreMultiplier = values[ATTRIB_ID_SCORE_MULTIPLIER]; } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 88f51bf961..178094476f 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -51,7 +53,6 @@ namespace osu.Game.Rulesets.Mania.Difficulty // In osu-stable mania, rate-adjustment mods don't affect the hit window. // This is done the way it is to introduce fractional differences in order to match osu-stable for the time being. GreatHitWindow = Math.Ceiling((int)(getHitWindow300(mods) * clockRate) / clockRate), - ScoreMultiplier = getScoreMultiplier(mods), MaxCombo = beatmap.HitObjects.Sum(maxComboForObject) }; } @@ -70,8 +71,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty LegacySortHelper.Sort(sortedObjects, Comparer.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime))); + List objects = new List(); + for (int i = 1; i < sortedObjects.Length; i++) - yield return new ManiaDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate); + objects.Add(new ManiaDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate, objects, objects.Count)); + + return objects; } // Sorting is done in CreateDifficultyHitObjects, since the full list of hitobjects is required. @@ -141,32 +146,5 @@ namespace osu.Game.Rulesets.Mania.Difficulty return value; } } - - private double getScoreMultiplier(Mod[] mods) - { - double scoreMultiplier = 1; - - foreach (var m in mods) - { - switch (m) - { - case ManiaModNoFail _: - case ManiaModEasy _: - case ManiaModHalfTime _: - scoreMultiplier *= 0.5; - break; - } - } - - var maniaBeatmap = (ManiaBeatmap)Beatmap; - int diff = maniaBeatmap.TotalColumns - maniaBeatmap.OriginalTotalColumns; - - if (diff > 0) - scoreMultiplier *= 0.9; - else if (diff < 0) - scoreMultiplier *= 0.9 + 0.04 * diff; - - return scoreMultiplier; - } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs index 17c864a268..01474e6e00 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; @@ -12,19 +14,12 @@ namespace osu.Game.Rulesets.Mania.Difficulty [JsonProperty("difficulty")] public double Difficulty { get; set; } - [JsonProperty("accuracy")] - public double Accuracy { get; set; } - - [JsonProperty("scaled_score")] - public double ScaledScore { get; set; } - public override IEnumerable GetAttributesForDisplay() { foreach (var attribute in base.GetAttributesForDisplay()) yield return attribute; yield return new PerformanceDisplayAttribute(nameof(Difficulty), "Difficulty", Difficulty); - yield return new PerformanceDisplayAttribute(nameof(Accuracy), "Accuracy", Accuracy); } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index b347cc9ae2..a925e7c0ac 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -13,15 +15,13 @@ namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaPerformanceCalculator : PerformanceCalculator { - // Score after being scaled by non-difficulty-increasing mods - private double scaledScore; - private int countPerfect; private int countGreat; private int countGood; private int countOk; private int countMeh; private int countMiss; + private double scoreAccuracy; public ManiaPerformanceCalculator() : base(new ManiaRuleset()) @@ -32,82 +32,47 @@ namespace osu.Game.Rulesets.Mania.Difficulty { var maniaAttributes = (ManiaDifficultyAttributes)attributes; - scaledScore = score.TotalScore; countPerfect = score.Statistics.GetValueOrDefault(HitResult.Perfect); countGreat = score.Statistics.GetValueOrDefault(HitResult.Great); countGood = score.Statistics.GetValueOrDefault(HitResult.Good); countOk = score.Statistics.GetValueOrDefault(HitResult.Ok); countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh); countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss); - - if (maniaAttributes.ScoreMultiplier > 0) - { - // Scale score up, so it's comparable to other keymods - scaledScore *= 1.0 / maniaAttributes.ScoreMultiplier; - } + scoreAccuracy = customAccuracy; // Arbitrary initial value for scaling pp in order to standardize distributions across game modes. // The specific number has no intrinsic meaning and can be adjusted as needed. - double multiplier = 0.8; + double multiplier = 8.0; if (score.Mods.Any(m => m is ModNoFail)) - multiplier *= 0.9; + multiplier *= 0.75; if (score.Mods.Any(m => m is ModEasy)) multiplier *= 0.5; double difficultyValue = computeDifficultyValue(maniaAttributes); - double accValue = computeAccuracyValue(difficultyValue, maniaAttributes); - double totalValue = - Math.Pow( - Math.Pow(difficultyValue, 1.1) + - Math.Pow(accValue, 1.1), 1.0 / 1.1 - ) * multiplier; + double totalValue = difficultyValue * multiplier; return new ManiaPerformanceAttributes { Difficulty = difficultyValue, - Accuracy = accValue, - ScaledScore = scaledScore, Total = totalValue }; } private double computeDifficultyValue(ManiaDifficultyAttributes attributes) { - double difficultyValue = Math.Pow(5 * Math.Max(1, attributes.StarRating / 0.2) - 4.0, 2.2) / 135.0; - - difficultyValue *= 1.0 + 0.1 * Math.Min(1.0, totalHits / 1500.0); - - if (scaledScore <= 500000) - difficultyValue = 0; - else if (scaledScore <= 600000) - difficultyValue *= (scaledScore - 500000) / 100000 * 0.3; - else if (scaledScore <= 700000) - difficultyValue *= 0.3 + (scaledScore - 600000) / 100000 * 0.25; - else if (scaledScore <= 800000) - difficultyValue *= 0.55 + (scaledScore - 700000) / 100000 * 0.20; - else if (scaledScore <= 900000) - difficultyValue *= 0.75 + (scaledScore - 800000) / 100000 * 0.15; - else - difficultyValue *= 0.90 + (scaledScore - 900000) / 100000 * 0.1; + double difficultyValue = Math.Pow(Math.Max(attributes.StarRating - 0.15, 0.05), 2.2) // Star rating to pp curve + * Math.Max(0, 5 * scoreAccuracy - 4) // From 80% accuracy, 1/20th of total pp is awarded per additional 1% accuracy + * (1 + 0.1 * Math.Min(1, totalHits / 1500)); // Length bonus, capped at 1500 notes return difficultyValue; } - private double computeAccuracyValue(double difficultyValue, ManiaDifficultyAttributes attributes) - { - if (attributes.GreatHitWindow <= 0) - return 0; - - // 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) - * difficultyValue - * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); - - return accuracyValue; - } - private double totalHits => countPerfect + countOk + countGreat + countGood + countMeh + countMiss; + + /// + /// Accuracy used to weight judgements independently from the score's actual accuracy. + /// + private double customAccuracy => (countPerfect * 320 + countGreat * 300 + countGood * 200 + countOk * 100 + countMeh * 50) / (totalHits * 320); } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs index 29ba934e9f..df95654319 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; @@ -11,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Preprocessing { public new ManiaHitObject BaseObject => (ManiaHitObject)base.BaseObject; - public ManiaDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) - : base(hitObject, lastObject, clockRate) + public ManiaDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, List objects, int index) + : base(hitObject, lastObject, clockRate, objects, index) { } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs index 31550a8105..c2e532430c 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Utils; using osu.Game.Rulesets.Difficulty.Preprocessing; @@ -84,9 +86,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills return individualStrain + overallStrain - CurrentStrain; } - protected override double CalculateInitialStrain(double offset) - => applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base) - + applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base); + protected override double CalculateInitialStrain(double offset, DifficultyHitObject current) + => applyDecay(individualStrain, offset - current.Previous(0).StartTime, individual_decay_base) + + applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base); private double applyDecay(double value, double deltaTime, double decayBase) => value * Math.Pow(decayBase, deltaTime / 1000); diff --git a/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs b/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs index 8d39e08b26..262247e244 100644 --- a/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs +++ b/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs index f5067ea366..52995b73f4 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; 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 9c9273de3a..23475ef924 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 093a8da24f..7c720b30aa 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; 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 35889aea0c..f76f170af0 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 7a99565e8a..7c7c802111 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 955336db57..5aa3b44f0d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 3db89c8ae6..e3cb830b80 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index e7a03905d2..929fdc29e0 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs index b0af8c503b..a3a9591964 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osuTK; diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs index a5f10ed436..960a08eeeb 100644 --- a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 1aa20f4737..b0019d8b6e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index c5a109a6d1..ad75afff8e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs index 186d50716e..6683ab6bdc 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index c389e1bced..3585fd4e8c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9fe1eb7932..7b9742a706 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs index 9f54152596..179f920c2f 100644 --- a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs index a206aafb8a..b602a67baa 100644 --- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index ee6cbbc828..4b94198c4d 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Judgements diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index d28b7bdf58..32f9689d7e 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 14ca27a11a..e8e90d198a 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index bd6a67bf67..4723416c30 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Mods; @@ -144,56 +146,56 @@ namespace osu.Game.Rulesets.Mania { switch (mod) { - case ManiaModKey1 _: + case ManiaModKey1: value |= LegacyMods.Key1; break; - case ManiaModKey2 _: + case ManiaModKey2: value |= LegacyMods.Key2; break; - case ManiaModKey3 _: + case ManiaModKey3: value |= LegacyMods.Key3; break; - case ManiaModKey4 _: + case ManiaModKey4: value |= LegacyMods.Key4; break; - case ManiaModKey5 _: + case ManiaModKey5: value |= LegacyMods.Key5; break; - case ManiaModKey6 _: + case ManiaModKey6: value |= LegacyMods.Key6; break; - case ManiaModKey7 _: + case ManiaModKey7: value |= LegacyMods.Key7; break; - case ManiaModKey8 _: + case ManiaModKey8: value |= LegacyMods.Key8; break; - case ManiaModKey9 _: + case ManiaModKey9: value |= LegacyMods.Key9; break; - case ManiaModDualStages _: + case ManiaModDualStages: value |= LegacyMods.KeyCoop; break; - case ManiaModFadeIn _: + case ManiaModFadeIn: value |= LegacyMods.FadeIn; value &= ~LegacyMods.Hidden; // this is toggled on in the base call due to inheritance, but we don't want that. break; - case ManiaModMirror _: + case ManiaModMirror: value |= LegacyMods.Mirror; break; - case ManiaModRandom _: + case ManiaModRandom: value |= LegacyMods.Random; break; } diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index bd3b8c3b10..43d4aa77a2 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs b/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs index 9aebf51576..21b362df00 100644 --- a/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs +++ b/osu.Game.Rulesets.Mania/ManiaSkinComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; using osu.Game.Skinning; @@ -28,7 +30,7 @@ namespace osu.Game.Rulesets.Mania protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME; - protected override string ComponentName => Component.ToString().ToLower(); + protected override string ComponentName => Component.ToString().ToLowerInvariant(); } public enum ManiaSkinComponents diff --git a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs index 5c595323c3..1a67117c03 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/LegacySortHelper.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics.Contracts; diff --git a/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs b/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs index 410386c9d5..0bae893810 100644 --- a/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index 050b302bd8..8f8b7cb091 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index d444c9b634..f9c51bf6a2 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs index f0db742eac..8d54923e7b 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModClassic.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModClassic.cs index 073dda9de8..603d096ed7 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModClassic.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModClassic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModConstantSpeed.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModConstantSpeed.cs index 614ef76a3b..20dfc14f09 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModConstantSpeed.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModConstantSpeed.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs index bec0a6a1d3..b166f3ebc3 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs index 0817f8f9fc..d053e64315 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDifficultyAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs index a302f95966..66627e6ed3 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs index c78bf72979..f25a77278b 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs index 4093aeb2a7..ff236d33bf 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs index f80c9e1f7c..ddbd7c5d6a 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs index 8ef5bfd94c..58005df561 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs index 014954dd60..87c81c2866 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs index d9de06a811..380edca515 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index e3ac624a6e..698555ddc4 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHoldOff.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHoldOff.cs index a65938184c..8c4fd0a8fc 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHoldOff.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHoldOff.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs index 4cbdaee323..f202b859b1 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs index 948979505c..9ce4fb6a48 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey1 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs index 684370fc3d..f378ce3435 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey10.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey10 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs index de91902ca8..5812df80f5 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey2 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs index 8575a96bde..4116ed5ceb 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey3 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs index 54ea3afa07..9879fec686 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey4 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs index e9a9bba5bd..646386b0d8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey5 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs index b9606d1cb5..56af9ed589 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey6 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs index b80d794085..a0a7116ed7 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey7 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs index 3462d634a4..fc8ecdb9ea 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey8 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs index 83c505c048..c495a6c82f 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModKey9 : ManiaKeyMod diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index 9c3744ea98..6e56981fc8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs index 33ebcf303a..076f634968 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMuted.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs index 4cc712060c..9ae664e1f6 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs index e8988be548..487f32dc26 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs index 2e22e23dbd..2789a2a06e 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs index 3c24e91d54..5da29e5a1d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModPlayfieldCover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index f5d1a34d73..22347d21b8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; @@ -22,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Mods var rng = new Random((int)Seed.Value); int availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; - var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => rng.Next()).ToList(); + var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(_ => rng.Next()).ToList(); 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 ecc343ecaa..17759d718e 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index 09a746042b..3f04a4fafe 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index 074cbf6bd6..0e2d6bce21 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osuTK; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 4e9781f336..19792086a7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs index 6722ad8ab8..d374e935ec 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteHead.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs index 803685363c..a7bdcd047e 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index cffa79322e..daec5ddbe7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 9ac223a0d7..bcc10ab7bc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 51727908c9..3c8b1b53b7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania/Objects/HeadNote.cs b/osu.Game.Rulesets.Mania/Objects/HeadNote.cs index e69cc62aed..fb5c7b4ddd 100644 --- a/osu.Game.Rulesets.Mania/Objects/HeadNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HeadNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Objects { public class HeadNote : Note diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index db0d3e2c5a..22fab15c1b 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Threading; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index ac6697a6dc..9117c60dcd 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 6289744df1..ebff5cf4e9 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Objects; @@ -11,12 +13,14 @@ namespace osu.Game.Rulesets.Mania.Objects { public abstract class ManiaHitObject : HitObject, IHasColumn, IHasXPosition { - public readonly Bindable ColumnBindable = new Bindable(); + private HitObjectProperty column; + + public Bindable ColumnBindable => column.Bindable; public virtual int Column { - get => ColumnBindable.Value; - set => ColumnBindable.Value = value; + get => column.Value; + set => column.Value = value; } protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 0035960c63..578b46a7aa 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 5a30fd6a12..cda8e2fa31 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs index ca1f7036c7..1bc20f7ef3 100644 --- a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index efe144ac03..7c8afdff12 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects; @@ -55,11 +56,11 @@ namespace osu.Game.Rulesets.Mania.Replays { switch (point) { - case HitPoint _: + case HitPoint: actions.Add(columnActions[point.Column]); break; - case ReleasePoint _: + case ReleasePoint: actions.Remove(columnActions[point.Column]); break; } @@ -83,7 +84,7 @@ namespace osu.Game.Rulesets.Mania.Replays } } - private double calculateReleaseTime(HitObject currentObject, HitObject nextObject) + private double calculateReleaseTime(HitObject currentObject, HitObject? nextObject) { double endTime = currentObject.GetEndTime(); @@ -94,10 +95,10 @@ namespace osu.Game.Rulesets.Mania.Replays bool canDelayKeyUpFully = nextObject == null || nextObject.StartTime > endTime + RELEASE_DELAY; - return endTime + (canDelayKeyUpFully ? RELEASE_DELAY : (nextObject.StartTime - endTime) * 0.9); + return endTime + (canDelayKeyUpFully ? RELEASE_DELAY : (nextObject.AsNonNull().StartTime - endTime) * 0.9); } - protected override HitObject GetNextObject(int currentIndex) + protected override HitObject? GetNextObject(int currentIndex) { int desiredColumn = Beatmap.HitObjects[currentIndex].Column; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index dbab54d1d0..29249ba474 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Replays Actions.AddRange(actions); } - public void FromLegacy(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) + public void FromLegacy(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame? lastFrame = null) { var maniaBeatmap = (ManiaBeatmap)beatmap; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs index 57c2ba9c6d..3f0491e53f 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs index 289f8a00ef..c46a1b5ab6 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 02d62a090b..dbf3d02955 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring diff --git a/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs b/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs index 2069329d9a..765fd11dd5 100644 --- a/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs +++ b/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs index 7138421b91..7476af3c3c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultBodyPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs index c9c3cff799..72bb05de49 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/DefaultNotePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs index 1f290f1f1c..9168a96b95 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/IHoldNoteBody.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Mania.Skinning.Default { /// diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs index 3c89e2c04a..362a265789 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/HitTargetInsetContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 31db08ce2f..4e6493ba18 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs index 54ddcbd5fe..f35cedab08 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs index e4d466dca5..278cf0707c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs index 490a03d11a..611dac30b3 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHitTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs index 1e75533442..a653e2ce36 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteHeadPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs index e6d4291d79..7511b008f0 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyHoldNoteTailPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs index 9c339345c4..dfd5af89c1 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyKeyArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs index eb5514ba43..ab953ccfb9 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaColumnElement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs index 5d662c18d3..d09a73a693 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs index 321a87f8b1..f185c8b99d 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyNotePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs index fdacc75c92..740ccbfe27 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs index 4e1952a670..f7c611d551 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageForeground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 315b4444c2..dd5baa8150 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs index 2e17a6bef1..4d0c321116 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigurationLookup.cs b/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigurationLookup.cs index f07a5518b7..e9005a3da0 100644 --- a/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigurationLookup.cs +++ b/osu.Game.Rulesets.Mania/Skinning/ManiaSkinConfigurationLookup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mania.UI; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index a04f5ef98e..deb1b155b5 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs b/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs index aef82d4c08..871ec9f1a3 100644 --- a/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs +++ b/osu.Game.Rulesets.Mania/UI/ColumnFlow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 77ddc6fbbf..5bd2d3ab48 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 51c138f5e1..b26b62f8a5 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs index 807f6a77d9..39d17db6be 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultColumnBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs index ec6c377a2e..53fa86125f 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultHitTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs index 15018b464f..5a0fab2ff4 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultKeyArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs index f5b542d085..20d80580bf 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs index b75b586ecf..7f4b8eacde 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs index 562d7b04c4..e83cd10d2d 100644 --- a/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/DefaultHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index 8581f016b1..923fc6863c 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index 28e970f397..ea3b438ec8 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs index 3252dcc276..74ddceeeef 100644 --- a/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Mania.UI diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 4cd6624ac6..99b36bd366 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs index 30e0aafb7d..8020fcb3cc 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs b/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs index b502d1f9e5..87d6c25ac2 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs index 98165fedeb..44fe4b1b30 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI diff --git a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs index 961858b62b..c39e21bace 100644 --- a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mania.Objects.Drawables; diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index 15d216e8c5..d397e7cc18 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs index 9f4963b022..28509d1f4e 100644 --- a/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/PoolableHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Pooling; diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index 94910bb410..c578bbb703 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/VariantMappingGenerator.cs b/osu.Game.Rulesets.Mania/VariantMappingGenerator.cs index 878d1088a6..2742ee087b 100644 --- a/osu.Game.Rulesets.Mania/VariantMappingGenerator.cs +++ b/osu.Game.Rulesets.Mania/VariantMappingGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs index 46c60f06a5..9b4226d5b6 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs index 01e635f09c..fa40a8536e 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs +++ b/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Foundation; using osu.Framework.iOS; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs index be38a883d7..ad23f3ee33 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.iOS; using UIKit; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckLowDiffOverlapsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckLowDiffOverlapsTest.cs index fd17d11d10..7a361b0821 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckLowDiffOverlapsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckLowDiffOverlapsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs index a6873c6de9..a778b76c67 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckOffscreenObjectsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTimeDistanceEqualityTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTimeDistanceEqualityTest.cs index 49a6fd12fa..4e8be75779 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTimeDistanceEqualityTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTimeDistanceEqualityTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSlidersTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSlidersTest.cs index 2eab5a4ce6..39a9d5e798 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSlidersTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSlidersTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSpinnersTest.cs b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSpinnersTest.cs index 1f3d4297f1..d044ae732a 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSpinnersTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/Checks/CheckTooShortSpinnersTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs index 7bccec6c97..4d84d3e79f 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs index 315493318d..fde62c7a53 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCircleSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs index a652fb32f4..a8829ef88c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectBeatSnap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs index 7bdf131e0d..6e8c7ff2bd 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index c50aec40a5..e54ce45ccc 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs index e1ca3ddd61..859290dbec 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs index 47b2d3a098..1e73885540 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs index d0348c1b6b..536739bd48 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs index 5a1aa42ed1..f196353f87 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs index e7bcd2cadc..a177079b8c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderControlPointPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Humanizer; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs index ce529f2a88..31b593e816 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderLengthValidity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs index e724015905..5c3c537541 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs index cc43eb3852..f84204f01c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs index b43b2b1461..a72f2031c9 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSnapping.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index 70a9c03e65..51871dd9e5 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs index 4750c97566..ef9e332253 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderVelocityAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using NUnit.Framework; @@ -8,7 +10,6 @@ using osu.Framework.Input; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit; @@ -39,10 +40,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); - private bool editorComponentsReady => editor.ChildrenOfType().FirstOrDefault()?.IsLoaded == true - && editor.ChildrenOfType().FirstOrDefault()?.IsLoaded == true - && editor?.ChildrenOfType().FirstOrDefault()?.IsLoaded == true; - [TestCase(true)] [TestCase(false)] public void TestVelocityChangeSavesCorrectly(bool adjustVelocity) @@ -50,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor double? velocity = null; AddStep("enter editor", () => Game.ScreenStack.Push(new EditorLoader())); - AddUntilStep("wait for editor load", () => editorComponentsReady); + AddUntilStep("wait for editor load", () => editor?.ReadyForUse == true); AddStep("seek to first control point", () => editorClock.Seek(editorBeatmap.ControlPointInfo.TimingPoints.First().Time)); AddStep("enter slider placement mode", () => InputManager.Key(Key.Number3)); @@ -89,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("exit", () => InputManager.Key(Key.Escape)); AddStep("enter editor (again)", () => Game.ScreenStack.Push(new EditorLoader())); - AddUntilStep("wait for editor load", () => editorComponentsReady); + AddUntilStep("wait for editor load", () => editor?.ReadyForUse == true); AddStep("seek to slider", () => editorClock.Seek(slider.StartTime)); AddAssert("slider has correct velocity", () => slider.Velocity == velocity); diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs index fa6c660b01..53ef675cb3 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs index 5007841805..a1b946dd4c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs index e29a67c770..efe195d872 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSliderScaling.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs index d8c10b814d..7c4ab2f5f4 100644 --- a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using System.Linq; @@ -78,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Tests skin.Setup(s => s.GetTexture(It.IsAny())).CallBase(); skin.Setup(s => s.GetTexture(It.IsIn(textureFilenames), It.IsAny(), It.IsAny())) - .Returns((string componentName, WrapMode _, WrapMode __) => new Texture(1, 1) { AssetName = componentName }); + .Returns((string componentName, WrapMode _, WrapMode _) => new Texture(1, 1) { AssetName = componentName }); Child = new DependencyProvidingContainer { diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs b/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs index d3cb3bcf59..4f005a0c70 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/OsuModTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Osu.Tests.Mods diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs index 5e46498aca..3d59e4fb51 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs index 37f1a846ad..378b71ccf7 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs index 9d06ff5801..80dc83d7dc 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs index 335ef31019..e1bed5153b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDoubleTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs index 71b575abe2..5ed25baca3 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs index 9b49e60363..1f1db04c24 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMagnetised.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs index e08d66fa31..99c9036ac0 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMuted.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs index 44404ca245..47e7ad320c 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModNoScope.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs index 985baa8cf5..b7669624ff 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.cs new file mode 100644 index 0000000000..6bd41e2fa5 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModRepel.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 NUnit.Framework; +using osu.Game.Rulesets.Osu.Mods; + +namespace osu.Game.Rulesets.Osu.Tests.Mods +{ + public class TestSceneOsuModRepel : OsuModTestScene + { + [TestCase(0.1f)] + [TestCase(0.5f)] + [TestCase(1)] + public void TestRepel(float strength) + { + CreateModTest(new ModTestData + { + Mod = new OsuModRepel + { + RepulsionStrength = { Value = strength }, + }, + PassCondition = () => true, + Autoplay = false, + }); + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs new file mode 100644 index 0000000000..1aed84be10 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSingleTap.cs @@ -0,0 +1,175 @@ +// 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.Game.Beatmaps; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Replays; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests.Mods +{ + public class TestSceneOsuModSingleTap : OsuModTestScene + { + [Test] + public void TestInputSingular() => CreateModTest(new ModTestData + { + Mod = new OsuModSingleTap(), + PassCondition = () => Player.ScoreProcessor.Combo.Value == 2, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + StartTime = 500, + Position = new Vector2(100), + }, + new HitCircle + { + StartTime = 1000, + Position = new Vector2(200, 100), + }, + new HitCircle + { + StartTime = 1500, + Position = new Vector2(300, 100), + }, + new HitCircle + { + StartTime = 2000, + Position = new Vector2(400, 100), + }, + }, + }, + ReplayFrames = new List + { + new OsuReplayFrame(500, new Vector2(100), OsuAction.LeftButton), + new OsuReplayFrame(501, new Vector2(100)), + new OsuReplayFrame(1000, new Vector2(200, 100), OsuAction.LeftButton), + } + }); + + [Test] + public void TestInputAlternating() => CreateModTest(new ModTestData + { + Mod = new OsuModSingleTap(), + PassCondition = () => Player.ScoreProcessor.Combo.Value == 0 && Player.ScoreProcessor.HighestCombo.Value == 1, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + StartTime = 500, + Position = new Vector2(100), + }, + new HitCircle + { + StartTime = 1000, + Position = new Vector2(200, 100), + }, + }, + }, + ReplayFrames = new List + { + new OsuReplayFrame(500, new Vector2(100), OsuAction.LeftButton), + new OsuReplayFrame(501, new Vector2(100)), + new OsuReplayFrame(1000, new Vector2(200, 100), OsuAction.RightButton), + new OsuReplayFrame(1001, new Vector2(200, 100)), + new OsuReplayFrame(1500, new Vector2(300, 100), OsuAction.LeftButton), + new OsuReplayFrame(1501, new Vector2(300, 100)), + new OsuReplayFrame(2000, new Vector2(400, 100), OsuAction.RightButton), + new OsuReplayFrame(2001, new Vector2(400, 100)), + } + }); + + /// + /// Ensures singletapping is reset before the first hitobject after intro. + /// + [Test] + public void TestInputAlternatingAtIntro() => CreateModTest(new ModTestData + { + Mod = new OsuModSingleTap(), + PassCondition = () => Player.ScoreProcessor.Combo.Value == 1, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = new List + { + new HitCircle + { + StartTime = 1000, + Position = new Vector2(100), + }, + }, + }, + ReplayFrames = new List + { + // first press during intro. + new OsuReplayFrame(500, new Vector2(200), OsuAction.LeftButton), + new OsuReplayFrame(501, new Vector2(200)), + // press different key at hitobject and ensure it has been hit. + new OsuReplayFrame(1000, new Vector2(100), OsuAction.RightButton), + } + }); + + /// + /// Ensures singletapping is reset before the first hitobject after a break. + /// + [Test] + public void TestInputAlternatingWithBreak() => CreateModTest(new ModTestData + { + Mod = new OsuModSingleTap(), + PassCondition = () => Player.ScoreProcessor.Combo.Value == 0 && Player.ScoreProcessor.HighestCombo.Value == 2, + Autoplay = false, + Beatmap = new Beatmap + { + Breaks = new List + { + new BreakPeriod(500, 2000), + }, + HitObjects = new List + { + new HitCircle + { + StartTime = 500, + Position = new Vector2(100), + }, + new HitCircle + { + StartTime = 2500, + Position = new Vector2(500, 100), + }, + new HitCircle + { + StartTime = 3000, + Position = new Vector2(500, 100), + }, + } + }, + ReplayFrames = new List + { + // first press to start singletap lock. + new OsuReplayFrame(500, new Vector2(100), OsuAction.LeftButton), + new OsuReplayFrame(501, new Vector2(100)), + // press different key after break but before hit object. + new OsuReplayFrame(2250, new Vector2(300, 100), OsuAction.RightButton), + new OsuReplayFrame(2251, new Vector2(300, 100)), + // press same key at second hitobject and ensure it has been hit. + new OsuReplayFrame(2500, new Vector2(500, 100), OsuAction.LeftButton), + new OsuReplayFrame(2501, new Vector2(500, 100)), + // press different key at third hitobject and ensure it has been missed. + new OsuReplayFrame(3000, new Vector2(500, 100), OsuAction.RightButton), + new OsuReplayFrame(3001, new Vector2(500, 100)), + } + }); + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs index a8953c1a6f..4f6d6376bf 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModSpunOut.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -50,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods lastResult = null; spinner = nextSpinner; - spinner.OnNewResult += (o, result) => lastResult = result; + spinner.OnNewResult += (_, result) => lastResult = result; } return lastResult?.Type == HitResult.Great; @@ -114,7 +116,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods return false; spinner = nextSpinner; - spinner.OnNewResult += (o, result) => results.Add(result); + spinner.OnNewResult += (_, result) => results.Add(result); results.Clear(); } diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 4c11efcc7c..bee46da1ba 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index df577ea8d3..46f7c461f8 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; @@ -15,18 +17,18 @@ namespace osu.Game.Rulesets.Osu.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; - [TestCase(6.6972307565739273d, 206, "diffcalc-test")] - [TestCase(1.4484754139145539d, 45, "zero-length-sliders")] + [TestCase(6.6369583000323935d, 206, "diffcalc-test")] + [TestCase(1.4476531024675374d, 45, "zero-length-sliders")] public void Test(double expectedStarRating, int expectedMaxCombo, string name) => base.Test(expectedStarRating, expectedMaxCombo, name); - [TestCase(8.9382559208689809d, 206, "diffcalc-test")] - [TestCase(1.7548875851757628d, 45, "zero-length-sliders")] + [TestCase(8.8816128335486386d, 206, "diffcalc-test")] + [TestCase(1.7540389962596916d, 45, "zero-length-sliders")] public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name) => Test(expectedStarRating, expectedMaxCombo, name, new OsuModDoubleTime()); - [TestCase(6.6972307218715166d, 239, "diffcalc-test")] - [TestCase(1.4484754139145537d, 54, "zero-length-sliders")] + [TestCase(6.6369583000323935d, 239, "diffcalc-test")] + [TestCase(1.4476531024675374d, 54, "zero-length-sliders")] public void TestClassicMod(double expectedStarRating, int expectedMaxCombo, string name) => Test(expectedStarRating, expectedMaxCombo, name, new OsuModClassic()); diff --git a/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs index 51da5b85cd..01d83b55e6 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; @@ -23,24 +25,27 @@ namespace osu.Game.Rulesets.Osu.Tests new object[] { LegacyMods.DoubleTime, new[] { typeof(OsuModDoubleTime) } }, new object[] { LegacyMods.Relax, new[] { typeof(OsuModRelax) } }, new object[] { LegacyMods.HalfTime, new[] { typeof(OsuModHalfTime) } }, - new object[] { LegacyMods.Nightcore, new[] { typeof(OsuModNightcore) } }, new object[] { LegacyMods.Flashlight, new[] { typeof(OsuModFlashlight) } }, new object[] { LegacyMods.Autoplay, new[] { typeof(OsuModAutoplay) } }, new object[] { LegacyMods.SpunOut, new[] { typeof(OsuModSpunOut) } }, new object[] { LegacyMods.Autopilot, new[] { typeof(OsuModAutopilot) } }, - new object[] { LegacyMods.Perfect, new[] { typeof(OsuModPerfect) } }, - new object[] { LegacyMods.Cinema, new[] { typeof(OsuModCinema) } }, new object[] { LegacyMods.Target, new[] { typeof(OsuModTarget) } }, new object[] { LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(OsuModHardRock), typeof(OsuModDoubleTime) } } }; [TestCaseSource(nameof(osu_mod_mapping))] + [TestCase(LegacyMods.Cinema, new[] { typeof(OsuModCinema) })] [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(OsuModCinema) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(OsuModNightcore) })] [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(OsuModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(OsuModPerfect) })] [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(OsuModPerfect) })] public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods); [TestCaseSource(nameof(osu_mod_mapping))] + [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(OsuModCinema) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(OsuModNightcore) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(OsuModPerfect) })] public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods); protected override Ruleset CreateRuleset() => new OsuRuleset(); diff --git a/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs b/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs index 233aaf2ed9..415e4ebedd 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuSkinnableTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs index 871afdb09d..a2ab7b564c 100644 --- a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs b/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs index 23d9d265be..106a7f499f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs index 79150a1941..805f4e6567 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneAccuracyHeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs index bd39dead34..b5d1c4854c 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorParticles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index 211b0e8145..c8d2d07be5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 7821ae9cf0..cfa1841fb7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs index fe67b63252..305678bb62 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index 496d495b43..2edacee9ac 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index f6e8a771ed..cc69054e23 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs index 8b3fead366..0bc65ac8e6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleApplication.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Timing; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs index 07bbd6379a..0cf2ec6b7e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs index ff600172d2..85951a95a2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index 45125204b6..a469f3dd99 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs index 2bce8fa7f2..e694871408 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleKiai.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 4e17c4c363..bcf2449e32 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 8b51225e98..1767d25e77 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs index a9325f98f7..0c6afe6c3d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs index 5e92bac986..9e524a1608 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs index d31e7a31f5..1665c40b40 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs index 19736a7709..e0d1646cb0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs index e8d98ce3b8..3bc55278d9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Reflection; using NUnit.Framework; using osu.Framework.IO.Stores; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index f5b28b36c0..6f378fc8b4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs index a7967c407a..e0d33c0e09 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index 43900c9a5c..dd767bf5e0 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Threading; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 0f362851a9..dd110662b2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 03b4254eed..a9ee276a9e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs index a40ae611d8..08a62fe3ae 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderApplication.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -12,7 +14,6 @@ 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.Skinning.Default; using osu.Game.Skinning; using osu.Game.Tests.Visual; using osuTK; @@ -91,10 +92,10 @@ namespace osu.Game.Rulesets.Osu.Tests }); AddStep("set accent white", () => dho.AccentColour.Value = Color4.White); - AddAssert("ball is white", () => dho.ChildrenOfType().Single().AccentColour == Color4.White); + AddAssert("ball is white", () => dho.ChildrenOfType().Single().AccentColour == Color4.White); AddStep("set accent red", () => dho.AccentColour.Value = Color4.Red); - AddAssert("ball is red", () => dho.ChildrenOfType().Single().AccentColour == Color4.Red); + AddAssert("ball is red", () => dho.ChildrenOfType().Single().AccentColour == Color4.Red); } private Slider prepareObject(Slider slider) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs index 13ced3019e..b48789a709 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs new file mode 100644 index 0000000000..7a6e19575e --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs @@ -0,0 +1,120 @@ +// 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 NUnit.Framework; +using osu.Framework.Screens; +using osu.Framework.Testing; +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.Replays; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [HeadlessTest] + public class TestSceneSliderFollowCircleInput : RateAdjustedBeatmapTestScene + { + private List? judgementResults; + private ScoreAccessibleReplayPlayer? currentPlayer; + + [Test] + public void TestMaximumDistanceTrackingWithoutMovement( + [Values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] + float circleSize, + [Values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] + double velocity) + { + const double time_slider_start = 1000; + + float circleRadius = OsuHitObject.OBJECT_RADIUS * (1.0f - 0.7f * (circleSize - 5) / 5) / 2; + float followCircleRadius = circleRadius * 1.2f; + + performTest(new Beatmap + { + HitObjects = + { + new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + DifficultyControlPoint = new DifficultyControlPoint { SliderVelocity = velocity }, + Path = new SliderPath(PathType.Linear, new[] + { + Vector2.Zero, + new Vector2(followCircleRadius, 0), + }, followCircleRadius), + }, + }, + BeatmapInfo = + { + Difficulty = new BeatmapDifficulty + { + CircleSize = circleSize, + SliderTickRate = 1 + }, + Ruleset = new OsuRuleset().RulesetInfo + }, + }, new List + { + new OsuReplayFrame { Position = new Vector2(-circleRadius + 1, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + }); + + AddAssert("Tracking kept", assertMaxJudge); + } + + private bool assertMaxJudge() => judgementResults?.Any() == true && judgementResults.All(t => t.Type == t.Judgement.MaxResult); + + private void performTest(Beatmap beatmap, List frames) + { + AddStep("load player", () => + { + Beatmap.Value = CreateWorkingBeatmap(beatmap); + + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); + + p.OnLoadComplete += _ => + { + p.ScoreProcessor.NewJudgement += result => + { + if (currentPlayer == p) judgementResults?.Add(result); + }; + }; + + LoadScreen(currentPlayer = p); + judgementResults = new List(); + }); + + AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); + AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); + AddUntilStep("Wait for completion", () => currentPlayer?.ScoreProcessor.HasCompleted.Value == true); + } + + private class ScoreAccessibleReplayPlayer : ReplayPlayer + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + protected override bool PauseOnFocusLost => false; + + public ScoreAccessibleReplayPlayer(Score score) + : base(score, new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) + { + } + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index b2bd727c6a..f70bdf8aa2 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 2368cc7365..e3cf5e9b05 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs index a3aa84d0e7..0118ed6513 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderSnaking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -22,6 +24,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Storyboards; +using osu.Game.Tests; using osuTK; namespace osu.Game.Rulesets.Osu.Tests @@ -64,18 +67,25 @@ namespace osu.Game.Rulesets.Osu.Tests drawableSlider = null; }); - [SetUpSteps] - public override void SetUpSteps() - { - } + protected override bool HasCustomSteps => true; [TestCase(0)] [TestCase(1)] [TestCase(2)] + [FlakyTest] + /* + * Fail rate around 0.15% + * + * TearDown : System.TimeoutException : "wait for seek to finish" timed out + * --TearDown + * at osu.Framework.Testing.Drawables.Steps.UntilStepButton.<>c__DisplayClass11_0.<.ctor>b__0() + * at osu.Framework.Testing.Drawables.Steps.StepButton.PerformStep(Boolean userTriggered) + * at osu.Framework.Testing.TestScene.runNextStep(Action onCompletion, Action`1 onError, Func`2 stopCondition) + */ public void TestSnakingEnabled(int sliderIndex) { AddStep("enable autoplay", () => autoplay = true); - base.SetUpSteps(); + CreateTest(); AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); retrieveSlider(sliderIndex); @@ -96,10 +106,20 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase(0)] [TestCase(1)] [TestCase(2)] + [FlakyTest] + /* + * Fail rate around 0.15% + * + * TearDown : System.TimeoutException : "wait for seek to finish" timed out + * --TearDown + * at osu.Framework.Testing.Drawables.Steps.UntilStepButton.<>c__DisplayClass11_0.<.ctor>b__0() + * at osu.Framework.Testing.Drawables.Steps.StepButton.PerformStep(Boolean userTriggered) + * at osu.Framework.Testing.TestScene.runNextStep(Action onCompletion, Action`1 onError, Func`2 stopCondition) + */ public void TestSnakingDisabled(int sliderIndex) { AddStep("have autoplay", () => autoplay = true); - base.SetUpSteps(); + CreateTest(); AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); retrieveSlider(sliderIndex); @@ -119,8 +139,7 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("enable autoplay", () => autoplay = true); setSnaking(true); - base.SetUpSteps(); - + CreateTest(); // repeat might have a chance to update its position depending on where in the frame its hit, // so some leniency is allowed here instead of checking strict equality addCheckPositionChangeSteps(() => 16600, getSliderRepeat, positionAlmostSame); @@ -131,15 +150,14 @@ namespace osu.Game.Rulesets.Osu.Tests { AddStep("disable autoplay", () => autoplay = false); setSnaking(true); - base.SetUpSteps(); - + CreateTest(); addCheckPositionChangeSteps(() => 16600, getSliderRepeat, positionDecreased); } private void retrieveSlider(int index) { AddStep("retrieve slider at index", () => slider = (Slider)beatmap.HitObjects[index]); - addSeekStep(() => slider); + addSeekStep(() => slider.StartTime); AddUntilStep("retrieve drawable slider", () => (drawableSlider = (DrawableSlider)Player.DrawableRuleset.Playfield.AllHitObjects.SingleOrDefault(d => d.HitObject == slider)) != null); } @@ -159,7 +177,7 @@ namespace osu.Game.Rulesets.Osu.Tests => addCheckPositionChangeSteps(timeAtRepeat(startTime, repeatIndex), positionAtRepeat(repeatIndex), positionRemainsSame); private Func timeAtRepeat(Func startTime, int repeatIndex) => () => startTime() + 100 + duration_of_span * repeatIndex; - private Func positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? (Func)getSliderStart : getSliderEnd; + private Func positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? getSliderStart : getSliderEnd; private List getSliderCurve() => ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve; private Vector2 getSliderStart() => getSliderCurve().First(); @@ -203,16 +221,10 @@ namespace osu.Game.Rulesets.Osu.Tests }); } - private void addSeekStep(Func slider) + private void addSeekStep(Func getTime) { - AddStep("seek to slider", () => Player.GameplayClockContainer.Seek(slider().StartTime)); - AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(slider().StartTime, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); - } - - private void addSeekStep(Func time) - { - AddStep("seek to time", () => Player.GameplayClockContainer.Seek(time())); - AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time(), Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); + AddStep("seek to time", () => Player.GameplayClockContainer.Seek(getTime())); + AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(getTime(), Player.DrawableRuleset.FrameStableClock.CurrentTime, 100)); } protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap { HitObjects = createHitObjects() }; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 2dea9837f3..8dc8f82b86 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs index 8c97c02049..14fa77245a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerApplication.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Timing; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index 91b6a05fe3..b7bc36722a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs index de795241bf..d1796f2231 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs index 53fa3624b8..96b26403e1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; 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 2c0d3fd937..4349d25cb3 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 @@ -1,9 +1,8 @@  - - + diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index a5282877ee..df146a9511 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index d82186fb52..e9518895be 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index f51f04bf87..da66669550 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index 9589fd576f..b8ad61e6dd 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Configuration; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs new file mode 100644 index 0000000000..76d5ccf682 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs @@ -0,0 +1,137 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators +{ + public static class AimEvaluator + { + private const double wide_angle_multiplier = 1.5; + private const double acute_angle_multiplier = 2.0; + private const double slider_multiplier = 1.5; + private const double velocity_change_multiplier = 0.75; + + /// + /// Evaluates the difficulty of aiming the current object, based on: + /// + /// cursor velocity to the current object, + /// angle difficulty, + /// sharp velocity increases, + /// and slider difficulty. + /// + /// + public static double EvaluateDifficultyOf(DifficultyHitObject current, bool withSliders) + { + if (current.BaseObject is Spinner || current.Index <= 1 || current.Previous(0).BaseObject is Spinner) + return 0; + + var osuCurrObj = (OsuDifficultyHitObject)current; + var osuLastObj = (OsuDifficultyHitObject)current.Previous(0); + var osuLastLastObj = (OsuDifficultyHitObject)current.Previous(1); + + // Calculate the velocity to the current hitobject, which starts with a base distance / time assuming the last object is a hitcircle. + double currVelocity = osuCurrObj.LazyJumpDistance / osuCurrObj.StrainTime; + + // But if the last object is a slider, then we extend the travel velocity through the slider into the current object. + if (osuLastObj.BaseObject is Slider && withSliders) + { + double travelVelocity = osuLastObj.TravelDistance / osuLastObj.TravelTime; // calculate the slider velocity from slider head to slider end. + double movementVelocity = osuCurrObj.MinimumJumpDistance / osuCurrObj.MinimumJumpTime; // calculate the movement velocity from slider end to current object + + currVelocity = Math.Max(currVelocity, movementVelocity + travelVelocity); // take the larger total combined velocity. + } + + // As above, do the same for the previous hitobject. + double prevVelocity = osuLastObj.LazyJumpDistance / osuLastObj.StrainTime; + + if (osuLastLastObj.BaseObject is Slider && withSliders) + { + double travelVelocity = osuLastLastObj.TravelDistance / osuLastLastObj.TravelTime; + double movementVelocity = osuLastObj.MinimumJumpDistance / osuLastObj.MinimumJumpTime; + + prevVelocity = Math.Max(prevVelocity, movementVelocity + travelVelocity); + } + + double wideAngleBonus = 0; + double acuteAngleBonus = 0; + double sliderBonus = 0; + double velocityChangeBonus = 0; + + double aimStrain = currVelocity; // Start strain with regular velocity. + + if (Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime) < 1.25 * Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime)) // If rhythms are the same. + { + if (osuCurrObj.Angle != null && osuLastObj.Angle != null && osuLastLastObj.Angle != null) + { + double currAngle = osuCurrObj.Angle.Value; + double lastAngle = osuLastObj.Angle.Value; + double lastLastAngle = osuLastLastObj.Angle.Value; + + // Rewarding angles, take the smaller velocity as base. + double angleBonus = Math.Min(currVelocity, prevVelocity); + + wideAngleBonus = calcWideAngleBonus(currAngle); + acuteAngleBonus = calcAcuteAngleBonus(currAngle); + + if (osuCurrObj.StrainTime > 100) // Only buff deltaTime exceeding 300 bpm 1/2. + acuteAngleBonus = 0; + else + { + acuteAngleBonus *= calcAcuteAngleBonus(lastAngle) // Multiply by previous angle, we don't want to buff unless this is a wiggle type pattern. + * Math.Min(angleBonus, 125 / osuCurrObj.StrainTime) // The maximum velocity we buff is equal to 125 / strainTime + * Math.Pow(Math.Sin(Math.PI / 2 * Math.Min(1, (100 - osuCurrObj.StrainTime) / 25)), 2) // scale buff from 150 bpm 1/4 to 200 bpm 1/4 + * Math.Pow(Math.Sin(Math.PI / 2 * (Math.Clamp(osuCurrObj.LazyJumpDistance, 50, 100) - 50) / 50), 2); // Buff distance exceeding 50 (radius) up to 100 (diameter). + } + + // Penalize wide angles if they're repeated, reducing the penalty as the lastAngle gets more acute. + wideAngleBonus *= angleBonus * (1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3))); + // Penalize acute angles if they're repeated, reducing the penalty as the lastLastAngle gets more obtuse. + acuteAngleBonus *= 0.5 + 0.5 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastLastAngle), 3))); + } + } + + if (Math.Max(prevVelocity, currVelocity) != 0) + { + // We want to use the average velocity over the whole object when awarding differences, not the individual jump and slider path velocities. + prevVelocity = (osuLastObj.LazyJumpDistance + osuLastLastObj.TravelDistance) / osuLastObj.StrainTime; + currVelocity = (osuCurrObj.LazyJumpDistance + osuLastObj.TravelDistance) / osuCurrObj.StrainTime; + + // Scale with ratio of difference compared to 0.5 * max dist. + double distRatio = Math.Pow(Math.Sin(Math.PI / 2 * Math.Abs(prevVelocity - currVelocity) / Math.Max(prevVelocity, currVelocity)), 2); + + // Reward for % distance up to 125 / strainTime for overlaps where velocity is still changing. + double overlapVelocityBuff = Math.Min(125 / Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime), Math.Abs(prevVelocity - currVelocity)); + + velocityChangeBonus = overlapVelocityBuff * distRatio; + + // Penalize for rhythm changes. + velocityChangeBonus *= Math.Pow(Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime) / Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime), 2); + } + + if (osuLastObj.TravelTime != 0) + { + // Reward sliders based on velocity. + sliderBonus = osuLastObj.TravelDistance / osuLastObj.TravelTime; + } + + // Add in acute angle bonus or wide angle bonus + velocity change bonus, whichever is larger. + aimStrain += Math.Max(acuteAngleBonus * acute_angle_multiplier, wideAngleBonus * wide_angle_multiplier + velocityChangeBonus * velocity_change_multiplier); + + // Add in additional slider velocity bonus. + if (withSliders) + aimStrain += sliderBonus * slider_multiplier; + + return aimStrain; + } + + private static double calcWideAngleBonus(double angle) => Math.Pow(Math.Sin(3.0 / 4 * (Math.Min(5.0 / 6 * Math.PI, Math.Max(Math.PI / 6, angle)) - Math.PI / 6)), 2); + + private static double calcAcuteAngleBonus(double angle) => 1 - calcWideAngleBonus(angle); + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs new file mode 100644 index 0000000000..3b0826394c --- /dev/null +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs @@ -0,0 +1,79 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators +{ + public static class FlashlightEvaluator + { + private const double max_opacity_bonus = 0.4; + private const double hidden_bonus = 0.2; + + /// + /// Evaluates the difficulty of memorising and hitting an object, based on: + /// + /// distance between the previous and current object, + /// the visual opacity of the current object, + /// and whether the hidden mod is enabled. + /// + /// + public static double EvaluateDifficultyOf(DifficultyHitObject current, bool hidden) + { + if (current.BaseObject is Spinner) + return 0; + + var osuCurrent = (OsuDifficultyHitObject)current; + var osuHitObject = (OsuHitObject)(osuCurrent.BaseObject); + + double scalingFactor = 52.0 / osuHitObject.Radius; + double smallDistNerf = 1.0; + double cumulativeStrainTime = 0.0; + + double result = 0.0; + + OsuDifficultyHitObject lastObj = osuCurrent; + + // This is iterating backwards in time from the current object. + for (int i = 0; i < Math.Min(current.Index, 10); i++) + { + var currentObj = (OsuDifficultyHitObject)current.Previous(i); + var currentHitObject = (OsuHitObject)(currentObj.BaseObject); + + if (!(currentObj.BaseObject is Spinner)) + { + double jumpDistance = (osuHitObject.StackedPosition - currentHitObject.EndPosition).Length; + + cumulativeStrainTime += lastObj.StrainTime; + + // We want to nerf objects that can be easily seen within the Flashlight circle radius. + if (i == 0) + smallDistNerf = Math.Min(1.0, jumpDistance / 75.0); + + // We also want to nerf stacks so that only the first object of the stack is accounted for. + double stackNerf = Math.Min(1.0, (currentObj.LazyJumpDistance / scalingFactor) / 25.0); + + // Bonus based on how visible the object is. + double opacityBonus = 1.0 + max_opacity_bonus * (1.0 - osuCurrent.OpacityAt(currentHitObject.StartTime, hidden)); + + result += stackNerf * opacityBonus * scalingFactor * jumpDistance / cumulativeStrainTime; + } + + lastObj = currentObj; + } + + result = Math.Pow(smallDistNerf * result, 2.0); + + // Additional bonus for Hidden due to there being no approach circles. + if (hidden) + result *= 1.0 + hidden_bonus; + + return result; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs new file mode 100644 index 0000000000..3ffd45b588 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs @@ -0,0 +1,110 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators +{ + public static class RhythmEvaluator + { + private const int history_time_max = 5000; // 5 seconds of calculatingRhythmBonus max. + private const double rhythm_multiplier = 0.75; + + /// + /// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current . + /// + public static double EvaluateDifficultyOf(DifficultyHitObject current, double greatWindow) + { + if (current.BaseObject is Spinner) + return 0; + + int previousIslandSize = 0; + + double rhythmComplexitySum = 0; + int islandSize = 1; + double startRatio = 0; // store the ratio of the current start of an island to buff for tighter rhythms + + bool firstDeltaSwitch = false; + + int historicalNoteCount = Math.Min(current.Index, 32); + + int rhythmStart = 0; + + while (rhythmStart < historicalNoteCount - 2 && current.StartTime - current.Previous(rhythmStart).StartTime < history_time_max) + rhythmStart++; + + for (int i = rhythmStart; i > 0; i--) + { + OsuDifficultyHitObject currObj = (OsuDifficultyHitObject)current.Previous(i - 1); + OsuDifficultyHitObject prevObj = (OsuDifficultyHitObject)current.Previous(i); + OsuDifficultyHitObject lastObj = (OsuDifficultyHitObject)current.Previous(i + 1); + + double currHistoricalDecay = (history_time_max - (current.StartTime - currObj.StartTime)) / history_time_max; // scales note 0 to 1 from history to now + + currHistoricalDecay = Math.Min((double)(historicalNoteCount - i) / historicalNoteCount, currHistoricalDecay); // either we're limited by time or limited by object count. + + double currDelta = currObj.StrainTime; + double prevDelta = prevObj.StrainTime; + double lastDelta = lastObj.StrainTime; + double currRatio = 1.0 + 6.0 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses. + + double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - greatWindow * 0.6) / (greatWindow * 0.6)); + + windowPenalty = Math.Min(1, windowPenalty); + + double effectiveRatio = windowPenalty * currRatio; + + if (firstDeltaSwitch) + { + if (!(prevDelta > 1.25 * currDelta || prevDelta * 1.25 < currDelta)) + { + if (islandSize < 7) + islandSize++; // island is still progressing, count size. + } + else + { + if (current.Previous(i - 1).BaseObject is Slider) // bpm change is into slider, this is easy acc window + effectiveRatio *= 0.125; + + if (current.Previous(i).BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle + effectiveRatio *= 0.25; + + if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet) + effectiveRatio *= 0.25; + + if (previousIslandSize % 2 == islandSize % 2) // repeated island polartiy (2 -> 4, 3 -> 5) + effectiveRatio *= 0.50; + + if (lastDelta > prevDelta + 10 && prevDelta > currDelta + 10) // previous increase happened a note ago, 1/1->1/2-1/4, dont want to buff this. + effectiveRatio *= 0.125; + + rhythmComplexitySum += Math.Sqrt(effectiveRatio * startRatio) * currHistoricalDecay * Math.Sqrt(4 + islandSize) / 2 * Math.Sqrt(4 + previousIslandSize) / 2; + + startRatio = effectiveRatio; + + previousIslandSize = islandSize; // log the last island size. + + if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting + firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size. + + islandSize = 1; + } + } + else if (prevDelta > 1.25 * currDelta) // we want to be speeding up. + { + // Begin counting island until we change speed again. + firstDeltaSwitch = true; + startRatio = effectiveRatio; + islandSize = 1; + } + } + + return Math.Sqrt(4 + rhythmComplexitySum * rhythm_multiplier) / 2; //produces multiplier that can be applied to strain. range [1, infinity) (not really though) + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs new file mode 100644 index 0000000000..5187717639 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs @@ -0,0 +1,68 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; + +namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators +{ + public static class SpeedEvaluator + { + private const double single_spacing_threshold = 125; + private const double min_speed_bonus = 75; // ~200BPM + private const double speed_balancing_factor = 40; + + /// + /// Evaluates the difficulty of tapping the current object, based on: + /// + /// time between pressing the previous and current object, + /// distance between those objects, + /// and how easily they can be cheesed. + /// + /// + public static double EvaluateDifficultyOf(DifficultyHitObject current, double greatWindow) + { + if (current.BaseObject is Spinner) + return 0; + + // derive strainTime for calculation + var osuCurrObj = (OsuDifficultyHitObject)current; + var osuPrevObj = current.Index > 0 ? (OsuDifficultyHitObject)current.Previous(0) : null; + var osuNextObj = (OsuDifficultyHitObject)current.Next(0); + + double strainTime = osuCurrObj.StrainTime; + double greatWindowFull = greatWindow * 2; + double doubletapness = 1; + + // Nerf doubletappable doubles. + if (osuNextObj != null) + { + double currDeltaTime = Math.Max(1, osuCurrObj.DeltaTime); + double nextDeltaTime = Math.Max(1, osuNextObj.DeltaTime); + double deltaDifference = Math.Abs(nextDeltaTime - currDeltaTime); + double speedRatio = currDeltaTime / Math.Max(currDeltaTime, deltaDifference); + double windowRatio = Math.Pow(Math.Min(1, currDeltaTime / greatWindowFull), 2); + doubletapness = Math.Pow(speedRatio, 1 - windowRatio); + } + + // Cap deltatime to the OD 300 hitwindow. + // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly, whilst 0.92 limits the effect of the cap. + strainTime /= Math.Clamp((strainTime / greatWindowFull) / 0.93, 0.92, 1); + + // derive speedBonus for calculation + double speedBonus = 1.0; + + if (strainTime < min_speed_bonus) + speedBonus = 1 + 0.75 * Math.Pow((min_speed_bonus - strainTime) / speed_balancing_factor, 2); + + double travelDistance = osuPrevObj?.TravelDistance ?? 0; + double distance = Math.Min(single_spacing_threshold, travelDistance + osuCurrObj.MinimumJumpDistance); + + return (speedBonus + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) * doubletapness / strainTime; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index 3deed4ea3d..03540abddb 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -24,6 +25,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty [JsonProperty("speed_difficulty")] public double SpeedDifficulty { get; set; } + /// + /// The number of clickable objects weighted by difficulty. + /// Related to + /// + [JsonProperty("speed_note_count")] + public double SpeedNoteCount { get; set; } + /// /// The difficulty corresponding to the flashlight skill. /// @@ -92,11 +100,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty yield return (ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty); yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor); + yield return (ATTRIB_ID_SPEED_NOTE_COUNT, SpeedNoteCount); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values) + public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values); + base.FromDatabaseAttributes(values, onlineInfo); AimDifficulty = values[ATTRIB_ID_AIM]; SpeedDifficulty = values[ATTRIB_ID_SPEED]; @@ -106,6 +115,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty StarRating = values[ATTRIB_ID_DIFFICULTY]; FlashlightDifficulty = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT); SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR]; + SpeedNoteCount = values[ATTRIB_ID_SPEED_NOTE_COUNT]; + + DrainRate = onlineInfo.DrainRate; + HitCircleCount = onlineInfo.CircleCount; + SliderCount = onlineInfo.SliderCount; + SpinnerCount = onlineInfo.SpinnerCount; } #region Newtonsoft.Json implicit ShouldSerialize() methods diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 4eb5c79808..75d9469da3 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -36,6 +38,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double aimRatingNoSliders = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[2].DifficultyValue()) * difficulty_multiplier; + double speedNotes = ((Speed)skills[2]).RelevantNoteCount(); double flashlightRating = Math.Sqrt(skills[3].DifficultyValue()) * difficulty_multiplier; double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1; @@ -73,6 +76,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty Mods = mods, AimDifficulty = aimRating, SpeedDifficulty = speedRating, + SpeedNoteCount = speedNotes, FlashlightDifficulty = flashlightRating, SliderFactor = sliderFactor, ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5, @@ -87,16 +91,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { + List objects = new List(); + // 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); + objects.Add(new OsuDifficultyHitObject(beatmap.HitObjects[i], beatmap.HitObjects[i - 1], lastLast, clockRate, objects, objects.Count)); } + + return objects; } protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs index 0aeaf7669f..efb3ade220 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index d046be9ccb..c3b7834009 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -161,8 +163,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty speedValue *= 1.0 + 0.04 * (12.0 - attributes.ApproachRate); } + // Calculate accuracy assuming the worst case scenario + double relevantTotalDiff = totalHits - attributes.SpeedNoteCount; + double relevantCountGreat = Math.Max(0, countGreat - relevantTotalDiff); + double relevantCountOk = Math.Max(0, countOk - Math.Max(0, relevantTotalDiff - countGreat)); + double relevantCountMeh = Math.Max(0, countMeh - Math.Max(0, relevantTotalDiff - countGreat - countOk)); + double relevantAccuracy = attributes.SpeedNoteCount == 0 ? 0 : (relevantCountGreat * 6.0 + relevantCountOk * 2.0 + relevantCountMeh) / (attributes.SpeedNoteCount * 6.0); + // Scale the speed value with accuracy and OD. - speedValue *= (0.95 + Math.Pow(attributes.OverallDifficulty, 2) / 750) * Math.Pow(accuracy, (14.5 - Math.Max(attributes.OverallDifficulty, 8)) / 2); + speedValue *= (0.95 + Math.Pow(attributes.OverallDifficulty, 2) / 750) * Math.Pow((accuracy + relevantAccuracy) / 2.0, (14.5 - Math.Max(attributes.OverallDifficulty, 8)) / 2); // Scale the speed value with # of 50s to punish doubletapping. speedValue *= Math.Pow(0.98, countMeh < totalHits / 500.0 ? 0 : countMeh - totalHits / 500.0); diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index cf4802d282..c8646ec456 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; +using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Mods; @@ -74,8 +77,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing private readonly OsuHitObject lastLastObject; private readonly OsuHitObject lastObject; - public OsuDifficultyHitObject(HitObject hitObject, HitObject lastLastObject, HitObject lastObject, double clockRate) - : base(hitObject, lastObject, clockRate) + public OsuDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject lastLastObject, double clockRate, List objects, int index) + : base(hitObject, lastObject, clockRate, objects, index) { this.lastLastObject = (OsuHitObject)lastLastObject; this.lastObject = (OsuHitObject)lastObject; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index a6301aed6d..9b1fbf9a2e 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Difficulty.Evaluators; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { @@ -22,142 +23,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private readonly bool withSliders; - protected override int HistoryLength => 2; - - private const double wide_angle_multiplier = 1.5; - private const double acute_angle_multiplier = 2.0; - private const double slider_multiplier = 1.5; - private const double velocity_change_multiplier = 0.75; - private double currentStrain; private double skillMultiplier => 23.25; private double strainDecayBase => 0.15; - private double strainValueOf(DifficultyHitObject current) - { - if (current.BaseObject is Spinner || Previous.Count <= 1 || Previous[0].BaseObject is Spinner) - return 0; - - var osuCurrObj = (OsuDifficultyHitObject)current; - var osuLastObj = (OsuDifficultyHitObject)Previous[0]; - var osuLastLastObj = (OsuDifficultyHitObject)Previous[1]; - - // Calculate the velocity to the current hitobject, which starts with a base distance / time assuming the last object is a hitcircle. - double currVelocity = osuCurrObj.LazyJumpDistance / osuCurrObj.StrainTime; - - // But if the last object is a slider, then we extend the travel velocity through the slider into the current object. - if (osuLastObj.BaseObject is Slider && withSliders) - { - double travelVelocity = osuLastObj.TravelDistance / osuLastObj.TravelTime; // calculate the slider velocity from slider head to slider end. - double movementVelocity = osuCurrObj.MinimumJumpDistance / osuCurrObj.MinimumJumpTime; // calculate the movement velocity from slider end to current object - - currVelocity = Math.Max(currVelocity, movementVelocity + travelVelocity); // take the larger total combined velocity. - } - - // As above, do the same for the previous hitobject. - double prevVelocity = osuLastObj.LazyJumpDistance / osuLastObj.StrainTime; - - if (osuLastLastObj.BaseObject is Slider && withSliders) - { - double travelVelocity = osuLastLastObj.TravelDistance / osuLastLastObj.TravelTime; - double movementVelocity = osuLastObj.MinimumJumpDistance / osuLastObj.MinimumJumpTime; - - prevVelocity = Math.Max(prevVelocity, movementVelocity + travelVelocity); - } - - double wideAngleBonus = 0; - double acuteAngleBonus = 0; - double sliderBonus = 0; - double velocityChangeBonus = 0; - - double aimStrain = currVelocity; // Start strain with regular velocity. - - if (Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime) < 1.25 * Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime)) // If rhythms are the same. - { - if (osuCurrObj.Angle != null && osuLastObj.Angle != null && osuLastLastObj.Angle != null) - { - double currAngle = osuCurrObj.Angle.Value; - double lastAngle = osuLastObj.Angle.Value; - double lastLastAngle = osuLastLastObj.Angle.Value; - - // Rewarding angles, take the smaller velocity as base. - double angleBonus = Math.Min(currVelocity, prevVelocity); - - wideAngleBonus = calcWideAngleBonus(currAngle); - acuteAngleBonus = calcAcuteAngleBonus(currAngle); - - if (osuCurrObj.StrainTime > 100) // Only buff deltaTime exceeding 300 bpm 1/2. - acuteAngleBonus = 0; - else - { - acuteAngleBonus *= calcAcuteAngleBonus(lastAngle) // Multiply by previous angle, we don't want to buff unless this is a wiggle type pattern. - * Math.Min(angleBonus, 125 / osuCurrObj.StrainTime) // The maximum velocity we buff is equal to 125 / strainTime - * Math.Pow(Math.Sin(Math.PI / 2 * Math.Min(1, (100 - osuCurrObj.StrainTime) / 25)), 2) // scale buff from 150 bpm 1/4 to 200 bpm 1/4 - * Math.Pow(Math.Sin(Math.PI / 2 * (Math.Clamp(osuCurrObj.LazyJumpDistance, 50, 100) - 50) / 50), 2); // Buff distance exceeding 50 (radius) up to 100 (diameter). - } - - // Penalize wide angles if they're repeated, reducing the penalty as the lastAngle gets more acute. - wideAngleBonus *= angleBonus * (1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3))); - // Penalize acute angles if they're repeated, reducing the penalty as the lastLastAngle gets more obtuse. - acuteAngleBonus *= 0.5 + 0.5 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastLastAngle), 3))); - } - } - - if (Math.Max(prevVelocity, currVelocity) != 0) - { - // We want to use the average velocity over the whole object when awarding differences, not the individual jump and slider path velocities. - prevVelocity = (osuLastObj.LazyJumpDistance + osuLastLastObj.TravelDistance) / osuLastObj.StrainTime; - currVelocity = (osuCurrObj.LazyJumpDistance + osuLastObj.TravelDistance) / osuCurrObj.StrainTime; - - // Scale with ratio of difference compared to 0.5 * max dist. - double distRatio = Math.Pow(Math.Sin(Math.PI / 2 * Math.Abs(prevVelocity - currVelocity) / Math.Max(prevVelocity, currVelocity)), 2); - - // Reward for % distance up to 125 / strainTime for overlaps where velocity is still changing. - double overlapVelocityBuff = Math.Min(125 / Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime), Math.Abs(prevVelocity - currVelocity)); - - // Reward for % distance slowed down compared to previous, paying attention to not award overlap - double nonOverlapVelocityBuff = Math.Abs(prevVelocity - currVelocity) - // do not award overlap - * Math.Pow(Math.Sin(Math.PI / 2 * Math.Min(1, Math.Min(osuCurrObj.LazyJumpDistance, osuLastObj.LazyJumpDistance) / 100)), 2); - - // Choose the largest bonus, multiplied by ratio. - velocityChangeBonus = Math.Max(overlapVelocityBuff, nonOverlapVelocityBuff) * distRatio; - - // Penalize for rhythm changes. - velocityChangeBonus *= Math.Pow(Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime) / Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime), 2); - } - - if (osuLastObj.TravelTime != 0) - { - // Reward sliders based on velocity. - sliderBonus = osuLastObj.TravelDistance / osuLastObj.TravelTime; - } - - // Add in acute angle bonus or wide angle bonus + velocity change bonus, whichever is larger. - aimStrain += Math.Max(acuteAngleBonus * acute_angle_multiplier, wideAngleBonus * wide_angle_multiplier + velocityChangeBonus * velocity_change_multiplier); - - // Add in additional slider velocity bonus. - if (withSliders) - aimStrain += sliderBonus * slider_multiplier; - - return aimStrain; - } - - private double calcWideAngleBonus(double angle) => Math.Pow(Math.Sin(3.0 / 4 * (Math.Min(5.0 / 6 * Math.PI, Math.Max(Math.PI / 6, angle)) - Math.PI / 6)), 2); - - private double calcAcuteAngleBonus(double angle) => 1 - calcWideAngleBonus(angle); - - private double applyDiminishingExp(double val) => Math.Pow(val, 0.99); - private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); - protected override double CalculateInitialStrain(double time) => currentStrain * strainDecay(time - Previous[0].StartTime); + protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => currentStrain * strainDecay(time - current.Previous(0).StartTime); protected override double StrainValueAt(DifficultyHitObject current) { currentStrain *= strainDecay(current.DeltaTime); - currentStrain += strainValueOf(current) * skillMultiplier; + currentStrain += AimEvaluator.EvaluateDifficultyOf(current, withSliders) * skillMultiplier; return currentStrain; } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs index d93007fae5..84ef109598 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs @@ -1,102 +1,48 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Difficulty.Evaluators; using osu.Game.Rulesets.Osu.Mods; -using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { /// /// Represents the skill required to memorise and hit every object in a map with the Flashlight mod enabled. /// - public class Flashlight : OsuStrainSkill + public class Flashlight : StrainSkill { + private readonly bool hasHiddenMod; + public Flashlight(Mod[] mods) : base(mods) { - hidden = mods.Any(m => m is OsuModHidden); + hasHiddenMod = mods.Any(m => m is OsuModHidden); } private double skillMultiplier => 0.05; private double strainDecayBase => 0.15; - protected override double DecayWeight => 1.0; - protected override int HistoryLength => 10; // Look back for 10 notes is added for the sake of flashlight calculations. - - private readonly bool hidden; - - private const double max_opacity_bonus = 0.4; - private const double hidden_bonus = 0.2; private double currentStrain; - private double strainValueOf(DifficultyHitObject current) - { - if (current.BaseObject is Spinner) - return 0; - - var osuCurrent = (OsuDifficultyHitObject)current; - var osuHitObject = (OsuHitObject)(osuCurrent.BaseObject); - - double scalingFactor = 52.0 / osuHitObject.Radius; - double smallDistNerf = 1.0; - double cumulativeStrainTime = 0.0; - - double result = 0.0; - - OsuDifficultyHitObject lastObj = osuCurrent; - - // This is iterating backwards in time from the current object. - for (int i = 0; i < Previous.Count; i++) - { - var currentObj = (OsuDifficultyHitObject)Previous[i]; - var currentHitObject = (OsuHitObject)(currentObj.BaseObject); - - if (!(currentObj.BaseObject is Spinner)) - { - double jumpDistance = (osuHitObject.StackedPosition - currentHitObject.EndPosition).Length; - - cumulativeStrainTime += lastObj.StrainTime; - - // We want to nerf objects that can be easily seen within the Flashlight circle radius. - if (i == 0) - smallDistNerf = Math.Min(1.0, jumpDistance / 75.0); - - // We also want to nerf stacks so that only the first object of the stack is accounted for. - double stackNerf = Math.Min(1.0, (currentObj.LazyJumpDistance / scalingFactor) / 25.0); - - // Bonus based on how visible the object is. - double opacityBonus = 1.0 + max_opacity_bonus * (1.0 - osuCurrent.OpacityAt(currentHitObject.StartTime, hidden)); - - result += stackNerf * opacityBonus * scalingFactor * jumpDistance / cumulativeStrainTime; - } - - lastObj = currentObj; - } - - result = Math.Pow(smallDistNerf * result, 2.0); - - // Additional bonus for Hidden due to there being no approach circles. - if (hidden) - result *= 1.0 + hidden_bonus; - - return result; - } - private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); - protected override double CalculateInitialStrain(double time) => currentStrain * strainDecay(time - Previous[0].StartTime); + protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => currentStrain * strainDecay(time - current.Previous(0).StartTime); protected override double StrainValueAt(DifficultyHitObject current) { currentStrain *= strainDecay(current.DeltaTime); - currentStrain += strainValueOf(current) * skillMultiplier; + currentStrain += FlashlightEvaluator.EvaluateDifficultyOf(current, hasHiddenMod) * skillMultiplier; return currentStrain; } + + public override double DifficultyValue() => GetCurrentStrainPeaks().Sum() * OsuStrainSkill.DEFAULT_DIFFICULTY_MULTIPLIER; } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index dcd2c7d321..d6683ade05 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Skills; @@ -12,6 +14,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills { public abstract class OsuStrainSkill : StrainSkill { + /// + /// The default multiplier applied by to the final difficulty value after all other calculations. + /// May be overridden via . + /// + public const double DEFAULT_DIFFICULTY_MULTIPLIER = 1.06; + /// /// The number of sections with the highest strains, which the peak strain reductions will apply to. /// This is done in order to decrease their impact on the overall difficulty of the map for this skill. @@ -26,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// The final multiplier to be applied to after all other calculations. /// - protected virtual double DifficultyMultiplier => 1.06; + protected virtual double DifficultyMultiplier => DEFAULT_DIFFICULTY_MULTIPLIER; protected OsuStrainSkill(Mod[] mods) : base(mods) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 06d1ef7346..a156726f94 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -1,12 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Difficulty.Evaluators; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -using osu.Game.Rulesets.Osu.Objects; -using osu.Framework.Utils; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { @@ -15,12 +18,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// public class Speed : OsuStrainSkill { - private const double single_spacing_threshold = 125; - private const double rhythm_multiplier = 0.75; - private const int history_time_max = 5000; // 5 seconds of calculatingRhythmBonus max. - private const double min_speed_bonus = 75; // ~200BPM - private const double speed_balancing_factor = 40; - private double skillMultiplier => 1375; private double strainDecayBase => 0.3; @@ -29,151 +26,45 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override int ReducedSectionCount => 5; protected override double DifficultyMultiplier => 1.04; - protected override int HistoryLength => 32; - private readonly double greatWindow; + private readonly List objectStrains = new List(); + public Speed(Mod[] mods, double hitWindowGreat) : base(mods) { greatWindow = hitWindowGreat; } - /// - /// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current . - /// - private double calculateRhythmBonus(DifficultyHitObject current) - { - if (current.BaseObject is Spinner) - return 0; - - int previousIslandSize = 0; - - double rhythmComplexitySum = 0; - int islandSize = 1; - double startRatio = 0; // store the ratio of the current start of an island to buff for tighter rhythms - - bool firstDeltaSwitch = false; - - int rhythmStart = 0; - - while (rhythmStart < Previous.Count - 2 && current.StartTime - Previous[rhythmStart].StartTime < history_time_max) - rhythmStart++; - - for (int i = rhythmStart; i > 0; i--) - { - OsuDifficultyHitObject currObj = (OsuDifficultyHitObject)Previous[i - 1]; - OsuDifficultyHitObject prevObj = (OsuDifficultyHitObject)Previous[i]; - OsuDifficultyHitObject lastObj = (OsuDifficultyHitObject)Previous[i + 1]; - - double currHistoricalDecay = (history_time_max - (current.StartTime - currObj.StartTime)) / history_time_max; // scales note 0 to 1 from history to now - - currHistoricalDecay = Math.Min((double)(Previous.Count - i) / Previous.Count, currHistoricalDecay); // either we're limited by time or limited by object count. - - double currDelta = currObj.StrainTime; - double prevDelta = prevObj.StrainTime; - double lastDelta = lastObj.StrainTime; - double currRatio = 1.0 + 6.0 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses. - - double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - greatWindow * 0.6) / (greatWindow * 0.6)); - - windowPenalty = Math.Min(1, windowPenalty); - - double effectiveRatio = windowPenalty * currRatio; - - if (firstDeltaSwitch) - { - if (!(prevDelta > 1.25 * currDelta || prevDelta * 1.25 < currDelta)) - { - if (islandSize < 7) - islandSize++; // island is still progressing, count size. - } - else - { - if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window - effectiveRatio *= 0.125; - - if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle - effectiveRatio *= 0.25; - - if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet) - effectiveRatio *= 0.25; - - if (previousIslandSize % 2 == islandSize % 2) // repeated island polartiy (2 -> 4, 3 -> 5) - effectiveRatio *= 0.50; - - if (lastDelta > prevDelta + 10 && prevDelta > currDelta + 10) // previous increase happened a note ago, 1/1->1/2-1/4, dont want to buff this. - effectiveRatio *= 0.125; - - rhythmComplexitySum += Math.Sqrt(effectiveRatio * startRatio) * currHistoricalDecay * Math.Sqrt(4 + islandSize) / 2 * Math.Sqrt(4 + previousIslandSize) / 2; - - startRatio = effectiveRatio; - - previousIslandSize = islandSize; // log the last island size. - - if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting - firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size. - - islandSize = 1; - } - } - else if (prevDelta > 1.25 * currDelta) // we want to be speeding up. - { - // Begin counting island until we change speed again. - firstDeltaSwitch = true; - startRatio = effectiveRatio; - islandSize = 1; - } - } - - return Math.Sqrt(4 + rhythmComplexitySum * rhythm_multiplier) / 2; //produces multiplier that can be applied to strain. range [1, infinity) (not really though) - } - - private double strainValueOf(DifficultyHitObject current) - { - if (current.BaseObject is Spinner) - return 0; - - // derive strainTime for calculation - var osuCurrObj = (OsuDifficultyHitObject)current; - var osuPrevObj = Previous.Count > 0 ? (OsuDifficultyHitObject)Previous[0] : null; - - double strainTime = osuCurrObj.StrainTime; - double greatWindowFull = greatWindow * 2; - double speedWindowRatio = strainTime / greatWindowFull; - - // Aim to nerf cheesy rhythms (Very fast consecutive doubles with large deltatimes between) - if (osuPrevObj != null && strainTime < greatWindowFull && osuPrevObj.StrainTime > strainTime) - strainTime = Interpolation.Lerp(osuPrevObj.StrainTime, strainTime, speedWindowRatio); - - // Cap deltatime to the OD 300 hitwindow. - // 0.93 is derived from making sure 260bpm OD8 streams aren't nerfed harshly, whilst 0.92 limits the effect of the cap. - strainTime /= Math.Clamp((strainTime / greatWindowFull) / 0.93, 0.92, 1); - - // derive speedBonus for calculation - double speedBonus = 1.0; - - if (strainTime < min_speed_bonus) - speedBonus = 1 + 0.75 * Math.Pow((min_speed_bonus - strainTime) / speed_balancing_factor, 2); - - double travelDistance = osuPrevObj?.TravelDistance ?? 0; - double distance = Math.Min(single_spacing_threshold, travelDistance + osuCurrObj.MinimumJumpDistance); - - return (speedBonus + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / strainTime; - } - private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); - protected override double CalculateInitialStrain(double time) => (currentStrain * currentRhythm) * strainDecay(time - Previous[0].StartTime); + protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => (currentStrain * currentRhythm) * strainDecay(time - current.Previous(0).StartTime); protected override double StrainValueAt(DifficultyHitObject current) { - currentStrain *= strainDecay(current.DeltaTime); - currentStrain += strainValueOf(current) * skillMultiplier; + currentStrain *= strainDecay(((OsuDifficultyHitObject)current).StrainTime); + currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current, greatWindow) * skillMultiplier; - currentRhythm = calculateRhythmBonus(current); + currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current, greatWindow); - return currentStrain * currentRhythm; + double totalStrain = currentStrain * currentRhythm; + + objectStrains.Add(totalStrain); + + return totalStrain; + } + + public double RelevantNoteCount() + { + if (objectStrains.Count == 0) + return 0; + + double maxStrain = objectStrains.Max(); + + if (maxStrain == 0) + return 0; + + return objectStrains.Aggregate((total, next) => total + (1.0 / (1.0 + Math.Exp(-(next / maxStrain * 12.0 - 6.0))))); } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs index b9c77d3f56..55b7efc8af 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs index ad4be2017e..71cdbc276e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; 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 0cfc67cedb..984fbb83a8 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index c45a04053f..ff4f61986f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 3f9cfe21d4..73756d9326 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index 2d0c6fe81d..422287918e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs index d66c9ea4bf..0b9ccc5c37 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointConnectionPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; 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 09759aa118..92d83d900e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; 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 e71bde7357..0506e8ab8a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; 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 6e22c35ab3..bb967a0a76 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs index d31d2aed97..d48d43d532 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 501589987d..59be93530c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using JetBrains.Annotations; @@ -14,6 +16,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osuTK; using osuTK.Input; @@ -22,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public class SliderPlacementBlueprint : PlacementBlueprint { - public new Objects.Slider HitObject => (Objects.Slider)base.HitObject; + public new Slider HitObject => (Slider)base.HitObject; private SliderBodyPiece bodyPiece; private HitCirclePiece headCirclePiece; @@ -40,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private IDistanceSnapProvider snapProvider { get; set; } public SliderPlacementBlueprint() - : base(new Objects.Slider()) + : base(new Slider()) { RelativeSizeAxes = Axes.Both; @@ -80,7 +83,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case SliderPlacementState.Initial: BeginPlacement(); - var nearestDifficultyPoint = editorBeatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.DifficultyControlPoint?.DeepClone() as DifficultyControlPoint; + var nearestDifficultyPoint = editorBeatmap.HitObjects + .LastOrDefault(h => h is Slider && h.GetEndTime() < HitObject.StartTime)? + .DifficultyControlPoint?.DeepClone() as DifficultyControlPoint; HitObject.DifficultyControlPoint = nearestDifficultyPoint ?? new DifficultyControlPoint(); HitObject.Position = ToLocalSpace(result.ScreenSpacePosition); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs index 616bb17e05..92071d4a57 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public enum SliderPosition diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index a019f2fb64..bd11cc826f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; 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 92961b40bc..28690ee0b7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index cc4ed0eccf..97d53d8e95 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; 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 ee573d1a01..5240c0bfeb 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs index 084a3e5ea1..57e6a6ad1d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckLowDiffOverlaps.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs index a342c2a821..af3521c35c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckOffscreenObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs index 585bd35bd9..753ddba710 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTimeDistanceEquality.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSliders.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSliders.cs index 159498c479..75eeb91918 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSliders.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSliders.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSpinners.cs b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSpinners.cs index f0aade1b7f..6b4dc01ab1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSpinners.cs +++ b/osu.Game.Rulesets.Osu/Edit/Checks/CheckTooShortSpinners.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs index 516b34d807..a5f7707cb3 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditorRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs index 5f7c8b77b0..69187875d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index 221723e4cd..2c67f0bf97 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index dc8c3d6107..c0fb0ae7db 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs index b11929c1e8..23bf67ff29 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuDistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index b0d6170190..60896b17bf 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -71,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Edit }); selectedHitObjects = EditorBeatmap.SelectedHitObjects.GetBoundCopy(); - selectedHitObjects.CollectionChanged += (_, __) => updateDistanceSnapGrid(); + selectedHitObjects.CollectionChanged += (_, _) => updateDistanceSnapGrid(); placementObject = EditorBeatmap.PlacementObject.GetBoundCopy(); placementObject.ValueChanged += _ => updateDistanceSnapGrid(); @@ -202,7 +204,7 @@ namespace osu.Game.Rulesets.Osu.Edit switch (BlueprintContainer.CurrentTool) { - case SelectTool _: + case SelectTool: if (!EditorBeatmap.SelectedHitObjects.Any()) return; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs index d1c81b51bc..35dad1a4fb 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 70c60ab635..4a6d94f303 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs b/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs index 8cb778a2e1..d8471aca1a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs +++ b/osu.Game.Rulesets.Osu/Edit/Setup/OsuSetupSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs index 596224e5c6..0a3fc176ad 100644 --- a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs index c5e90da3bd..3c0cf34010 100644 --- a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs index ad292b0439..9762c676c5 100644 --- a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Rulesets.Osu.Judgements diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs index 9b33e746b3..5f9faaceb2 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs index 1999785efe..1bdb74cd3b 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Judgements diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 1a88e2a8b2..a5503d3273 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 15444b847b..50d73fa19d 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs index 9f77175398..4229c87b58 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs index a088696784..270c1f31fb 100644 --- a/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Judgements diff --git a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs index 4a3b187e83..affc0bae6a 100644 --- a/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IHidesApproachCircles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Mods { /// diff --git a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs index 1458abfe05..a108f5fd14 100644 --- a/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs +++ b/osu.Game.Rulesets.Osu/Mods/IRequiresApproachCircles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Mods { /// diff --git a/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs b/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs new file mode 100644 index 0000000000..a7aca8257b --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs @@ -0,0 +1,114 @@ +// Copyright (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.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; +using osu.Game.Utils; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public abstract class InputBlockingMod : Mod, IApplicableToDrawableRuleset + { + public override double ScoreMultiplier => 1.0; + public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(OsuModCinema) }; + public override ModType Type => ModType.Conversion; + + private const double flash_duration = 1000; + + private DrawableRuleset ruleset = null!; + + protected OsuAction? LastAcceptedAction { get; private set; } + + /// + /// A tracker for periods where alternate should not be forced (i.e. non-gameplay periods). + /// + /// + /// This is different from in that the periods here end strictly at the first object after the break, rather than the break's end time. + /// + private PeriodTracker nonGameplayPeriods = null!; + + private IFrameStableClock gameplayClock = null!; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + ruleset = drawableRuleset; + drawableRuleset.KeyBindingInputManager.Add(new InputInterceptor(this)); + + var periods = new List(); + + if (drawableRuleset.Objects.Any()) + { + periods.Add(new Period(int.MinValue, getValidJudgementTime(ruleset.Objects.First()) - 1)); + + foreach (BreakPeriod b in drawableRuleset.Beatmap.Breaks) + periods.Add(new Period(b.StartTime, getValidJudgementTime(ruleset.Objects.First(h => h.StartTime >= b.EndTime)) - 1)); + + static double getValidJudgementTime(HitObject hitObject) => hitObject.StartTime - hitObject.HitWindows.WindowFor(HitResult.Meh); + } + + nonGameplayPeriods = new PeriodTracker(periods); + + gameplayClock = drawableRuleset.FrameStableClock; + } + + protected abstract bool CheckValidNewAction(OsuAction action); + + private bool checkCorrectAction(OsuAction action) + { + if (nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) + { + LastAcceptedAction = null; + return true; + } + + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + break; + + // Any action which is not left or right button should be ignored. + default: + return true; + } + + if (CheckValidNewAction(action)) + { + LastAcceptedAction = action; + return true; + } + + ruleset.Cursor.FlashColour(Colour4.Red, flash_duration, Easing.OutQuint); + return false; + } + + private class InputInterceptor : Component, IKeyBindingHandler + { + private readonly InputBlockingMod mod; + + public InputInterceptor(InputBlockingMod mod) + { + this.mod = mod; + } + + public bool OnPressed(KeyBindingPressEvent e) + // if the pressed action is incorrect, block it from reaching gameplay. + => !mod.checkCorrectAction(e.Action); + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAlternate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAlternate.cs index 0832cfb545..d88cb17e84 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAlternate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAlternate.cs @@ -2,116 +2,19 @@ // 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.Sprites; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; -using osu.Game.Beatmaps.Timing; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; -using osu.Game.Utils; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModAlternate : Mod, IApplicableToDrawableRuleset + public class OsuModAlternate : InputBlockingMod { public override string Name => @"Alternate"; public override string Acronym => @"AL"; public override string Description => @"Don't use the same key twice in a row!"; - public override double ScoreMultiplier => 1.0; - public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax) }; - public override ModType Type => ModType.Conversion; public override IconUsage? Icon => FontAwesome.Solid.Keyboard; + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModSingleTap) }).ToArray(); - private const double flash_duration = 1000; - - /// - /// A tracker for periods where alternate should not be forced (i.e. non-gameplay periods). - /// - /// - /// This is different from in that the periods here end strictly at the first object after the break, rather than the break's end time. - /// - private PeriodTracker nonGameplayPeriods; - - private OsuAction? lastActionPressed; - private DrawableRuleset ruleset; - - private IFrameStableClock gameplayClock; - - public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) - { - ruleset = drawableRuleset; - drawableRuleset.KeyBindingInputManager.Add(new InputInterceptor(this)); - - var periods = new List(); - - if (drawableRuleset.Objects.Any()) - { - periods.Add(new Period(int.MinValue, getValidJudgementTime(ruleset.Objects.First()) - 1)); - - foreach (BreakPeriod b in drawableRuleset.Beatmap.Breaks) - periods.Add(new Period(b.StartTime, getValidJudgementTime(ruleset.Objects.First(h => h.StartTime >= b.EndTime)) - 1)); - - static double getValidJudgementTime(HitObject hitObject) => hitObject.StartTime - hitObject.HitWindows.WindowFor(HitResult.Meh); - } - - nonGameplayPeriods = new PeriodTracker(periods); - - gameplayClock = drawableRuleset.FrameStableClock; - } - - private bool checkCorrectAction(OsuAction action) - { - if (nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) - { - lastActionPressed = null; - return true; - } - - switch (action) - { - case OsuAction.LeftButton: - case OsuAction.RightButton: - break; - - // Any action which is not left or right button should be ignored. - default: - return true; - } - - if (lastActionPressed != action) - { - // User alternated correctly. - lastActionPressed = action; - return true; - } - - ruleset.Cursor.FlashColour(Colour4.Red, flash_duration, Easing.OutQuint); - return false; - } - - private class InputInterceptor : Component, IKeyBindingHandler - { - private readonly OsuModAlternate mod; - - public InputInterceptor(OsuModAlternate mod) - { - this.mod = mod; - } - - public bool OnPressed(KeyBindingPressEvent e) - // if the pressed action is incorrect, block it from reaching gameplay. - => !mod.checkCorrectAction(e.Action); - - public void OnReleased(KeyBindingReleaseEvent e) - { - } - } + protected override bool CheckValidNewAction(OsuAction action) => LastAcceptedAction != action; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs index 8b323eefa6..e25845f5ab 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -35,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableHitObject(DrawableHitObject drawable) { - drawable.ApplyCustomUpdateState += (drawableObject, state) => + drawable.ApplyCustomUpdateState += (drawableObject, _) => { if (!(drawableObject is DrawableHitCircle drawableHitCircle)) return; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index aaf455e95f..a3f6448457 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -22,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Automation; public override string Description => @"Automatic cursor movement - just follow the rhythm."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail), typeof(ModAutoplay), typeof(OsuModMagnetised) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail), typeof(ModAutoplay), typeof(OsuModMagnetised), typeof(OsuModRepel) }; public bool PerformFail() => false; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index 507b3588bd..c4de77b8a3 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -12,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModAutoplay : ModAutoplay { - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModMagnetised), typeof(OsuModAutopilot), typeof(OsuModSpunOut), typeof(OsuModAlternate) }).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModMagnetised), typeof(OsuModRepel), typeof(OsuModAutopilot), typeof(OsuModSpunOut), typeof(OsuModAlternate), typeof(OsuModSingleTap) }).ToArray(); public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = "Autoplay" }); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs index 9e71f657ce..71bdd98457 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 7567c96b50..17a9a81de8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -28,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override IconUsage? Icon => FontAwesome.Solid.Adjust; public override ModType Type => ModType.DifficultyIncrease; - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; public override Type[] IncompatibleMods => new[] { typeof(OsuModFlashlight) }; private DrawableOsuBlinds blinds; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs index 99d7535957..d5096619b9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -13,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModCinema : ModCinema { - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModMagnetised), typeof(OsuModAutopilot), typeof(OsuModSpunOut), typeof(OsuModAlternate) }).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModMagnetised), typeof(OsuModAutopilot), typeof(OsuModSpunOut), typeof(OsuModAlternate), typeof(OsuModSingleTap), typeof(OsuModRepel) }).ToArray(); public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = "Autoplay" }); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs b/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs index 76ff361ce3..00009f4c3d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; @@ -28,9 +30,6 @@ namespace osu.Game.Rulesets.Osu.Mods [SettingSource("Apply classic note lock", "Applies note lock to the full hit window.")] public Bindable ClassicNoteLock { get; } = new BindableBool(true); - [SettingSource("Use fixed slider follow circle hit area", "Makes the slider follow circle track its final size at all times.")] - public Bindable FixedFollowCircleHitArea { get; } = new BindableBool(true); - [SettingSource("Always play a slider's tail sample", "Always plays a slider's tail sample regardless of whether it was hit or not.")] public Bindable AlwaysPlayTailSample { get; } = new BindableBool(true); @@ -60,10 +59,6 @@ namespace osu.Game.Rulesets.Osu.Mods { switch (obj) { - case DrawableSlider slider: - slider.Ball.InputTracksVisualSize = !FixedFollowCircleHitArea.Value; - break; - case DrawableSliderHead head: head.TrackFollowCircle = !NoSliderHeadMovement.Value; break; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs index 371dfe6a1a..c4cc0b4f48 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Mods diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs index ee6a7815e2..e95e61312e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDeflate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs index 3a6b232f9f..be159523b7 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDifficultyAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Game.Beatmaps; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs index 933c6cde1c..b86efe84ee 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs @@ -1,12 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Mods { public class OsuModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs b/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs index 06b5b6cfb8..90b22e8d9c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Mods diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 44d72fae61..b72e6b4dcb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; @@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModFlashlight : ModFlashlight, IApplicableToDrawableHitObject { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModBlinds)).ToArray(); private const double default_follow_delay = 120; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 182d6eeb4b..34840de983 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs index 4769e7660b..54c5c56ca6 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Mods diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 007820b016..1f25655c8c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets.Mods; @@ -12,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModHardRock : ModHardRock, IApplicableToHitObject { - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModMirror)).ToArray(); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index fc04e4d091..253eaf473b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; @@ -23,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods public Bindable OnlyFadeApproachCircles { get; } = new BindableBool(); public override string Description => @"Play with no approach circles and fading circles/sliders."; - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn) }; @@ -86,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Mods switch (drawableObject) { - case DrawableSliderTail _: + case DrawableSliderTail: using (drawableObject.BeginAbsoluteSequence(fadeStartTime)) drawableObject.FadeOut(fadeDuration); @@ -163,14 +165,14 @@ namespace osu.Game.Rulesets.Osu.Mods switch (hitObject) { - case Slider _: + case Slider: return (fadeOutStartTime, longFadeDuration); - case SliderTick _: + case SliderTick: double tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); return (hitObject.StartTime - tickFadeOutDuration, tickFadeOutDuration); - case Spinner _: + case Spinner: return (fadeOutStartTime + longFadeDuration, fadeOutDuration); default: diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs index ca6e9cfb1d..f9a74d2a3a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; @@ -24,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override string Description => "No need to chase the circles – your cursor is a magnet!"; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModRelax) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModRelax), typeof(OsuModRepel) }; private IFrameStableClock gameplayClock; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs index 3faca0b01f..1d822a2d4c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMirror.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs index 5e3ee37b61..1d4650a379 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMuted.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs index 7780e23a26..b1fe066a1e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; @@ -8,6 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModNightcore : ModNightcore { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs index 9f707a5aa6..c20fcf0b1b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs index 8e377ea632..fe415cb967 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoScope.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs index 70c075276f..44942e9e37 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -42,13 +44,13 @@ namespace osu.Game.Rulesets.Osu.Mods // apply grow effect switch (drawable) { - case DrawableSliderHead _: - case DrawableSliderTail _: + case DrawableSliderHead: + case DrawableSliderTail: // special cases we should *not* be scaling. break; - case DrawableSlider _: - case DrawableHitCircle _: + case DrawableSlider: + case DrawableHitCircle: { using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) drawable.ScaleTo(StartScale.Value).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine); diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs b/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs index da462eb6e8..bde7718da5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs @@ -1,11 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System; +using System.Linq; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Mods { public class OsuModPerfect : ModPerfect { + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 79ff222a89..4f83154728 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 5f37c6a0ae..2030156f2e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods public class OsuModRelax : ModRelax, IUpdatableByPlayfield, IApplicableToDrawableRuleset, IApplicableToPlayer { public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModMagnetised), typeof(OsuModAlternate) }).ToArray(); + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModMagnetised), typeof(OsuModAlternate), typeof(OsuModSingleTap) }).ToArray(); /// /// How early before a hitobject's start time to trigger a hit. diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs new file mode 100644 index 0000000000..211987ee32 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRepel.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; +using System.Diagnostics; +using osu.Framework.Bindables; +using osu.Framework.Utils; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Osu.Utils; +using osu.Game.Rulesets.UI; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModRepel : Mod, IUpdatableByPlayfield, IApplicableToDrawableRuleset + { + public override string Name => "Repel"; + public override string Acronym => "RP"; + public override ModType Type => ModType.Fun; + public override string Description => "Hit objects run away!"; + public override double ScoreMultiplier => 1; + public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModMagnetised) }; + + private IFrameStableClock? gameplayClock; + + [SettingSource("Repulsion strength", "How strong the repulsion is.", 0)] + public BindableFloat RepulsionStrength { get; } = new BindableFloat(0.5f) + { + Precision = 0.05f, + MinValue = 0.05f, + MaxValue = 1.0f, + }; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + gameplayClock = drawableRuleset.FrameStableClock; + + // Hide judgment displays and follow points as they won't make any sense. + // Judgements can potentially be turned on in a future where they display at a position relative to their drawable counterpart. + drawableRuleset.Playfield.DisplayJudgements.Value = false; + (drawableRuleset.Playfield as OsuPlayfield)?.FollowPoints.Hide(); + } + + public void Update(Playfield playfield) + { + var cursorPos = playfield.Cursor.ActiveCursor.DrawPosition; + + foreach (var drawable in playfield.HitObjectContainer.AliveObjects) + { + var destination = Vector2.Clamp(2 * drawable.Position - cursorPos, Vector2.Zero, OsuPlayfield.BASE_SIZE); + + if (drawable.HitObject is Slider thisSlider) + { + var possibleMovementBounds = OsuHitObjectGenerationUtils.CalculatePossibleMovementBounds(thisSlider); + + destination = Vector2.Clamp( + destination, + new Vector2(possibleMovementBounds.Left, possibleMovementBounds.Top), + new Vector2(possibleMovementBounds.Right, possibleMovementBounds.Bottom) + ); + } + + switch (drawable) + { + case DrawableHitCircle circle: + easeTo(circle, destination, cursorPos); + break; + + case DrawableSlider slider: + + if (!slider.HeadCircle.Result.HasResult) + easeTo(slider, destination, cursorPos); + else + easeTo(slider, destination - slider.Ball.DrawPosition, cursorPos); + + break; + } + } + } + + private void easeTo(DrawableHitObject hitObject, Vector2 destination, Vector2 cursorPos) + { + Debug.Assert(gameplayClock != null); + + double dampLength = Vector2.Distance(hitObject.Position, cursorPos) / (0.04 * RepulsionStrength.Value + 0.04); + + float x = (float)Interpolation.DampContinuously(hitObject.X, destination.X, dampLength, gameplayClock.ElapsedFrameTime); + float y = (float)Interpolation.DampContinuously(hitObject.Y, destination.Y, dampLength, gameplayClock.ElapsedFrameTime); + + hitObject.Position = new Vector2(x, y); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSingleTap.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSingleTap.cs new file mode 100644 index 0000000000..b170d30448 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSingleTap.cs @@ -0,0 +1,18 @@ +// Copyright (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; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModSingleTap : InputBlockingMod + { + public override string Name => @"Single Tap"; + public override string Acronym => @"SG"; + public override string Description => @"You must only use one key!"; + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAlternate) }).ToArray(); + + protected override bool CheckValidNewAction(OsuAction action) => LastAcceptedAction == null || LastAcceptedAction == action; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs index 95e7d13ee7..16e7780af0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index d9ab749ad3..61028a1ee8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs index 0b34ab28a3..565ff415be 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs index 429fe30fc5..4eb7659152 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index c58c624f5c..f03bcffdc8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -372,7 +374,7 @@ namespace osu.Game.Rulesets.Osu.Mods int i = 0; double currentTime = timingPoint.Time; - while (!definitelyBigger(currentTime, mapEndTime) && controlPointInfo.TimingPointAt(currentTime) == timingPoint) + while (!definitelyBigger(currentTime, mapEndTime) && ReferenceEquals(controlPointInfo.TimingPointAt(currentTime), timingPoint)) { beats.Add(Math.Floor(currentTime)); i++; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs index 7276cc753c..f8c1e1639d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Mods diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 07ce009cf8..6e5dd45a7a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 45ce4d555a..84906f6eed 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; @@ -20,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override string Description => "Everything rotates. EVERYTHING."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModWiggle), typeof(OsuModMagnetised) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModWiggle), typeof(OsuModMagnetised), typeof(OsuModRepel) }; private float theta; @@ -32,10 +34,10 @@ namespace osu.Game.Rulesets.Osu.Mods { switch (drawable) { - case DrawableSliderHead _: - case DrawableSliderTail _: - case DrawableSliderTick _: - case DrawableSliderRepeat _: + case DrawableSliderHead: + case DrawableSliderTail: + case DrawableSliderTick: + case DrawableSliderRepeat: return; default: diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 693a5bee0b..8acd4fc422 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; @@ -20,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override string Description => "They just won't stay still..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModTransform), typeof(OsuModMagnetised) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTransform), typeof(OsuModMagnetised), typeof(OsuModRepel) }; private const int wiggle_duration = 90; // (ms) Higher = fewer wiggles private const int wiggle_strength = 10; // Higher = stronger wiggles diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index b989500066..36d8ba0189 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index e88d09e6d9..0306c99fd5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Pooling; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs index ad656d2085..cbec5efda7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointLifetimeEntry.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 011e9fa85d..4949abccab 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index f05aea0df4..23e5cb0ad7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index fa2d2ba38c..360b28f69f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index e4df41a4fe..e137a503a5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index c48ab998ba..d83f5df7a3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; @@ -27,7 +29,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public DrawableSliderHead HeadCircle => headContainer.Child; public DrawableSliderTail TailCircle => tailContainer.Child; - public SliderBall Ball { get; private set; } + [Cached] + public DrawableSliderBall Ball { get; private set; } + public SkinnableDrawable Body { get; private set; } /// @@ -58,6 +62,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public DrawableSlider([CanBeNull] Slider s = null) : base(s) { + Ball = new DrawableSliderBall + { + GetInitialHitAction = () => HeadCircle.HitAction, + BypassAutoSizeAxes = Axes.Both, + AlwaysPresent = true, + Alpha = 0 + }; } [BackgroundDependencyLoader] @@ -71,13 +82,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, headContainer = new Container { RelativeSizeAxes = Axes.Both }, OverlayElementContainer = new Container { RelativeSizeAxes = Axes.Both, }, - Ball = new SliderBall(this) - { - GetInitialHitAction = () => HeadCircle.HitAction, - BypassAutoSizeAxes = Axes.Both, - AlwaysPresent = true, - Alpha = 0 - }, + Ball, slidingSample = new PausableSkinnableSound { Looping = true } }; @@ -314,13 +319,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables const float fade_out_time = 450; - // intentionally pile on an extra FadeOut to make it happen much faster. - Ball.FadeOut(fade_out_time / 4, Easing.Out); - switch (state) { case ArmedState.Hit: - Ball.ScaleTo(HitObject.Scale * 1.4f, fade_out_time, Easing.Out); if (SliderBody?.SnakingOut.Value == true) Body.FadeOut(40); // short fade to allow for any body colour to smoothly disappear. break; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs similarity index 64% rename from osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs index 710967b741..6bfb4e8aae 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderBall.cs @@ -1,29 +1,30 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Osu.Skinning.Default +namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition, IHasAccentColour + public class DrawableSliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition, IHasAccentColour { + public const float FOLLOW_AREA = 2.4f; + public Func GetInitialHitAction; public Color4 AccentColour @@ -32,19 +33,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default set => ball.Colour = value; } - /// - /// Whether to track accurately to the visual size of this . - /// If false, tracking will be performed at the final scale at all times. - /// - public bool InputTracksVisualSize = true; + private Drawable followCircleReceptor; + private DrawableSlider drawableSlider; + private Drawable ball; - private readonly Drawable followCircle; - private readonly DrawableSlider drawableSlider; - private readonly Drawable ball; - - public SliderBall(DrawableSlider drawableSlider) + [BackgroundDependencyLoader] + private void load(DrawableHitObject drawableSlider) { - this.drawableSlider = drawableSlider; + this.drawableSlider = (DrawableSlider)drawableSlider; Origin = Anchor.Centre; @@ -52,13 +48,18 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default Children = new[] { - followCircle = new FollowCircleContainer + new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()) { Origin = Anchor.Centre, Anchor = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Alpha = 0, - Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()), + }, + followCircleReceptor = new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true }, ball = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall()) { @@ -102,15 +103,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default tracking = value; - if (InputTracksVisualSize) - followCircle.ScaleTo(tracking ? 2.4f : 1f, 300, Easing.OutQuint); - else - { - // We need to always be tracking the final size, at both endpoints. For now, this is achieved by removing the scale duration. - followCircle.ScaleTo(tracking ? 2.4f : 1f); - } - - followCircle.FadeTo(tracking ? 1f : 0, 300, Easing.OutQuint); + followCircleReceptor.Scale = new Vector2(tracking ? FOLLOW_AREA : 1f); } } @@ -168,7 +161,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default // in valid time range Time.Current >= drawableSlider.HitObject.StartTime && Time.Current < drawableSlider.HitObject.EndTime && // in valid position range - lastScreenSpaceMousePosition.HasValue && followCircle.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && + lastScreenSpaceMousePosition.HasValue && followCircleReceptor.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && // valid action (actions?.Any(isValidTrackingAction) ?? false); @@ -206,74 +199,5 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default ball.Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); lastPosition = Position; } - - private class FollowCircleContainer : CircularContainer - { - public override bool HandlePositionalInput => true; - } - - public class DefaultFollowCircle : CompositeDrawable - { - public DefaultFollowCircle() - { - RelativeSizeAxes = Axes.Both; - - InternalChild = new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = 5, - BorderColour = Color4.Orange, - Blending = BlendingParameters.Additive, - Child = new Box - { - Colour = Color4.Orange, - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f, - } - }; - } - } - - public class DefaultSliderBall : CompositeDrawable - { - private Box box; - - [BackgroundDependencyLoader] - private void load(DrawableHitObject drawableObject, ISkinSource skin) - { - var slider = (DrawableSlider)drawableObject; - - RelativeSizeAxes = Axes.Both; - - float radius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; - - InternalChild = new CircularContainer - { - Masking = true, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(radius / OsuHitObject.OBJECT_RADIUS), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Blending = BlendingParameters.Additive, - BorderThickness = 10, - BorderColour = Color4.White, - Alpha = 1, - Child = box = new Box - { - Blending = BlendingParameters.Additive, - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - AlwaysPresent = true, - Alpha = 0 - } - }; - - slider.Tracking.BindValueChanged(trackingChanged, true); - } - - private void trackingChanged(ValueChangedEvent tracking) => - box.FadeTo(tracking.NewValue ? 0.3f : 0.05f, 200, Easing.OutQuint); - } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index 2b026e6840..70b1bd225f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 673211ac6c..1bddc603ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 64964ed396..df3a12fe33 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index c7bfdb02fb..3ffbe68b98 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index fa095edafa..53f4d21975 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs index ffeb14b0a8..841f74b751 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSpinnerBonusTick : DrawableSpinnerTick diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs index 39239c8233..6a15463a32 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs index b1815b23c9..55de5a0e8d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Objects.Drawables { public interface IRequireTracking diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs index cae2a7c36d..9e8035a1ee 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs index c72080c9e5..4af4767a3e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/SkinnableLighting.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Skinning; diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index d652db0fd4..5f43e57ed8 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 7594f7c2e0..eddd251bda 100644 --- a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs +++ b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Objects { public interface ISliderProgress diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 8b7de9e109..7b98fc48e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -1,16 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Objects; -using osuTK; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; +using osuTK; namespace osu.Game.Rulesets.Osu.Objects { @@ -34,12 +36,14 @@ namespace osu.Game.Rulesets.Osu.Objects public double TimePreempt = 600; public double TimeFadeIn = 400; - public readonly Bindable PositionBindable = new Bindable(); + private HitObjectProperty position; + + public Bindable PositionBindable => position.Bindable; public virtual Vector2 Position { - get => PositionBindable.Value; - set => PositionBindable.Value = value; + get => position.Value; + set => position.Value = value; } public float X => Position.X; @@ -51,66 +55,80 @@ namespace osu.Game.Rulesets.Osu.Objects public Vector2 StackedEndPosition => EndPosition + StackOffset; - public readonly Bindable StackHeightBindable = new Bindable(); + private HitObjectProperty stackHeight; + + public Bindable StackHeightBindable => stackHeight.Bindable; public int StackHeight { - get => StackHeightBindable.Value; - set => StackHeightBindable.Value = value; + get => stackHeight.Value; + set => stackHeight.Value = value; } public virtual Vector2 StackOffset => new Vector2(StackHeight * Scale * -6.4f); public double Radius => OBJECT_RADIUS * Scale; - public readonly Bindable ScaleBindable = new BindableFloat(1); + private HitObjectProperty scale = new HitObjectProperty(1); + + public Bindable ScaleBindable => scale.Bindable; public float Scale { - get => ScaleBindable.Value; - set => ScaleBindable.Value = value; + get => scale.Value; + set => scale.Value = value; } public virtual bool NewCombo { get; set; } - public readonly Bindable ComboOffsetBindable = new Bindable(); + private HitObjectProperty comboOffset; + + public Bindable ComboOffsetBindable => comboOffset.Bindable; public int ComboOffset { - get => ComboOffsetBindable.Value; - set => ComboOffsetBindable.Value = value; + get => comboOffset.Value; + set => comboOffset.Value = value; } - public Bindable IndexInCurrentComboBindable { get; } = new Bindable(); + private HitObjectProperty indexInCurrentCombo; + + public Bindable IndexInCurrentComboBindable => indexInCurrentCombo.Bindable; public virtual int IndexInCurrentCombo { - get => IndexInCurrentComboBindable.Value; - set => IndexInCurrentComboBindable.Value = value; + get => indexInCurrentCombo.Value; + set => indexInCurrentCombo.Value = value; } - public Bindable ComboIndexBindable { get; } = new Bindable(); + private HitObjectProperty comboIndex; + + public Bindable ComboIndexBindable => comboIndex.Bindable; public virtual int ComboIndex { - get => ComboIndexBindable.Value; - set => ComboIndexBindable.Value = value; + get => comboIndex.Value; + set => comboIndex.Value = value; } - public Bindable ComboIndexWithOffsetsBindable { get; } = new Bindable(); + private HitObjectProperty comboIndexWithOffsets; + + public Bindable ComboIndexWithOffsetsBindable => comboIndexWithOffsets.Bindable; public int ComboIndexWithOffsets { - get => ComboIndexWithOffsetsBindable.Value; - set => ComboIndexWithOffsetsBindable.Value = value; + get => comboIndexWithOffsets.Value; + set => comboIndexWithOffsets.Value = value; } - public Bindable LastInComboBindable { get; } = new Bindable(); + private HitObjectProperty lastInCombo; + + public Bindable LastInComboBindable => lastInCombo.Bindable; public bool LastInCombo { - get => LastInComboBindable.Value; - set => LastInComboBindable.Value = value; + get => lastInCombo.Value; + set => lastInCombo.Value = value; } protected OsuHitObject() diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index a698311bf7..a5468ff613 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; @@ -154,7 +156,7 @@ namespace osu.Game.Rulesets.Osu.Objects public Slider() { - SamplesBindable.CollectionChanged += (_, __) => UpdateNestedSamples(); + SamplesBindable.CollectionChanged += (_, _) => UpdateNestedSamples(); Path.Version.ValueChanged += _ => updateNestedPositions(); } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs index f893559548..35bec92354 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs index 5672283230..2a84b04030 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs index cca86361c2..7b9316f8ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index f9450062f4..87c8117b6b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index e7e64954e9..569e9b7c1c 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 1a130e96b3..0e1fe56cea 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs index 2c443cb96b..81cdf5755b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Audio; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs index d715b9a428..650d02c675 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 5c6b907e42..12256e93d0 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.ComponentModel; using osu.Framework.Input; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 207e7a4ab0..302194e91a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; @@ -118,19 +120,19 @@ namespace osu.Game.Rulesets.Osu { switch (mod) { - case OsuModAutopilot _: + case OsuModAutopilot: value |= LegacyMods.Autopilot; break; - case OsuModSpunOut _: + case OsuModSpunOut: value |= LegacyMods.SpunOut; break; - case OsuModTarget _: + case OsuModTarget: value |= LegacyMods.Target; break; - case OsuModTouchDevice _: + case OsuModTouchDevice: value |= LegacyMods.TouchDevice; break; } @@ -170,7 +172,7 @@ namespace osu.Game.Rulesets.Osu new OsuModClassic(), new OsuModRandom(), new OsuModMirror(), - new OsuModAlternate(), + new MultiMod(new OsuModAlternate(), new OsuModSingleTap()) }; case ModType.Automation: @@ -195,7 +197,7 @@ namespace osu.Game.Rulesets.Osu new OsuModApproachDifferent(), new OsuModMuted(), new OsuModNoScope(), - new OsuModMagnetised(), + new MultiMod(new OsuModMagnetised(), new OsuModRepel()), new ModAdaptiveSpeed() }; diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponent.cs b/osu.Game.Rulesets.Osu/OsuSkinComponent.cs index 1d223f231b..0abaf2c924 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponent.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu @@ -14,6 +16,6 @@ namespace osu.Game.Rulesets.Osu protected override string RulesetPrefix => OsuRuleset.SHORT_NAME; - protected override string ComponentName => Component.ToString().ToLower(); + protected override string ComponentName => Component.ToString().ToLowerInvariant(); } } diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs index 71657ed532..fcf079b6aa 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu { public enum OsuSkinComponents diff --git a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs index c842874635..7fffb1871f 100644 --- a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index e231550e3e..5a3d882ef0 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Replays { double endTime = prev.GetEndTime(); - HitWindows hitWindows = null; + HitWindows? hitWindows = null; switch (h) { @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.Replays hitWindows = slider.TailCircle.HitWindows; break; - case Spinner _: + case Spinner: hitWindows = defaultHitWindows; break; } @@ -243,7 +243,7 @@ namespace osu.Game.Rulesets.Osu.Replays } double timeDifference = ApplyModsToTimeDelta(lastFrame.Time, h.StartTime); - OsuReplayFrame lastLastFrame = Frames.Count >= 2 ? (OsuReplayFrame)Frames[^2] : null; + OsuReplayFrame? lastLastFrame = Frames.Count >= 2 ? (OsuReplayFrame)Frames[^2] : null; if (timeDifference > 0) { diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 3db81d70da..85060261fe 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Replays Actions.AddRange(actions); } - public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) + public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame? lastFrame = null) { Position = currentFrame.Position; if (currentFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs index dafe63a6d1..05fbac625e 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHitWindows.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Scoring diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index ab0c0850dc..34a1bd40e9 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; @@ -25,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Scoring { switch (hitObject) { - case HitCircle _: + case HitCircle: return new OsuHitCircleJudgementResult(hitObject, judgement); default: diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs index cb68d4b7a7..40e9f69963 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/CirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs index a522367fe6..251fd8d948 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultApproachCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs new file mode 100644 index 0000000000..b77d4addee --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultFollowCircle.cs @@ -0,0 +1,68 @@ +// 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 osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Utils; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning.Default +{ + public class DefaultFollowCircle : FollowCircle + { + public DefaultFollowCircle() + { + InternalChild = new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 5, + BorderColour = Color4.Orange, + Blending = BlendingParameters.Additive, + Child = new Box + { + Colour = Color4.Orange, + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + } + }; + } + + protected override void OnTrackingChanged(ValueChangedEvent tracking) + { + Debug.Assert(ParentObject != null); + + const float duration = 300f; + + if (ParentObject.Judged) + return; + + if (tracking.NewValue) + { + if (Precision.AlmostEquals(0, Alpha)) + this.ScaleTo(1); + + this.ScaleTo(DrawableSliderBall.FOLLOW_AREA, duration, Easing.OutQuint) + .FadeTo(1f, duration, Easing.OutQuint); + } + else + { + this.ScaleTo(DrawableSliderBall.FOLLOW_AREA * 1.2f, duration / 2, Easing.OutQuint) + .FadeTo(0, duration / 2, Easing.OutQuint); + } + } + + protected override void OnSliderEnd() + { + const float fade_duration = 300; + + // intentionally pile on an extra FadeOut to make it happen much faster + this.ScaleTo(1, fade_duration, Easing.OutQuint); + this.FadeOut(fade_duration / 2, Easing.OutQuint); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs new file mode 100644 index 0000000000..97bb4a3697 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSliderBall.cs @@ -0,0 +1,111 @@ +// Copyright (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.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning.Default +{ + public class DefaultSliderBall : CompositeDrawable + { + private Box box = null!; + + [Resolved(canBeNull: true)] + private DrawableHitObject? parentObject { get; set; } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + RelativeSizeAxes = Axes.Both; + + float radius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; + + InternalChild = new CircularContainer + { + Masking = true, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(radius / OsuHitObject.OBJECT_RADIUS), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + BorderThickness = 10, + BorderColour = Color4.White, + Alpha = 1, + Child = box = new Box + { + Blending = BlendingParameters.Additive, + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + AlwaysPresent = true, + Alpha = 0 + } + }; + + if (parentObject != null) + { + var slider = (DrawableSlider)parentObject; + slider.Tracking.BindValueChanged(trackingChanged, true); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (parentObject != null) + { + parentObject.ApplyCustomUpdateState += updateStateTransforms; + updateStateTransforms(parentObject, parentObject.State.Value); + } + } + + private void trackingChanged(ValueChangedEvent tracking) => + box.FadeTo(tracking.NewValue ? 0.3f : 0.05f, 200, Easing.OutQuint); + + private void updateStateTransforms(DrawableHitObject drawableObject, ArmedState state) + { + // Gets called by slider ticks, tails, etc., leading to duplicated + // animations which may negatively affect performance + if (drawableObject is not DrawableSlider) + return; + + const float fade_duration = 450f; + + using (BeginAbsoluteSequence(drawableObject.StateUpdateTime)) + { + this.FadeIn() + .ScaleTo(1f); + } + + using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime)) + { + // intentionally pile on an extra FadeOut to make it happen much faster + this.FadeOut(fade_duration / 4, Easing.Out); + + switch (state) + { + case ArmedState.Hit: + this.ScaleTo(1.4f, fade_duration, Easing.Out); + break; + } + } + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (parentObject != null) + parentObject.ApplyCustomUpdateState -= updateStateTransforms; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs index df33bf52be..a215b3b1f0 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs index 4ea0831627..60489c1b22 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DefaultSpinnerDisc.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -88,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default { base.LoadComplete(); - complete.BindValueChanged(complete => updateComplete(complete.NewValue, 200)); + complete.BindValueChanged(complete => updateDiscColour(complete.NewValue, 200)); drawableSpinner.ApplyCustomUpdateState += updateStateTransforms; updateStateTransforms(drawableSpinner, drawableSpinner.State.Value); @@ -135,6 +137,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default this.ScaleTo(initial_scale); this.RotateTo(0); + updateDiscColour(false); + using (BeginDelayedSequence(spinner.TimePreempt / 2)) { // constant ambient rotation to give the spinner "spinning" character. @@ -175,12 +179,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default } } - // transforms we have from completing the spinner will be rolled back, so reapply immediately. - using (BeginAbsoluteSequence(spinner.StartTime - spinner.TimePreempt)) - updateComplete(state == ArmedState.Hit, 0); + if (drawableSpinner.Result?.TimeCompleted is double completionTime) + { + using (BeginAbsoluteSequence(completionTime)) + updateDiscColour(true, 200); + } } - private void updateComplete(bool complete, double duration) + private void updateDiscColour(bool complete, double duration = 0) { var colour = complete ? completeColour : normalColour; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs index db077f009d..94f93807d4 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/DrawableSliderPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Lines; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs index 510ed225a8..6ee8a12132 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ExplodePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs index 06ee64d8b3..98a8b39f6f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/FlashPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs index f5e01b802e..2360bc2238 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/GlowPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/IHasMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/IHasMainCirclePiece.cs index 8bb7629542..0ba7998d43 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/IHasMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/IHasMainCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Skinning.Default diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs b/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs index 506f679836..a1cfd170a6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/KiaiFlash.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Audio.Track; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs index d7ebe9333d..4acc406ae1 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs index d73c94eb9b..8d8d9e0d94 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ManualSliderBody.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs index 43d8d1e27f..f6759c1093 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/NumberPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs index 8602ebc88b..83f7bb8904 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/PlaySliderBody.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs index 0009ffc586..8f682d02f6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/ReverseArrowPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs index 7f10a7bf56..b941a86171 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/RingPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs index 7e6df759f8..9841cc7cdf 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SliderBody.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs index 42d3840158..86dd5f5c74 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SnakingSliderBody.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs index a1184a15cd..a9b7ddf86f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerBackgroundLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs index 67b5ed5410..ef7b4c2c96 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerCentreLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs index f574ae589e..b7ec9e9799 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerFill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs index 4313e99b13..f9ed8b8721 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerRotationTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs index a5205bbb8c..df72223214 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerSpmCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs index e518ae1da8..b66cbe41b6 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/SpinnerTicks.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs index fa23c60d57..7399ddbd1b 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/TrianglesPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics.Backgrounds; namespace osu.Game.Rulesets.Osu.Skinning.Default diff --git a/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs new file mode 100644 index 0000000000..321705d25e --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/FollowCircle.cs @@ -0,0 +1,75 @@ +// Copyright (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.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public abstract class FollowCircle : CompositeDrawable + { + [Resolved] + protected DrawableHitObject? ParentObject { get; private set; } + + protected FollowCircle() + { + RelativeSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + ((DrawableSlider?)ParentObject)?.Tracking.BindValueChanged(OnTrackingChanged, true); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (ParentObject != null) + { + ParentObject.HitObjectApplied += onHitObjectApplied; + onHitObjectApplied(ParentObject); + + ParentObject.ApplyCustomUpdateState += updateStateTransforms; + updateStateTransforms(ParentObject, ParentObject.State.Value); + } + } + + private void onHitObjectApplied(DrawableHitObject drawableObject) + { + this.ScaleTo(1f) + .FadeOut(); + } + + private void updateStateTransforms(DrawableHitObject drawableObject, ArmedState state) + { + // Gets called by slider ticks, tails, etc., leading to duplicated + // animations which may negatively affect performance + if (drawableObject is not DrawableSlider) + return; + + using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime)) + OnSliderEnd(); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (ParentObject != null) + { + ParentObject.HitObjectApplied -= onHitObjectApplied; + ParentObject.ApplyCustomUpdateState -= updateStateTransforms; + } + } + + protected abstract void OnTrackingChanged(ValueChangedEvent tracking); + + protected abstract void OnSliderEnd(); + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/IHasApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/IHasApproachCircle.cs index 7fbc5b144b..8ebab97503 100644 --- a/osu.Game.Rulesets.Osu/Skinning/IHasApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/IHasApproachCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Rulesets.Osu.Skinning diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/KiaiFlashingDrawable.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/KiaiFlashingDrawable.cs index 4ee28d05b5..152ed5c3d9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/KiaiFlashingDrawable.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/KiaiFlashingDrawable.cs @@ -7,8 +7,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; -#nullable enable - namespace osu.Game.Rulesets.Osu.Skinning.Legacy { internal class KiaiFlashingDrawable : BeatSyncedContainer diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs index 6a2cb871b1..03406d37ff 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyApproachCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs index b2ffc171be..4465f9c266 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Osu.UI.Cursor; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs index b511444c44..ee75b8a857 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorParticles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs index 75d847d54d..e62754c6ce 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorTrail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.cs new file mode 100644 index 0000000000..5b7da5a1ba --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyFollowCircle.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.Diagnostics; +using osu.Framework.Bindables; +using osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Osu.Skinning.Legacy +{ + public class LegacyFollowCircle : FollowCircle + { + public LegacyFollowCircle(Drawable animationContent) + { + // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x + animationContent.Scale *= 0.5f; + animationContent.Anchor = Anchor.Centre; + animationContent.Origin = Anchor.Centre; + + RelativeSizeAxes = Axes.Both; + InternalChild = animationContent; + } + + protected override void OnTrackingChanged(ValueChangedEvent tracking) + { + Debug.Assert(ParentObject != null); + + if (ParentObject.Judged) + return; + + double remainingTime = Math.Max(0, ParentObject.HitStateUpdateTime - Time.Current); + + // Note that the scale adjust here is 2 instead of DrawableSliderBall.FOLLOW_AREA to match legacy behaviour. + // This means the actual tracking area for gameplay purposes is larger than the sprite (but skins may be accounting for this). + if (tracking.NewValue) + { + // TODO: Follow circle should bounce on each slider tick. + this.ScaleTo(0.5f).ScaleTo(2f, Math.Min(180f, remainingTime), Easing.Out) + .FadeTo(0).FadeTo(1f, Math.Min(60f, remainingTime)); + } + else + { + // TODO: Should animate only at the next slider tick if we want to match stable perfectly. + this.ScaleTo(4f, 100) + .FadeTo(0f, 100); + } + } + + protected override void OnSliderEnd() + { + this.ScaleTo(1.6f, 200, Easing.Out) + .FadeOut(200, Easing.In); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index dd6226e19b..1b2ab82044 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -16,8 +16,6 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; -#nullable enable - namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public class LegacyMainCirclePiece : CompositeDrawable diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs index a58f62736b..d5cc469ca9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyNewStyleSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -124,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy break; - case DrawableSpinnerBonusTick _: + case DrawableSpinnerBonusTick: if (state == ArmedState.Hit) glow.FlashColour(Color4.White, 200); diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs index ea122d47bb..a5a765fc02 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyOldStyleSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs index 7a071b5a03..ff384ee7fc 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index e4e1483665..414879f42d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -5,6 +5,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; using osuTK.Graphics; @@ -16,8 +18,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private readonly ISkin skin; - private Sprite layerNd; - private Sprite layerSpec; + [Resolved(canBeNull: true)] + private DrawableHitObject? parentObject { get; set; } + + private Sprite layerNd = null!; + private Sprite layerSpec = null!; public LegacySliderBall(Drawable animationContent, ISkin skin) { @@ -56,6 +61,17 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + if (parentObject != null) + { + parentObject.ApplyCustomUpdateState += updateStateTransforms; + updateStateTransforms(parentObject, parentObject.State.Value); + } + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); @@ -66,5 +82,28 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy layerNd.Rotation = -appliedRotation; layerSpec.Rotation = -appliedRotation; } + + private void updateStateTransforms(DrawableHitObject drawableObject, ArmedState _) + { + // Gets called by slider ticks, tails, etc., leading to duplicated + // animations which in this case have no visual impact (due to + // instant fade) but may negatively affect performance + if (drawableObject is not DrawableSlider) + return; + + using (BeginAbsoluteSequence(drawableObject.StateUpdateTime)) + this.FadeIn(); + + using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime)) + this.FadeOut(); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (parentObject != null) + parentObject.ApplyCustomUpdateState -= updateStateTransforms; + } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs index 29a0745193..dbfec14eb2 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBody.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs index 7de2b8c7fa..ab39d7c6ef 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderHeadHitCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs index 93aba608e6..004222ad7a 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 572185e6e1..885a2c12fb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -39,11 +41,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy return this.GetAnimation(component.LookupName, false, false); case OsuSkinComponents.SliderFollowCircle: - var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true); - if (followCircle != null) - // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x - followCircle.Scale *= 0.5f; - return followCircle; + var followCircleContent = this.GetAnimation("sliderfollowcircle", true, true, true); + if (followCircleContent != null) + return new LegacyFollowCircle(followCircleContent); + + return null; case OsuSkinComponents.SliderBall: var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: ""); diff --git a/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs b/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs index 55257106e2..0b45c770ba 100644 --- a/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs +++ b/osu.Game.Rulesets.Osu/Skinning/NonPlayfieldSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs index 24f9217a5f..5d8a2ff606 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinColour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Skinning { public enum OsuSkinColour diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index 7b9cf8e1d1..306a1e38b9 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Osu.Skinning { public enum OsuSkinConfiguration diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 6c76da7925..acf32da73f 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs index b4de91562b..afa54c2dfb 100644 --- a/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs +++ b/osu.Game.Rulesets.Osu/UI/AnyOrderHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 62cab4d6d7..c1d518a843 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Runtime.InteropServices; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs index 0e7d7cdcf3..15ef7e538b 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index b60ea5da21..533db3ddfe 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs index 573c408a78..03ef79a262 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index df3f7c64e4..5f430dc921 100644 --- a/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs index 5d8ea035a7..0dac3307c2 100644 --- a/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs +++ b/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/UI/ObjectOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/ObjectOrderedHitPolicy.cs index 83f205deac..6330208d37 100644 --- a/osu.Game.Rulesets.Osu/UI/ObjectOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu/UI/ObjectOrderedHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Objects; @@ -35,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.UI switch (obj) { - case DrawableSpinner _: + case DrawableSpinner: continue; case DrawableSlider slider: diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index bc1e80cd12..3179b37d5a 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -94,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.UI // note: `Slider`'s `ProxiedLayer` is added when its nested `DrawableHitCircle` is loaded. switch (drawable) { - case DrawableSpinner _: + case DrawableSpinner: spinnerProxies.Add(drawable.CreateProxy()); break; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index 0d1a5a8304..80f4eb3000 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs b/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs index 1304dfe416..5964a9b9b6 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index 4d4340936d..fc3f89a836 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index a638019e69..eff4b30362 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game.Rulesets.Osu/UI/StartTimeOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/StartTimeOrderedHitPolicy.cs index 0173156246..edc3ba0818 100644 --- a/osu.Game.Rulesets.Osu/UI/StartTimeOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu/UI/StartTimeOrderedHitPolicy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index 266f7d1251..5e827d4782 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils_Reposition.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils_Reposition.cs index a77d1f8b0f..a9ae313a31 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils_Reposition.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils_Reposition.cs @@ -10,8 +10,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osuTK; -#nullable enable - namespace osu.Game.Rulesets.Osu.Utils { public static partial class OsuHitObjectGenerationUtils @@ -90,11 +88,11 @@ namespace osu.Game.Rulesets.Osu.Utils switch (hitObject) { - case HitCircle _: + case HitCircle: shift = clampHitCircleToPlayfield(current); break; - case Slider _: + case Slider: shift = clampSliderToPlayfield(current); break; } @@ -196,7 +194,28 @@ namespace osu.Game.Rulesets.Osu.Utils private static Vector2 clampSliderToPlayfield(WorkingObject workingObject) { var slider = (Slider)workingObject.HitObject; - var possibleMovementBounds = calculatePossibleMovementBounds(slider); + var possibleMovementBounds = CalculatePossibleMovementBounds(slider); + + // The slider rotation applied in computeModifiedPosition might make it impossible to fit the slider into the playfield + // For example, a long horizontal slider will be off-screen when rotated by 90 degrees + // In this case, limit the rotation to either 0 or 180 degrees + if (possibleMovementBounds.Width < 0 || possibleMovementBounds.Height < 0) + { + float currentRotation = getSliderRotation(slider); + float diff1 = getAngleDifference(workingObject.RotationOriginal, currentRotation); + float diff2 = getAngleDifference(workingObject.RotationOriginal + MathF.PI, currentRotation); + + if (diff1 < diff2) + { + RotateSlider(slider, workingObject.RotationOriginal - getSliderRotation(slider)); + } + else + { + RotateSlider(slider, workingObject.RotationOriginal + MathF.PI - getSliderRotation(slider)); + } + + possibleMovementBounds = CalculatePossibleMovementBounds(slider); + } var previousPosition = workingObject.PositionModified; @@ -241,10 +260,12 @@ namespace osu.Game.Rulesets.Osu.Utils /// Calculates a which contains all of the possible movements of the slider (in relative X/Y coordinates) /// such that the entire slider is inside the playfield. /// + /// The for which to calculate a movement bounding box. + /// A which contains all of the possible movements of the slider such that the entire slider is inside the playfield. /// /// If the slider is larger than the playfield, the returned may have negative width/height. /// - private static RectangleF calculatePossibleMovementBounds(Slider slider) + public static RectangleF CalculatePossibleMovementBounds(Slider slider) { var pathPositions = new List(); slider.Path.GetPathToProgress(pathPositions, 0, 1); @@ -355,6 +376,18 @@ namespace osu.Game.Rulesets.Osu.Utils return MathF.Atan2(endPositionVector.Y, endPositionVector.X); } + /// + /// Get the absolute difference between 2 angles measured in Radians. + /// + /// The first angle + /// The second angle + /// The absolute difference with interval [0, MathF.PI) + private static float getAngleDifference(float angle1, float angle2) + { + float diff = MathF.Abs(angle1 - angle2) % (MathF.PI * 2); + return MathF.Min(diff, MathF.PI * 2 - diff); + } + public class ObjectPositionInfo { /// @@ -397,6 +430,7 @@ namespace osu.Game.Rulesets.Osu.Utils private class WorkingObject { + public float RotationOriginal { get; } public Vector2 PositionOriginal { get; } public Vector2 PositionModified { get; set; } public Vector2 EndPositionModified { get; set; } @@ -407,6 +441,7 @@ namespace osu.Game.Rulesets.Osu.Utils public WorkingObject(ObjectPositionInfo positionInfo) { PositionInfo = positionInfo; + RotationOriginal = HitObject is Slider slider ? getSliderRotation(slider) : 0; PositionModified = PositionOriginal = HitObject.Position; EndPositionModified = HitObject.EndPosition; } diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs index e4f4bbfd53..a55b461876 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs index 567220f316..385ba48707 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Foundation; using osu.Framework.iOS; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs index 9fde65a074..1ebbd61a94 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.iOS; using UIKit; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs index a099795d12..01719bfea6 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs index 6d4cac0ebe..6a585b840d 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs index ea877c9e17..7355e1dbca 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Input.Events; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs index e3c1613bd9..5915b9fdfa 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index 33c2ba532e..06c06f6e28 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Rulesets.Taiko.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs index 55eb2fa66b..16f17f4131 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs index ac01508081..09a6a2f16c 100644 --- a/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/HitObjectApplicationTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs index 3090facf8c..ca2f8102b7 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TaikoModTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Mods diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs index 7abbb9d186..0b28bfee2e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Rulesets.Taiko.Mods; diff --git a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs index a83cc16413..917462c128 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Mods/TestSceneTaikoModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Mods; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs index 69250a14e1..82be26b422 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs index 16c4148d15..ad6f08dbd4 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs index 26a4e85fe5..2d27e0e40e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs index c4ee68206c..d5a97f8f88 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index 920a7cd1a1..ef95358d34 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Humanizer; @@ -142,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning createDrawableRuleset(); assertStateAfterResult(new JudgementResult(new Swell(), new TaikoSwellJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Clear); - AddUntilStep($"state reverts to {expectedStateAfterClear.ToString().ToLower()}", () => allMascotsIn(expectedStateAfterClear)); + AddUntilStep($"state reverts to {expectedStateAfterClear.ToString().ToLowerInvariant()}", () => allMascotsIn(expectedStateAfterClear)); } private void setBeatmap(bool kiai = false) @@ -193,7 +195,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning { TaikoMascotAnimationState[] mascotStates = null; - AddStep($"{judgementResult.Type.ToString().ToLower()} result for {judgementResult.Judgement.GetType().Name.Humanize(LetterCasing.LowerCase)}", + AddStep($"{judgementResult.Type.ToString().ToLowerInvariant()} result for {judgementResult.Judgement.GetType().Name.Humanize(LetterCasing.LowerCase)}", () => { applyNewResult(judgementResult); @@ -202,7 +204,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning Schedule(() => mascotStates = animatedMascots.Select(mascot => mascot.State.Value).ToArray()); }); - AddAssert($"state is {expectedState.ToString().ToLower()}", () => mascotStates.All(state => state == expectedState)); + AddAssert($"state is {expectedState.ToString().ToLowerInvariant()}", () => mascotStates.All(state => state == expectedState)); } private void applyNewResult(JudgementResult judgementResult) diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs index 1cba6c9008..f87e0355ad 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs index 10fca30865..f342bfe78e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs index 419e100296..e1a3c736fe 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index 6f2fcd08f1..52d24b567f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs index 9882c7bc90..954b4be7f3 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Testing; using osu.Framework.Timing; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index b3f6a733d3..796f5721bb 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs index 51332a1ece..579b461624 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs index a039e84106..c86f8cb8d2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; @@ -22,22 +24,25 @@ namespace osu.Game.Rulesets.Taiko.Tests new object[] { LegacyMods.DoubleTime, new[] { typeof(TaikoModDoubleTime) } }, new object[] { LegacyMods.Relax, new[] { typeof(TaikoModRelax) } }, new object[] { LegacyMods.HalfTime, new[] { typeof(TaikoModHalfTime) } }, - new object[] { LegacyMods.Nightcore, new[] { typeof(TaikoModNightcore) } }, new object[] { LegacyMods.Flashlight, new[] { typeof(TaikoModFlashlight) } }, new object[] { LegacyMods.Autoplay, new[] { typeof(TaikoModAutoplay) } }, - new object[] { LegacyMods.Perfect, new[] { typeof(TaikoModPerfect) } }, new object[] { LegacyMods.Random, new[] { typeof(TaikoModRandom) } }, - new object[] { LegacyMods.Cinema, new[] { typeof(TaikoModCinema) } }, new object[] { LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(TaikoModHardRock), typeof(TaikoModDoubleTime) } } }; + [TestCaseSource(nameof(taiko_mod_mapping))] + [TestCase(LegacyMods.Cinema, new[] { typeof(TaikoModCinema) })] + [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(TaikoModCinema) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(TaikoModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(TaikoModPerfect) })] + public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods); + [TestCaseSource(nameof(taiko_mod_mapping))] [TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(TaikoModCinema) })] [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(TaikoModNightcore) })] [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(TaikoModPerfect) })] - public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods); - - [TestCaseSource(nameof(taiko_mod_mapping))] public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods); protected override Ruleset CreateRuleset() => new TaikoRuleset(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs index f33c738b04..867ee13bea 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs index c389a05566..eceeaf5083 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollJudgements.cs index 060c3c9443..82dfaecaa4 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollJudgements.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs index 5c7e3954e8..c787683620 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneFlyingHits.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs index c2f251fcb6..b337519c85 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index 87c936d386..5350a81f55 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs index e5c9358c26..e6c28a532a 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs index 75049b7467..bd546b16f2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs index 221d715a35..674ac5670f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoHitObjectSamples.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Reflection; using NUnit.Framework; using osu.Framework.IO.Stores; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs index cd7511241a..5e984b19f8 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.cs new file mode 100644 index 0000000000..13df24c988 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayerLegacySkin.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.Taiko.Mods; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneTaikoPlayerLegacySkin : LegacySkinPlayerTestScene + { + protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset(); + + protected override TestPlayer CreatePlayer(Ruleset ruleset) + { + SelectedMods.Value = new[] { new TaikoModClassic() }; + return base.CreatePlayer(ruleset); + } + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index eec88d7bf8..cdfab4a215 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; @@ -42,7 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Tests AddStep("Setup judgements", () => { judged = false; - Player.ScoreProcessor.NewJudgement += b => judged = true; + Player.ScoreProcessor.NewJudgement += _ => judged = true; }); AddUntilStep("swell judged", () => judged); AddAssert("failed", () => Player.GameplayState.HasFailed); 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 ce468d399b..51d4bbc630 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 @@ -1,7 +1,6 @@  - diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs index 41fe63a553..6ff5cdf7e5 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index b1d8575de4..524565a863 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs index ae33c184d0..4c7b140832 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Objects; @@ -24,11 +27,6 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing /// public readonly HitType? HitType; - /// - /// The index of the object in the beatmap. - /// - public readonly int ObjectIndex; - /// /// Whether the object should carry a penalty due to being hittable using special techniques /// making it easier to do so. @@ -42,16 +40,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing /// The gameplay preceding . /// The gameplay preceding . /// The rate of the gameplay clock. Modified by speed-changing mods. - /// The index of the object in the beatmap. - public TaikoDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject lastLastObject, double clockRate, int objectIndex) - : base(hitObject, lastObject, clockRate) + /// The list of s in the current beatmap. + /// /// The position of this in the list. + public TaikoDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject lastLastObject, double clockRate, List objects, int index) + : base(hitObject, lastObject, clockRate, objects, index) { var currentHit = hitObject as Hit; Rhythm = getClosestRhythm(lastObject, lastLastObject, clockRate); HitType = currentHit?.Type; - - ObjectIndex = objectIndex; } /// diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectRhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectRhythm.cs index ea6a224094..526d20e7d7 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectRhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectRhythm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing { /// diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs index 0c17ca66b9..3727c0e4b7 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs index 973e55f4b4..4a2b97a4cb 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; @@ -106,7 +108,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills if (!samePattern(start, mostRecentPatternsToCompare)) continue; - int notesSince = hitObject.ObjectIndex - rhythmHistory[start].ObjectIndex; + int notesSince = hitObject.Index - rhythmHistory[start].Index; penalty *= repetitionPenalty(notesSince); break; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs index cabfd231d8..c2e1dd4f82 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/SingleKeyStamina.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs index 61bcbfa59d..67b628a814 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs index 3dc5438072..380ab4a4fc 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Taiko.Difficulty @@ -55,9 +56,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values) + public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values); + base.FromDatabaseAttributes(values, onlineInfo); MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; StarRating = values[ATTRIB_ID_DIFFICULTY]; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 1aa31c6fe4..228856cbe9 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -46,13 +48,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { - List taikoDifficultyHitObjects = new List(); + List taikoDifficultyHitObjects = new List(); for (int i = 2; i < beatmap.HitObjects.Count; i++) { taikoDifficultyHitObjects.Add( new TaikoDifficultyHitObject( - beatmap.HitObjects[i], beatmap.HitObjects[i - 1], beatmap.HitObjects[i - 2], clockRate, i + beatmap.HitObjects[i], beatmap.HitObjects[i - 1], beatmap.HitObjects[i - 2], clockRate, taikoDifficultyHitObjects, taikoDifficultyHitObjects.Count ) ); } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs index fa5c0202dd..68d0038b24 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 8d99fd3b87..2c2dbddf13 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -33,13 +35,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh); countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss); - double multiplier = 1.1; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things - - if (score.Mods.Any(m => m is ModNoFail)) - multiplier *= 0.90; + double multiplier = 1.12; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things if (score.Mods.Any(m => m is ModHidden)) - multiplier *= 1.10; + multiplier *= 1.075; + + if (score.Mods.Any(m => m is ModEasy)) + multiplier *= 0.975; double difficultyValue = computeDifficultyValue(score, taikoAttributes); double accuracyValue = computeAccuracyValue(score, taikoAttributes); @@ -59,12 +61,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty private double computeDifficultyValue(ScoreInfo score, TaikoDifficultyAttributes attributes) { - double difficultyValue = Math.Pow(5 * Math.Max(1.0, attributes.StarRating / 0.175) - 4.0, 2.25) / 450.0; + double difficultyValue = Math.Pow(5 * Math.Max(1.0, attributes.StarRating / 0.115) - 4.0, 2.25) / 1150.0; double lengthBonus = 1 + 0.1 * Math.Min(1.0, totalHits / 1500.0); difficultyValue *= lengthBonus; - difficultyValue *= Math.Pow(0.985, countMiss); + difficultyValue *= Math.Pow(0.986, countMiss); + + if (score.Mods.Any(m => m is ModEasy)) + difficultyValue *= 0.980; if (score.Mods.Any(m => m is ModHidden)) difficultyValue *= 1.025; @@ -72,7 +77,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty if (score.Mods.Any(m => m is ModFlashlight)) difficultyValue *= 1.05 * lengthBonus; - return difficultyValue * score.Accuracy; + return difficultyValue * Math.Pow(score.Accuracy, 1.5); } private double computeAccuracyValue(ScoreInfo score, TaikoDifficultyAttributes attributes) @@ -80,10 +85,16 @@ namespace osu.Game.Rulesets.Taiko.Difficulty if (attributes.GreatHitWindow <= 0) return 0; - double accValue = Math.Pow(150.0 / attributes.GreatHitWindow, 1.1) * Math.Pow(score.Accuracy, 15) * 22.0; + double accuracyValue = Math.Pow(140.0 / attributes.GreatHitWindow, 1.1) * Math.Pow(score.Accuracy, 12.0) * 27; - // Bonus for many objects - it's harder to keep good accuracy up for longer - return accValue * Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); + double lengthBonus = Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); + accuracyValue *= lengthBonus; + + // Slight HDFL Bonus for accuracy. + if (score.Mods.Any(m => m is ModFlashlight) && score.Mods.Any(m => m is ModHidden)) + accuracyValue *= 1.10 * lengthBonus; + + return accuracyValue; } private int totalHits => countGreat + countOk + countMeh + countMiss; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs index eb07ce7635..dfbcd1cce3 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs index b02e3aa9ba..86f32ca17c 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index 0d0fd136a7..df1450bf77 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Taiko.Objects; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs index 6b651fd739..e201d58f7a 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs index 95fa82a0f2..1d08af47d3 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs index 01b90c4bca..4c67a37417 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs index 59249e6bf4..e49043e58e 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs index 587a4efecb..acb17fc455 100644 --- a/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs index 3e97b4e322..e52dae4b0c 100644 --- a/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs index 918afde1dd..dd0ff61c10 100644 --- a/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs index a465638779..6107c8009a 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs index 161799c980..1c1a5c325f 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs index ab3b729307..80e4e8f406 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 0d91002f4b..be128d85b5 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 647ad7853d..5f2587a5d5 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index e272c1a4ef..f8e3303752 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 06495ad9f4..f2397aba22 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index 4d61efd3ee..b2ac0b7f03 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index 4b74b4991e..6c01bae027 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs index fee0cb2744..d1c192f7fa 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index 5a6f57bc36..233179c9ec 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.UI; @@ -16,6 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Mods { drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset; drawableTaikoRuleset.LockPlayfieldAspect.Value = false; + + var playfield = (TaikoPlayfield)drawableRuleset.Playfield; + playfield.ClassicHitTargetPosition.Value = true; } public void Update(Playfield playfield) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs index 84aa5e6bba..873aa7f992 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 99a064d35f..564d023c5a 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Game.Beatmaps; using osu.Game.Configuration; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs index bc38213acc..b19c2eaccf 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs @@ -1,12 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index ad6fdf59e2..a37e1c6f5c 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index beec785fe8..fe02a6caf9 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Layout; @@ -15,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModFlashlight : ModFlashlight { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; [SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")] public override BindableFloat SizeMultiplier { get; } = new BindableFloat diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs index 68d6305fbf..ddfc2d1174 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index 8437dfe52e..7780936e7d 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; @@ -8,7 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModHardRock : ModHardRock { - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; /// /// Multiplier factor added to the scrolling speed. diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs index 7f565cb82d..fe3e5ca11c 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -16,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public class TaikoModHidden : ModHidden, IApplicableToDrawableRuleset { public override string Description => @"Beats fade out before you hit them!"; - public override double ScoreMultiplier => 1.06; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; /// /// How far away from the hit target should hitobjects start to fade out. @@ -46,8 +48,8 @@ namespace osu.Game.Rulesets.Taiko.Mods { switch (hitObject) { - case DrawableDrumRollTick _: - case DrawableHit _: + case DrawableDrumRollTick: + case DrawableHit: double preempt = drawableRuleset.TimeRange.Value / drawableRuleset.ControlPointAt(hitObject.HitObject.StartTime).Multiplier; double start = hitObject.HitObject.StartTime - preempt * fade_out_start_time; double duration = preempt * fade_out_duration; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs index 0f1e0b2885..874e15406d 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModMuted.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Objects; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs index 5377eb1072..e02a16f62f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Objects; @@ -8,6 +10,6 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModNightcore : ModNightcore { - public override double ScoreMultiplier => 1.12; + public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs index bf1006f1aa..57ecf0224f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs index b107b14a03..c65dba243b 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModRandom.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModRandom.cs index 307a37bf2e..f58f59aaf2 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModRandom.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModRandom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs index 7be70d9ac3..a3a644ab99 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs index 7a0f6c7cd1..037e376ad2 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs index 3cb337c41d..c9cba59760 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index bbfc02f975..d2eba0eb54 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -9,14 +11,16 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class BarLine : TaikoHitObject, IBarLine { + private HitObjectProperty major; + + public Bindable MajorBindable => major.Bindable; + public bool Major { - get => MajorBindable.Value; - set => MajorBindable.Value = value; + get => major.Value; + set => major.Value = value; } - public readonly Bindable MajorBindable = new BindableBool(); - public override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index d653f01db6..e4806c4a12 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index b84db513f7..04ed6d0b87 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index e24923e482..705a0a8047 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs index 3253c1ce5a..5ce72028e0 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 863672b3fa..484f125a09 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 9c22e34387..01ee91a5c7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; 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 77243218ce..2451c79772 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index d4ea9ed29f..b2a54176fb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index eb64ba72f2..9bbd3670fa 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs index 70d4371e99..4b58cc60e6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoStrongableHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 0e93ad7e73..e1619e2857 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; using System; using System.Threading; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 9d0336441e..433fdab908 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; 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 2038da9344..787079bfee 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -1,10 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Audio; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK.Graphics; @@ -12,19 +15,21 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class Hit : TaikoStrongableHitObject, IHasDisplayColour { - public readonly Bindable TypeBindable = new Bindable(); + private HitObjectProperty type; - public Bindable DisplayColour { get; } = new Bindable(COLOUR_CENTRE); + public Bindable TypeBindable => type.Bindable; /// /// The that actuates this . /// public HitType Type { - get => TypeBindable.Value; - set => TypeBindable.Value = value; + get => type.Value; + set => type.Value = value; } + public Bindable DisplayColour { get; } = new Bindable(COLOUR_CENTRE); + public static readonly Color4 COLOUR_CENTRE = Color4Extensions.FromHex(@"bb1177"); public static readonly Color4 COLOUR_RIM = Color4Extensions.FromHex(@"2299bb"); @@ -36,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Objects DisplayColour.Value = Type == HitType.Centre ? COLOUR_CENTRE : COLOUR_RIM; }); - SamplesBindable.BindCollectionChanged((_, __) => updateTypeFromSamples()); + SamplesBindable.BindCollectionChanged((_, _) => updateTypeFromSamples()); } private void updateTypeFromSamples() diff --git a/osu.Game.Rulesets.Taiko/Objects/HitType.cs b/osu.Game.Rulesets.Taiko/Objects/HitType.cs index 17b3fdbd04..eae7fa683a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/HitType.cs +++ b/osu.Game.Rulesets.Taiko/Objects/HitType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Taiko.Objects { /// diff --git a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs index 302f940ef4..18f47b7cff 100644 --- a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs index 3b427e48c5..628c41d878 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; 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 eeae6e79f8..cb91c46b4d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index bdc0478195..43830cb528 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 1a1fde1990..3aba5c571b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs index 6e0f6a3109..d4d59d5d44 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Threading; using osu.Framework.Bindables; @@ -39,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Objects protected TaikoStrongableHitObject() { IsStrongBindable.BindValueChanged(_ => updateSamplesFromType()); - SamplesBindable.BindCollectionChanged((_, __) => updateTypeFromSamples()); + SamplesBindable.BindCollectionChanged((_, _) => updateTypeFromSamples()); } private void updateTypeFromSamples() diff --git a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs index ca7d04876e..5b66e18a6d 100644 --- a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 5fd281f9fa..11136ad695 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; @@ -117,7 +118,7 @@ namespace osu.Game.Rulesets.Taiko.Replays var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY; - double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.StartTime - endTime) * 0.9; + double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.AsNonNull().StartTime - endTime) * 0.9; Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay)); hitButton = !hitButton; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index d2a7329a28..a0a687dca6 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Replays Actions.AddRange(actions); } - public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) + public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame? lastFrame = null) { if (currentFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); if (currentFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index 0d6ce44255..a663817aa8 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs index cf806c0c97..896af24772 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Scoring diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index bacc22714e..3b0bb952dd 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Scoring diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs index 25f895708f..b91d5cfe8d 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CentreHitCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs index f2452ad88c..a7ab1bcd4a 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Audio.Track; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs index 210841bca0..ba2679fe97 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/ElongatedCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs index c6165495d8..63269f1267 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/RimHitCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs index 2f59cac3ff..d19dc4c887 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/SwellSymbolPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs index 09c8243aac..7d3268f777 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/TickPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs index 2b528ae8ce..97e0a340dd 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyBarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs index 2b6c14ca63..7f813e7b27 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs index ea6f813be8..80f139a66b 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyDrumRoll.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs index d93317f0e2..b4277f86bb 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Skinning; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs index 21bd35ad22..87ed2e2e60 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs index d3eeb8e16a..a03d987efd 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyInputDrum.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -18,13 +20,14 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy /// internal class LegacyInputDrum : Container { + private Container content; private LegacyHalfDrum left; private LegacyHalfDrum right; - private Container content; public LegacyInputDrum() { - RelativeSizeAxes = Axes.Both; + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs index fa49242675..bd4a2f8935 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyTaikoScroller.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs index c4657fcc49..a48cdf47f6 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyHitTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs index 02756d57a4..f425a410a4 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacyPlayfieldBackgroundRight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs index af5921b0fb..888271f32d 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/TaikoLegacySkinTransformer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Audio.Sample; diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs index 20766029bb..d36fe5d496 100644 --- a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 0a198414dc..9a5f5791ab 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs index e6e4bc0dd7..63314a6822 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Skinning; namespace osu.Game.Rulesets.Taiko @@ -14,6 +16,6 @@ namespace osu.Game.Rulesets.Taiko protected override string RulesetPrefix => TaikoRuleset.SHORT_NAME; - protected override string ComponentName => Component.ToString().ToLower(); + protected override string ComponentName => Component.ToString().ToLowerInvariant(); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs index bf48898dd2..d231dc7e4f 100644 --- a/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs +++ b/osu.Game.Rulesets.Taiko/TaikoSkinComponents.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Taiko { public enum TaikoSkinComponents diff --git a/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs b/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs index cb878e8ea0..071808a044 100644 --- a/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/BarLinePlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko/UI/DefaultHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/DefaultHitExplosion.cs index 91e844187a..687c8f788f 100644 --- a/osu.Game.Rulesets.Taiko/UI/DefaultHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/DefaultHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs index 7ce8b016d5..e91475d87b 100644 --- a/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/DefaultKiaiHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index 876fa207bf..264e4db54e 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs index 7ba2618a63..8bedca19d8 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoMascot.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio.Track; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index e52c95e34a..a117435ada 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs b/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs index ae37840825..e0d5a3c680 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumRollHitContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs index 3279d128d3..ef5bd1d7f0 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Audio; using osu.Game.Rulesets.Taiko.Objects; diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index 8f5e9e54ab..046b3a6fd0 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osuTK; diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs index badf34554c..8707f7e840 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosionPool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/UI/IAnimatableHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/IAnimatableHitExplosion.cs index cf0f5f9fb6..6a9d43a0ab 100644 --- a/osu.Game.Rulesets.Taiko/UI/IAnimatableHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/IAnimatableHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.UI diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index e984bef3ce..97990395a2 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -10,6 +12,8 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Screens.Ranking; using osu.Game.Skinning; using osuTK; @@ -25,7 +29,8 @@ namespace osu.Game.Rulesets.Taiko.UI public InputDrum() { - RelativeSizeAxes = Axes.Both; + AutoSizeAxes = Axes.X; + RelativeSizeAxes = Axes.Y; } [BackgroundDependencyLoader] @@ -33,12 +38,31 @@ namespace osu.Game.Rulesets.Taiko.UI { Children = new Drawable[] { - new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new Container + new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.InputDrum), _ => new DefaultInputDrum()) { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + }, + }; + } + + private class DefaultInputDrum : AspectContainer + { + public DefaultInputDrum() + { + RelativeSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, Scale = new Vector2(0.9f), - Children = new Drawable[] + Children = new[] { new TaikoHalfDrum(false, CentreSize) { @@ -63,123 +87,130 @@ namespace osu.Game.Rulesets.Taiko.UI CentreAction = TaikoAction.RightCentre } } - }) - }; - } - - /// - /// A half-drum. Contains one centre and one rim hit. - /// - private class TaikoHalfDrum : Container, IKeyBindingHandler - { - /// - /// The key to be used for the rim of the half-drum. - /// - public TaikoAction RimAction; - - /// - /// The key to be used for the centre of the half-drum. - /// - public TaikoAction CentreAction; - - private readonly Sprite rim; - private readonly Sprite rimHit; - private readonly Sprite centre; - private readonly Sprite centreHit; - - public TaikoHalfDrum(bool flipped, float centreSize) - { - Masking = true; - - Children = new Drawable[] - { - rim = new Sprite - { - Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both - }, - rimHit = new Sprite - { - Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Blending = BlendingParameters.Additive, - }, - centre = new Sprite - { - Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(centreSize) - }, - centreHit = new Sprite - { - Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(centreSize), - Alpha = 0, - Blending = BlendingParameters.Additive - } }; } - [BackgroundDependencyLoader] - private void load(TextureStore textures, OsuColour colours) + /// + /// A half-drum. Contains one centre and one rim hit. + /// + private class TaikoHalfDrum : Container, IKeyBindingHandler { - rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer"); - rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit"); - centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner"); - centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit"); + /// + /// The key to be used for the rim of the half-drum. + /// + public TaikoAction RimAction; - rimHit.Colour = colours.Blue; - centreHit.Colour = colours.Pink; - } + /// + /// The key to be used for the centre of the half-drum. + /// + public TaikoAction CentreAction; - public bool OnPressed(KeyBindingPressEvent e) - { - Drawable target = null; - Drawable back = null; + private readonly Sprite rim; + private readonly Sprite rimHit; + private readonly Sprite centre; + private readonly Sprite centreHit; - if (e.Action == CentreAction) + [Resolved] + private DrumSampleTriggerSource sampleTriggerSource { get; set; } + + public TaikoHalfDrum(bool flipped) { - target = centreHit; - back = centre; - } - else if (e.Action == RimAction) - { - target = rimHit; - back = rim; + Masking = true; + + Children = new Drawable[] + { + rim = new Sprite + { + Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both + }, + rimHit = new Sprite + { + Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Blending = BlendingParameters.Additive, + }, + centre = new Sprite + { + Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.7f) + }, + centreHit = new Sprite + { + Anchor = flipped ? Anchor.CentreLeft : Anchor.CentreRight, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.7f), + Alpha = 0, + Blending = BlendingParameters.Additive + } + }; } - if (target != null) + [BackgroundDependencyLoader] + private void load(TextureStore textures, OsuColour colours) { - const float scale_amount = 0.05f; - const float alpha_amount = 0.5f; + rim.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer"); + rimHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-outer-hit"); + centre.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner"); + centreHit.Texture = textures.Get(@"Gameplay/taiko/taiko-drum-inner-hit"); - const float down_time = 40; - const float up_time = 1000; - - back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint) - .Then() - .ScaleTo(1, up_time, Easing.OutQuint); - - target.Animate( - t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint), - t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint) - ).Then( - t => t.ScaleTo(1, up_time, Easing.OutQuint), - t => t.FadeOut(up_time, Easing.OutQuint) - ); + rimHit.Colour = colours.Blue; + centreHit.Colour = colours.Pink; } - return false; - } + public bool OnPressed(KeyBindingPressEvent e) + { + Drawable target = null; + Drawable back = null; - public void OnReleased(KeyBindingReleaseEvent e) - { + if (e.Action == CentreAction) + { + target = centreHit; + back = centre; + + sampleTriggerSource.Play(HitType.Centre); + } + else if (e.Action == RimAction) + { + target = rimHit; + back = rim; + + sampleTriggerSource.Play(HitType.Rim); + } + + if (target != null) + { + const float scale_amount = 0.05f; + const float alpha_amount = 0.5f; + + const float down_time = 40; + const float up_time = 1000; + + back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint) + .Then() + .ScaleTo(1, up_time, Easing.OutQuint); + + target.Animate( + t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint), + t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint) + ).Then( + t => t.ScaleTo(1, up_time, Easing.OutQuint), + t => t.FadeOut(up_time, Easing.OutQuint) + ); + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } } } } diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index 20900a9352..319d8979ae 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs index 2a8890a95d..db1094e100 100644 --- a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs +++ b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundLeft.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs index 44bfdacf37..43252e2e77 100644 --- a/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs +++ b/osu.Game.Rulesets.Taiko/UI/PlayfieldBackgroundRight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs b/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs index 6401c6d09f..f48ed2c941 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoHitTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs index c496c05236..26a37fc464 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -137,10 +139,10 @@ namespace osu.Game.Rulesets.Taiko.UI private static Texture getAnimationFrame(ISkin skin, TaikoMascotAnimationState state, int frameIndex) { - var texture = skin.GetTexture($"pippidon{state.ToString().ToLower()}{frameIndex}"); + var texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}{frameIndex}"); if (frameIndex == 0 && texture == null) - texture = skin.GetTexture($"pippidon{state.ToString().ToLower()}"); + texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}"); return texture; } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimationState.cs b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimationState.cs index 02bf245b7b..717f0d725a 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimationState.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimationState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Taiko.UI { public enum TaikoMascotAnimationState diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 1b0dcaecf9..a17fc0391a 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -1,10 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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.Graphics.Pooling; @@ -32,6 +35,11 @@ namespace osu.Game.Rulesets.Taiko.UI /// public const float DEFAULT_HEIGHT = 200; + /// + /// Whether the hit target should be nudged further towards the left area, matching the stable "classic" position. + /// + public Bindable ClassicHitTargetPosition = new BindableBool(); + private Container hitExplosionContainer; private Container kiaiExplosionContainer; private JudgementContainer judgementContainer; @@ -43,8 +51,8 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly IDictionary explosionPools = new Dictionary(); private ProxyContainer topLevelHitContainer; + private InputDrum inputDrum; private Container rightArea; - private Container leftArea; /// /// is purposefully not called on this to prevent i.e. being able to interact @@ -52,14 +60,43 @@ namespace osu.Game.Rulesets.Taiko.UI /// private BarLinePlayfield barLinePlayfield; - private Container hitTargetOffsetContent; + private Container playfieldContent; + private Container playfieldOverlay; [BackgroundDependencyLoader] private void load(OsuColour colours) { + inputDrum = new InputDrum() + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + }; + InternalChildren = new[] { new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundRight), _ => new PlayfieldBackgroundRight()), + new Container + { + Name = "Left overlay", + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + BorderColour = colours.Gray0, + Children = new[] + { + new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundLeft), _ => new PlayfieldBackgroundLeft()), + inputDrum.CreateProxy(), + } + }, + mascot = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.Mascot), _ => Empty()) + { + Origin = Anchor.BottomLeft, + Anchor = Anchor.TopLeft, + RelativePositionAxes = Axes.Y, + RelativeSizeAxes = Axes.None, + Y = 0.2f + }, rightArea = new Container { Name = "Right area", @@ -69,7 +106,7 @@ namespace osu.Game.Rulesets.Taiko.UI { new Container { - Name = "Masked elements before hit objects", + Name = "Elements before hit objects", RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, Children = new[] @@ -84,22 +121,28 @@ namespace osu.Game.Rulesets.Taiko.UI } } }, - hitTargetOffsetContent = new Container + new Container { + Name = "Masked hit objects content", + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = playfieldContent = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + barLinePlayfield = new BarLinePlayfield(), + HitObjectContainer, + } + } + }, + playfieldOverlay = new Container + { + Name = "Elements after hit objects", RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - barLinePlayfield = new BarLinePlayfield(), - new Container - { - Name = "Hit objects", - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - HitObjectContainer, - drumRollHitContainer = new DrumRollHitContainer() - } - }, + drumRollHitContainer = new DrumRollHitContainer(), kiaiExplosionContainer = new Container { Name = "Kiai hit explosions", @@ -115,30 +158,6 @@ namespace osu.Game.Rulesets.Taiko.UI }, } }, - leftArea = new Container - { - Name = "Left overlay", - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - BorderColour = colours.Gray0, - Children = new Drawable[] - { - new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundLeft), _ => new PlayfieldBackgroundLeft()), - new InputDrum - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - } - }, - mascot = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.Mascot), _ => Empty()) - { - Origin = Anchor.BottomLeft, - Anchor = Anchor.TopLeft, - RelativePositionAxes = Axes.Y, - RelativeSizeAxes = Axes.None, - Y = 0.2f - }, topLevelHitContainer = new ProxyContainer { Name = "Top level hit objects", @@ -146,6 +165,9 @@ namespace osu.Game.Rulesets.Taiko.UI }, drumRollHitContainer.CreateProxy(), new DrumSamplePlayer(HitObjectContainer), + // this is added at the end of the hierarchy to receive input before taiko objects. + // but is proxied below everything to not cover visual effects such as hit explosions. + inputDrum, }; RegisterPool(50); @@ -192,8 +214,9 @@ namespace osu.Game.Rulesets.Taiko.UI // Padding is required to be updated for elements which are based on "absolute" X sized elements. // This is basically allowing for correct alignment as relative pieces move around them. - rightArea.Padding = new MarginPadding { Left = leftArea.DrawWidth }; - hitTargetOffsetContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 }; + rightArea.Padding = new MarginPadding { Left = inputDrum.Width }; + playfieldContent.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 }; + playfieldOverlay.Padding = new MarginPadding { Left = HitTarget.DrawWidth / 2 }; mascot.Scale = new Vector2(DrawHeight / DEFAULT_HEIGHT); } @@ -244,7 +267,7 @@ namespace osu.Game.Rulesets.Taiko.UI barLinePlayfield.Add(barLine); break; - case DrawableTaikoHitObject _: + case DrawableTaikoHitObject: base.Add(h); break; @@ -260,7 +283,7 @@ namespace osu.Game.Rulesets.Taiko.UI case DrawableBarLine barLine: return barLinePlayfield.Remove(barLine); - case DrawableTaikoHitObject _: + case DrawableTaikoHitObject: return base.Remove(h); default: @@ -279,12 +302,12 @@ namespace osu.Game.Rulesets.Taiko.UI switch (result.Judgement) { - case TaikoStrongJudgement _: + case TaikoStrongJudgement: if (result.IsHit) hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).ParentHitObject)?.VisualiseSecondHit(result); break; - case TaikoDrumRollTickJudgement _: + case TaikoDrumRollTickJudgement: if (!result.IsHit) break; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 9cf530e903..8e99a82b1b 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs b/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs index e6391d1386..a76adc495d 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoReplayRecorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Taiko.Replays; diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs index dbe74a10da..6c4f9bac58 100644 --- a/osu.Game.Tests.Android/MainActivity.cs +++ b/osu.Game.Tests.Android/MainActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Android.App; using osu.Framework.Android; diff --git a/osu.Game.Tests.iOS/AppDelegate.cs b/osu.Game.Tests.iOS/AppDelegate.cs index 1e703e0c0a..b13027459f 100644 --- a/osu.Game.Tests.iOS/AppDelegate.cs +++ b/osu.Game.Tests.iOS/AppDelegate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Foundation; using osu.Framework.iOS; diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs index 585b495c96..cf36fea139 100644 --- a/osu.Game.Tests.iOS/Application.cs +++ b/osu.Game.Tests.iOS/Application.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.iOS; using UIKit; diff --git a/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs b/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs index 149096608f..d05eb7994b 100644 --- a/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs +++ b/osu.Game.Tests/Audio/SampleInfoEqualityTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Audio; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index e2d9910b82..9acd3a6cab 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index 0d436c1ef7..09130ac57d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections; using System.Collections.Generic; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs index 4334c4d7a2..c1c9e0d118 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps.Formats; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs index 1474f2d277..aa6fc1f309 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Globalization; using System.IO; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 560e2ef894..57dded8ee4 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osuTK; diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 2eb75259d9..3764467047 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using DeepEqual.Syntax; diff --git a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs index 669acc3202..f3673b0e7f 100644 --- a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using NUnit.Framework; diff --git a/osu.Game.Tests/Beatmaps/IO/BeatmapImportHelper.cs b/osu.Game.Tests/Beatmaps/IO/BeatmapImportHelper.cs index 9e440c6bce..055832d753 100644 --- a/osu.Game.Tests/Beatmaps/IO/BeatmapImportHelper.cs +++ b/osu.Game.Tests/Beatmaps/IO/BeatmapImportHelper.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.IO; diff --git a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs index 5e37f01c81..8f20fd7a68 100644 --- a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Text; diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 810ea5dbd0..04eb9a3fa2 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs b/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs index 9fba0f1668..d30ab3dea1 100644 --- a/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs +++ b/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs index f3456cf8e4..6eb103316f 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; @@ -155,7 +157,7 @@ namespace osu.Game.Tests.Beatmaps [TestCase(8.3, DifficultyRating.ExpertPlus)] public void TestDifficultyRatingMapping(double starRating, DifficultyRating expectedBracket) { - var actualBracket = BeatmapDifficultyCache.GetDifficultyRating(starRating); + var actualBracket = StarDifficulty.GetDifficultyRating(starRating); Assert.AreEqual(expectedBracket, actualBracket); } diff --git a/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs b/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs index 153788c2cf..81d0e6f3ef 100644 --- a/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs +++ b/osu.Game.Tests/Beatmaps/TestSceneEditorBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs b/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs index 10cac4ed9d..b4a205b478 100644 --- a/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs +++ b/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Models; diff --git a/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs b/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs index 5f70f08413..f4b1028c0e 100644 --- a/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/WorkingBeatmapTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Threading; diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index cea4d510c1..ebfa9bd8b7 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Online.Chat; diff --git a/osu.Game.Tests/Chat/TestSceneChannelManager.cs b/osu.Game.Tests/Chat/TestSceneChannelManager.cs index 2bb6459f20..e7eb06c795 100644 --- a/osu.Game.Tests/Chat/TestSceneChannelManager.cs +++ b/osu.Game.Tests/Chat/TestSceneChannelManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs index 5cbede54f5..9a8f29647d 100644 --- a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs +++ b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Text; @@ -49,11 +51,16 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); + // Even with no beatmaps imported, collections are tracking the hashes and will continue to. + // In the future this whole mechanism will be replaced with having the collections in realm, + // but until that happens it makes rough sense that we want to track not-yet-imported beatmaps + // and have them associate with collections if/when they become available. + Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.Zero); + Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(1)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.Zero); + Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(12)); } finally { @@ -76,10 +83,10 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(1)); + Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(1)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.EqualTo(12)); + Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(12)); } finally { @@ -92,7 +99,7 @@ namespace osu.Game.Tests.Collections.IO public async Task TestImportMalformedDatabase() { bool exceptionThrown = false; - UnhandledExceptionEventHandler setException = (_, __) => exceptionThrown = true; + UnhandledExceptionEventHandler setException = (_, _) => exceptionThrown = true; using (HeadlessGameHost host = new CleanRunHeadlessGameHost()) { @@ -131,7 +138,7 @@ namespace osu.Game.Tests.Collections.IO { string firstRunName; - using (var host = new CleanRunHeadlessGameHost(bypassCleanup: true)) + using (var host = new CleanRunHeadlessGameHost(bypassCleanupOnDispose: true)) { firstRunName = host.Name; @@ -142,8 +149,8 @@ namespace osu.Game.Tests.Collections.IO await importCollectionsFromStream(osu, TestResources.OpenResource("Collections/collections.db")); // Move first beatmap from second collection into the first. - osu.CollectionManager.Collections[0].Beatmaps.Add(osu.CollectionManager.Collections[1].Beatmaps[0]); - osu.CollectionManager.Collections[1].Beatmaps.RemoveAt(0); + osu.CollectionManager.Collections[0].BeatmapHashes.Add(osu.CollectionManager.Collections[1].BeatmapHashes[0]); + osu.CollectionManager.Collections[1].BeatmapHashes.RemoveAt(0); // Rename the second collecction. osu.CollectionManager.Collections[1].Name.Value = "Another"; @@ -164,10 +171,10 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(2)); + Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Another")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.EqualTo(11)); + Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(11)); } finally { diff --git a/osu.Game.Tests/Database/BeatmapImporterTests.cs b/osu.Game.Tests/Database/BeatmapImporterTests.cs index d4956e97e0..9ee88c0670 100644 --- a/osu.Game.Tests/Database/BeatmapImporterTests.cs +++ b/osu.Game.Tests/Database/BeatmapImporterTests.cs @@ -12,15 +12,12 @@ using NUnit.Framework; using osu.Framework.Extensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Logging; -using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Extensions; -using osu.Game.IO.Archives; using osu.Game.Models; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; -using osu.Game.Stores; using osu.Game.Tests.Resources; using Realms; using SharpCompress.Archives; @@ -28,8 +25,6 @@ using SharpCompress.Archives.Zip; using SharpCompress.Common; using SharpCompress.Writers.Zip; -#nullable enable - namespace osu.Game.Tests.Database { [TestFixture] @@ -40,13 +35,11 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using (var importer = new BeatmapModelManager(realm, storage)) + var importer = new BeatmapImporter(storage, realm); + using (new RealmRulesetStore(realm, storage)) { - Live? beatmapSet; - - using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream())) - beatmapSet = await importer.Import(reader); + var beatmapSet = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz")); Assert.NotNull(beatmapSet); Debug.Assert(beatmapSet != null); @@ -84,13 +77,11 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using (var importer = new BeatmapModelManager(realm, storage)) + var importer = new BeatmapImporter(storage, realm); + using (new RealmRulesetStore(realm, storage)) { - Live? beatmapSet; - - using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream())) - beatmapSet = await importer.Import(reader); + var beatmapSet = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz")); Assert.NotNull(beatmapSet); Debug.Assert(beatmapSet != null); @@ -143,16 +134,16 @@ namespace osu.Game.Tests.Database { BeatmapSetInfo? detachedSet = null; - using (var importer = new BeatmapModelManager(realm, storage)) + var manager = new ModelManager(storage, realm); + + var importer = new BeatmapImporter(storage, realm); + using (new RealmRulesetStore(realm, storage)) { Task.Run(async () => { - Live? beatmapSet; - - using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream())) - // ReSharper disable once AccessToDisposedClosure - beatmapSet = await importer.Import(reader); + // ReSharper disable once AccessToDisposedClosure + var beatmapSet = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz")); Assert.NotNull(beatmapSet); Debug.Assert(beatmapSet != null); @@ -162,7 +153,7 @@ namespace osu.Game.Tests.Database }).WaitSafely(); Debug.Assert(detachedSet != null); - importer.AddFile(detachedSet, new MemoryStream(), "test"); + manager.AddFile(detachedSet, new MemoryStream(), "test"); } }); } @@ -172,16 +163,12 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using (var importer = new BeatmapModelManager(realm, storage)) + var importer = new BeatmapImporter(storage, realm); + using (new RealmRulesetStore(realm, storage)) { - Live? imported; - - using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream())) - { - imported = await importer.Import(reader); - EnsureLoaded(realm.Realm); - } + var imported = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz")); + EnsureLoaded(realm.Realm); Assert.AreEqual(1, realm.Realm.All().Count()); @@ -204,7 +191,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); await LoadOszIntoStore(importer, realm.Realm); @@ -216,7 +203,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -234,7 +221,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -248,7 +235,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? tempPath = TestResources.GetTestBeatmapForImport(); @@ -278,7 +265,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -293,12 +280,48 @@ namespace osu.Game.Tests.Database }); } + [Test] + public void TestImportDirectoryWithEmptyOsuFiles() + { + RunTestWithRealmAsync(async (realm, storage) => + { + var importer = new BeatmapImporter(storage, realm); + using var store = new RealmRulesetStore(realm, storage); + + string? temp = TestResources.GetTestBeatmapForImport(); + + string extractedFolder = $"{temp}_extracted"; + Directory.CreateDirectory(extractedFolder); + + try + { + using (var zip = ZipArchive.Open(temp)) + zip.WriteToDirectory(extractedFolder); + + foreach (var file in new DirectoryInfo(extractedFolder).GetFiles("*.osu")) + { + using (file.Open(FileMode.Create)) + { + // empty file. + } + } + + var imported = await importer.Import(new ImportTask(extractedFolder)); + Assert.IsNull(imported); + } + finally + { + Directory.Delete(extractedFolder, true); + } + }); + } + [Test] public void TestImportThenImportWithReZip() { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -347,7 +370,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -394,12 +417,11 @@ namespace osu.Game.Tests.Database } [Test] - [Ignore("intentionally broken by import optimisations")] public void TestImportThenImportWithChangedFile() { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -447,7 +469,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -491,28 +513,29 @@ namespace osu.Game.Tests.Database } [Test] - [Ignore("intentionally broken by import optimisations")] public void TestImportCorruptThenImport() { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); var firstFile = imported.Files.First(); + var fileStorage = storage.GetStorageForDirectory("files"); + long originalLength; - using (var stream = storage.GetStream(firstFile.File.GetStoragePath())) + using (var stream = fileStorage.GetStream(firstFile.File.GetStoragePath())) originalLength = stream.Length; - using (var stream = storage.CreateFileSafely(firstFile.File.GetStoragePath())) + using (var stream = fileStorage.CreateFileSafely(firstFile.File.GetStoragePath())) stream.WriteByte(0); var importedSecondTime = await LoadOszIntoStore(importer, realm.Realm); - using (var stream = storage.GetStream(firstFile.File.GetStoragePath())) + using (var stream = fileStorage.GetStream(firstFile.File.GetStoragePath())) Assert.AreEqual(stream.Length, originalLength, "Corruption was not fixed on second import"); // check the newly "imported" beatmap is actually just the restored previous import. since it matches hash. @@ -529,7 +552,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var progressNotification = new ImportProgressNotification(); @@ -567,7 +590,7 @@ namespace osu.Game.Tests.Database Interlocked.Increment(ref loggedExceptionCount); }; - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -588,6 +611,12 @@ namespace osu.Game.Tests.Database using (var outStream = File.Open(brokenTempFilename, FileMode.CreateNew)) using (var zip = ZipArchive.Open(brokenOsz)) { + foreach (var entry in zip.Entries.ToArray()) + { + if (entry.Key.EndsWith(".osu", StringComparison.InvariantCulture)) + zip.RemoveEntry(entry); + } + zip.AddEntry("broken.osu", brokenOsu, false); zip.SaveTo(outStream, CompressionType.Deflate); } @@ -608,7 +637,7 @@ namespace osu.Game.Tests.Database checkSingleReferencedFileCount(realm.Realm, 18); - Assert.AreEqual(1, loggedExceptionCount); + Assert.AreEqual(0, loggedExceptionCount); File.Delete(brokenTempFilename); }); @@ -619,10 +648,10 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); - var imported = await LoadOszIntoStore(importer, realm.Realm); + var imported = await LoadOszIntoStore(importer, realm.Realm, batchImport: true); deleteBeatmapSet(imported, realm.Realm); @@ -646,7 +675,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realmFactory, storage) => { - using var importer = new BeatmapModelManager(realmFactory, storage); + var importer = new BeatmapImporter(storage, realmFactory); using var store = new RealmRulesetStore(realmFactory, storage); var imported = await LoadOszIntoStore(importer, realmFactory.Realm); @@ -678,7 +707,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new NonOptimisedBeatmapImporter(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -705,7 +734,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var imported = await LoadOszIntoStore(importer, realm.Realm); @@ -731,7 +760,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealm((realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); var metadata = new BeatmapMetadata @@ -762,7 +791,7 @@ namespace osu.Game.Tests.Database } }; - var imported = importer.Import(toImport); + var imported = importer.ImportModel(toImport); realm.Run(r => r.Refresh()); @@ -779,7 +808,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -796,7 +825,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -832,7 +861,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -874,7 +903,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -925,7 +954,7 @@ namespace osu.Game.Tests.Database { RunTestWithRealmAsync(async (realm, storage) => { - using var importer = new BeatmapModelManager(realm, storage); + var importer = new BeatmapImporter(storage, realm); using var store = new RealmRulesetStore(realm, storage); string? temp = TestResources.GetTestBeatmapForImport(); @@ -960,11 +989,11 @@ namespace osu.Game.Tests.Database return realm.All().FirstOrDefault(beatmapSet => beatmapSet.ID == importedSet!.ID); } - public static async Task LoadOszIntoStore(BeatmapImporter importer, Realm realm, string? path = null, bool virtualTrack = false) + public static async Task LoadOszIntoStore(BeatmapImporter importer, Realm realm, string? path = null, bool virtualTrack = false, bool batchImport = false) { string? temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack); - var importedSet = await importer.Import(new ImportTask(temp)); + var importedSet = await importer.Import(new ImportTask(temp), batchImport); Assert.NotNull(importedSet); Debug.Assert(importedSet != null); @@ -1081,15 +1110,5 @@ namespace osu.Game.Tests.Database Assert.Fail(failureMessage); } - - public class NonOptimisedBeatmapImporter : BeatmapImporter - { - public NonOptimisedBeatmapImporter(RealmAccess realm, Storage storage) - : base(realm, storage) - { - } - - protected override bool HasCustomHashFunction => true; - } } } diff --git a/osu.Game.Tests/Database/FileStoreTests.cs b/osu.Game.Tests/Database/FileStoreTests.cs index 98b0ed99b5..ab9b761b8f 100644 --- a/osu.Game.Tests/Database/FileStoreTests.cs +++ b/osu.Game.Tests/Database/FileStoreTests.cs @@ -6,11 +6,9 @@ using System.IO; using System.Linq; using NUnit.Framework; using osu.Framework.Logging; +using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Models; -using osu.Game.Stores; - -#nullable enable namespace osu.Game.Tests.Database { diff --git a/osu.Game.Tests/Database/GeneralUsageTests.cs b/osu.Game.Tests/Database/GeneralUsageTests.cs index 8262ef18d4..fd0b391d0d 100644 --- a/osu.Game.Tests/Database/GeneralUsageTests.cs +++ b/osu.Game.Tests/Database/GeneralUsageTests.cs @@ -2,13 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using System.Threading; using System.Threading.Tasks; using NUnit.Framework; +using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Database; - -#nullable enable +using osu.Game.Tests.Resources; namespace osu.Game.Tests.Database { @@ -29,12 +30,91 @@ namespace osu.Game.Tests.Database { RunTestWithRealm((realm, _) => { - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } }); } + [Test] + public void TestAsyncWriteAsync() + { + RunTestWithRealmAsync(async (realm, _) => + { + await realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); + + realm.Run(r => r.Refresh()); + + Assert.That(realm.Run(r => r.All().Count()), Is.EqualTo(1)); + }); + } + + [Test] + public void TestAsyncWriteWhileBlocking() + { + RunTestWithRealm((realm, _) => + { + Task writeTask; + + using (realm.BlockAllOperations("testing")) + { + writeTask = realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); + Thread.Sleep(100); + Assert.That(writeTask.IsCompleted, Is.False); + } + + writeTask.WaitSafely(); + + realm.Run(r => r.Refresh()); + Assert.That(realm.Run(r => r.All().Count()), Is.EqualTo(1)); + }); + } + + [Test] + public void TestAsyncWrite() + { + RunTestWithRealm((realm, _) => + { + realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo())).WaitSafely(); + + realm.Run(r => r.Refresh()); + + Assert.That(realm.Run(r => r.All().Count()), Is.EqualTo(1)); + }); + } + + [Test] + public void TestAsyncWriteAfterDisposal() + { + RunTestWithRealm((realm, _) => + { + realm.Dispose(); + Assert.ThrowsAsync(() => realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo()))); + }); + } + + [Test] + public void TestAsyncWriteBeforeDisposal() + { + ManualResetEventSlim resetEvent = new ManualResetEventSlim(); + + RunTestWithRealm((realm, _) => + { + var writeTask = realm.WriteAsync(r => + { + // ensure that disposal blocks for our execution + Assert.That(resetEvent.Wait(100), Is.False); + + r.Add(TestResources.CreateTestBeatmapSetInfo()); + }); + + realm.Dispose(); + resetEvent.Set(); + + writeTask.WaitSafely(); + }); + } + /// /// Test to ensure that a `CreateContext` call nested inside a subscription doesn't cause any deadlocks /// due to context fetching semaphores. @@ -48,7 +128,7 @@ namespace osu.Game.Tests.Database realm.RegisterCustomSubscription(r => { - var subscription = r.All().QueryAsyncWithNotifications((sender, changes, error) => + var subscription = r.All().QueryAsyncWithNotifications((_, _, _) => { realm.Run(_ => { @@ -81,15 +161,15 @@ namespace osu.Game.Tests.Database { hasThreadedUsage.Set(); - stopThreadedUsage.Wait(); + stopThreadedUsage.Wait(60000); }); }, TaskCreationOptions.LongRunning | TaskCreationOptions.HideScheduler); - hasThreadedUsage.Wait(); + hasThreadedUsage.Wait(60000); Assert.Throws(() => { - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } }); @@ -97,7 +177,7 @@ namespace osu.Game.Tests.Database stopThreadedUsage.Set(); // Ensure we can block a second time after the usage has ended. - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } }); diff --git a/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs b/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs new file mode 100644 index 0000000000..1df3d336ee --- /dev/null +++ b/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs @@ -0,0 +1,75 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Game.Database; +using osu.Game.IO; + +namespace osu.Game.Tests.Database +{ + [TestFixture] + public class LegacyBeatmapImporterTest + { + private readonly TestLegacyBeatmapImporter importer = new TestLegacyBeatmapImporter(); + + [Test] + public void TestSongsSubdirectories() + { + using (var storage = new TemporaryNativeStorage("stable-songs-folder")) + { + var songsStorage = storage.GetStorageForDirectory(StableStorage.STABLE_DEFAULT_SONGS_PATH); + + // normal beatmap folder + var beatmap1 = songsStorage.GetStorageForDirectory("beatmap1"); + createFile(beatmap1, "beatmap.osu"); + + // songs subdirectory + var subdirectory = songsStorage.GetStorageForDirectory("subdirectory"); + createFile(subdirectory, Path.Combine("beatmap2", "beatmap.osu")); + createFile(subdirectory, Path.Combine("beatmap3", "beatmap.osu")); + createFile(subdirectory, Path.Combine("sub-subdirectory", "beatmap4", "beatmap.osu")); + + // songs subdirectory with system file + var subdirectory2 = songsStorage.GetStorageForDirectory("subdirectory2"); + createFile(subdirectory2, ".DS_Store"); + createFile(subdirectory2, Path.Combine("beatmap5", "beatmap.osu")); + createFile(subdirectory2, Path.Combine("beatmap6", "beatmap.osu")); + + // empty songs subdirectory + songsStorage.GetStorageForDirectory("subdirectory3"); + + string[] paths = importer.GetStableImportPaths(songsStorage).ToArray(); + Assert.That(paths.Length, Is.EqualTo(6)); + Assert.That(paths.Contains(songsStorage.GetFullPath("beatmap1"))); + Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory", "beatmap2")))); + Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory", "beatmap3")))); + Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory", "sub-subdirectory", "beatmap4")))); + Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory2", "beatmap5")))); + Assert.That(paths.Contains(songsStorage.GetFullPath(Path.Combine("subdirectory2", "beatmap6")))); + } + + static void createFile(Storage storage, string path) + { + using (var stream = storage.CreateFileSafely(path)) + stream.WriteByte(0); + } + } + + private class TestLegacyBeatmapImporter : LegacyBeatmapImporter + { + public TestLegacyBeatmapImporter() + : base(null) + { + } + + public new IEnumerable GetStableImportPaths(Storage storage) => base.GetStableImportPaths(storage); + } + } +} diff --git a/osu.Game.Tests/Database/RealmLiveTests.cs b/osu.Game.Tests/Database/RealmLiveTests.cs index 4bc1f5078a..3615cebe6a 100644 --- a/osu.Game.Tests/Database/RealmLiveTests.cs +++ b/osu.Game.Tests/Database/RealmLiveTests.cs @@ -12,8 +12,6 @@ using osu.Game.Beatmaps; using osu.Game.Database; using Realms; -#nullable enable - namespace osu.Game.Tests.Database { public class RealmLiveTests : RealmTest @@ -51,7 +49,7 @@ namespace osu.Game.Tests.Database { migratedStorage.DeleteDirectory(string.Empty); - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { storage.Migrate(migratedStorage); } @@ -61,6 +59,64 @@ namespace osu.Game.Tests.Database }); } + [Test] + public void TestFailedWritePerformsRollback() + { + RunTestWithRealm((realm, _) => + { + Assert.Throws(() => + { + realm.Write(r => + { + r.Add(new BeatmapInfo(CreateRuleset(), new BeatmapDifficulty(), new BeatmapMetadata())); + throw new InvalidOperationException(); + }); + }); + + Assert.That(realm.Run(r => r.All()), Is.Empty); + }); + } + + [Test] + public void TestFailedNestedWritePerformsRollback() + { + RunTestWithRealm((realm, _) => + { + Assert.Throws(() => + { + realm.Write(r => + { + realm.Write(_ => + { + r.Add(new BeatmapInfo(CreateRuleset(), new BeatmapDifficulty(), new BeatmapMetadata())); + throw new InvalidOperationException(); + }); + }); + }); + + Assert.That(realm.Run(r => r.All()), Is.Empty); + }); + } + + [Test] + public void TestNestedWriteCalls() + { + RunTestWithRealm((realm, _) => + { + var beatmap = new BeatmapInfo(CreateRuleset(), new BeatmapDifficulty(), new BeatmapMetadata()); + + var liveBeatmap = beatmap.ToLive(realm); + + realm.Run(r => + r.Write(_ => + r.Write(_ => + r.Add(beatmap))) + ); + + Assert.IsFalse(liveBeatmap.PerformRead(l => l.Hidden)); + }); + } + [Test] public void TestAccessAfterAttach() { @@ -93,6 +149,25 @@ namespace osu.Game.Tests.Database Assert.IsFalse(liveBeatmap.PerformRead(l => l.Hidden)); } + [Test] + public void TestTransactionRolledBackOnException() + { + RunTestWithRealm((realm, _) => + { + var beatmap = new BeatmapInfo(CreateRuleset(), new BeatmapDifficulty(), new BeatmapMetadata()); + + realm.Run(r => r.Write(_ => r.Add(beatmap))); + + var liveBeatmap = beatmap.ToLive(realm); + + Assert.Throws(() => liveBeatmap.PerformWrite(l => throw new InvalidOperationException())); + Assert.IsFalse(liveBeatmap.PerformRead(l => l.Hidden)); + + liveBeatmap.PerformWrite(l => l.Hidden = true); + Assert.IsTrue(liveBeatmap.PerformRead(l => l.Hidden)); + }); + } + [Test] public void TestScopedReadWithoutContext() { @@ -191,7 +266,7 @@ namespace osu.Game.Tests.Database }); // Can't be used, even from within a valid context. - realm.Run(threadContext => + realm.Run(_ => { Assert.Throws(() => { diff --git a/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs b/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs index d99bcc092d..4ee302bbd0 100644 --- a/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs +++ b/osu.Game.Tests/Database/RealmSubscriptionRegistrationTests.cs @@ -1,13 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions; @@ -86,11 +83,7 @@ namespace osu.Game.Tests.Database realm.Run(r => r.Refresh()); - // Without forcing the write onto its own thread, realm will internally run the operation synchronously, which can cause a deadlock with `WaitSafely`. - Task.Run(async () => - { - await realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); - }).WaitSafely(); + realm.WriteAsync(r => r.Add(TestResources.CreateTestBeatmapSetInfo())).WaitSafely(); realm.Run(r => r.Refresh()); @@ -143,7 +136,7 @@ namespace osu.Game.Tests.Database resolvedItems = null; lastChanges = null; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(resolvedItems, Is.Empty); realm.Write(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); @@ -161,7 +154,7 @@ namespace osu.Game.Tests.Database testEventsArriving(false); // And make sure even after another context loss we don't get firings. - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(resolvedItems, Is.Null); realm.Write(r => r.Add(TestResources.CreateTestBeatmapSetInfo())); @@ -219,7 +212,7 @@ namespace osu.Game.Tests.Database Assert.That(beatmapSetInfo, Is.Not.Null); - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { // custom disposal action fired when context lost. Assert.That(beatmapSetInfo, Is.Null); @@ -233,7 +226,7 @@ namespace osu.Game.Tests.Database Assert.That(beatmapSetInfo, Is.Null); - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(beatmapSetInfo, Is.Null); realm.Run(r => r.Refresh()); @@ -258,7 +251,7 @@ namespace osu.Game.Tests.Database Assert.That(receivedValue, Is.Not.Null); receivedValue = null; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) { } @@ -269,7 +262,7 @@ namespace osu.Game.Tests.Database subscription.Dispose(); receivedValue = null; - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("testing")) Assert.That(receivedValue, Is.Null); realm.Run(r => r.Refresh()); diff --git a/osu.Game.Tests/Database/RealmTest.cs b/osu.Game.Tests/Database/RealmTest.cs index 16072888b9..d6b3c1ff44 100644 --- a/osu.Game.Tests/Database/RealmTest.cs +++ b/osu.Game.Tests/Database/RealmTest.cs @@ -15,8 +15,6 @@ using osu.Game.IO; using osu.Game.Models; using osu.Game.Rulesets; -#nullable enable - namespace osu.Game.Tests.Database { [TestFixture] diff --git a/osu.Game.Tests/Database/RulesetStoreTests.cs b/osu.Game.Tests/Database/RulesetStoreTests.cs index f48b5cba11..795e90f543 100644 --- a/osu.Game.Tests/Database/RulesetStoreTests.cs +++ b/osu.Game.Tests/Database/RulesetStoreTests.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs b/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs index 891801865f..362b37124d 100644 --- a/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs +++ b/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioInVideoTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioInVideoTest.cs index 614b9b4ac1..947e884494 100644 --- a/osu.Game.Tests/Editing/Checks/CheckAudioInVideoTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckAudioInVideoTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs index e22dfa5f8b..9fdd49823e 100644 --- a/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckAudioQualityTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Moq; using NUnit.Framework; diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index bb560054a3..af5588f509 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs index 5adb91a22e..9c1dd2c1e8 100644 --- a/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckConcurrentObjectsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Editing/Checks/CheckFewHitsoundsTest.cs b/osu.Game.Tests/Editing/Checks/CheckFewHitsoundsTest.cs index cf5b3a42a4..82bb2e59c9 100644 --- a/osu.Game.Tests/Editing/Checks/CheckFewHitsoundsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFewHitsoundsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs index 01baaadc7d..2f18720a5b 100644 --- a/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckFilePresenceTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs index 91d9a8753c..622386405a 100644 --- a/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Editing/Checks/CheckTestHelpers.cs b/osu.Game.Tests/Editing/Checks/CheckTestHelpers.cs index 9067714ff9..405738cd55 100644 --- a/osu.Game.Tests/Editing/Checks/CheckTestHelpers.cs +++ b/osu.Game.Tests/Editing/Checks/CheckTestHelpers.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Models; namespace osu.Game.Tests.Editing.Checks diff --git a/osu.Game.Tests/Editing/Checks/CheckTooShortAudioFilesTest.cs b/osu.Game.Tests/Editing/Checks/CheckTooShortAudioFilesTest.cs index 53c85defae..7d33b92dbe 100644 --- a/osu.Game.Tests/Editing/Checks/CheckTooShortAudioFilesTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckTooShortAudioFilesTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs index 882baba8fa..f647bf8d8e 100644 --- a/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckUnsnappedObjectsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Editing/Checks/CheckZeroByteFilesTest.cs b/osu.Game.Tests/Editing/Checks/CheckZeroByteFilesTest.cs index 79d00e6a60..793cc70a3f 100644 --- a/osu.Game.Tests/Editing/Checks/CheckZeroByteFilesTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckZeroByteFilesTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Editing/Checks/CheckZeroLengthObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckZeroLengthObjectsTest.cs index 93b20cd166..1c1965ab56 100644 --- a/osu.Game.Tests/Editing/Checks/CheckZeroLengthObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckZeroLengthObjectsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Editing/Checks/MockNestableHitObject.cs b/osu.Game.Tests/Editing/Checks/MockNestableHitObject.cs index 29938839d3..6c0306d63d 100644 --- a/osu.Game.Tests/Editing/Checks/MockNestableHitObject.cs +++ b/osu.Game.Tests/Editing/Checks/MockNestableHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Threading; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs b/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs index 2d61948a2a..e1accd5b5f 100644 --- a/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs +++ b/osu.Game.Tests/Editing/EditorChangeHandlerTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Beatmaps; diff --git a/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs b/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs index 44a908b756..5af0366e6e 100644 --- a/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs +++ b/osu.Game.Tests/Editing/LegacyEditorBeatmapPatcherTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Text; using NUnit.Framework; diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index 82fc7a208b..c2df9e5e09 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs b/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs index 592971dbaf..c3e171684c 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectContainerEventBuffer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs b/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs index 4ce9115ec4..3d7286c396 100644 --- a/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs +++ b/osu.Game.Tests/Editing/TransactionalCommitComponentTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Screens.Edit; diff --git a/osu.Game.Tests/Extensions/StringDehumanizeExtensionsTest.cs b/osu.Game.Tests/Extensions/StringDehumanizeExtensionsTest.cs new file mode 100644 index 0000000000..e7490b461b --- /dev/null +++ b/osu.Game.Tests/Extensions/StringDehumanizeExtensionsTest.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 System.Globalization; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Extensions; + +namespace osu.Game.Tests.Extensions +{ + [TestFixture] + public class StringDehumanizeExtensionsTest + { + [Test] + [TestCase("single", "Single")] + [TestCase("example word", "ExampleWord")] + [TestCase("mixed Casing test", "MixedCasingTest")] + [TestCase("PascalCase", "PascalCase")] + [TestCase("camelCase", "CamelCase")] + [TestCase("snake_case", "SnakeCase")] + [TestCase("kebab-case", "KebabCase")] + [TestCase("i will not break in a different culture", "IWillNotBreakInADifferentCulture", "tr-TR")] + public void TestToPascalCase(string input, string expectedOutput, string? culture = null) + { + using (temporaryCurrentCulture(culture)) + Assert.That(input.ToPascalCase(), Is.EqualTo(expectedOutput)); + } + + [Test] + [TestCase("single", "single")] + [TestCase("example word", "exampleWord")] + [TestCase("mixed Casing test", "mixedCasingTest")] + [TestCase("PascalCase", "pascalCase")] + [TestCase("camelCase", "camelCase")] + [TestCase("snake_case", "snakeCase")] + [TestCase("kebab-case", "kebabCase")] + [TestCase("I will not break in a different culture", "iWillNotBreakInADifferentCulture", "tr-TR")] + public void TestToCamelCase(string input, string expectedOutput, string? culture = null) + { + using (temporaryCurrentCulture(culture)) + Assert.That(input.ToCamelCase(), Is.EqualTo(expectedOutput)); + } + + [Test] + [TestCase("single", "single")] + [TestCase("example word", "example_word")] + [TestCase("mixed Casing test", "mixed_casing_test")] + [TestCase("PascalCase", "pascal_case")] + [TestCase("camelCase", "camel_case")] + [TestCase("snake_case", "snake_case")] + [TestCase("kebab-case", "kebab_case")] + [TestCase("I will not break in a different culture", "i_will_not_break_in_a_different_culture", "tr-TR")] + public void TestToSnakeCase(string input, string expectedOutput, string? culture = null) + { + using (temporaryCurrentCulture(culture)) + Assert.That(input.ToSnakeCase(), Is.EqualTo(expectedOutput)); + } + + [Test] + [TestCase("single", "single")] + [TestCase("example word", "example-word")] + [TestCase("mixed Casing test", "mixed-casing-test")] + [TestCase("PascalCase", "pascal-case")] + [TestCase("camelCase", "camel-case")] + [TestCase("snake_case", "snake-case")] + [TestCase("kebab-case", "kebab-case")] + [TestCase("I will not break in a different culture", "i-will-not-break-in-a-different-culture", "tr-TR")] + public void TestToKebabCase(string input, string expectedOutput, string? culture = null) + { + using (temporaryCurrentCulture(culture)) + Assert.That(input.ToKebabCase(), Is.EqualTo(expectedOutput)); + } + + private IDisposable temporaryCurrentCulture(string? cultureName) + { + var storedCulture = CultureInfo.CurrentCulture; + + if (cultureName != null) + CultureInfo.CurrentCulture = new CultureInfo(cultureName); + + return new InvokeOnDisposal(() => CultureInfo.CurrentCulture = storedCulture); + } + } +} diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index a354464a8e..c4e8bbfccf 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using NUnit.Framework; using osu.Framework.Graphics; @@ -190,7 +192,7 @@ namespace osu.Game.Tests.Gameplay AddStep("apply perfect hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = HitResult.Perfect })); AddAssert("not failed", () => !processor.HasFailed); - AddStep($"apply {resultApplied.ToString().ToLower()} hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = resultApplied })); + AddStep($"apply {resultApplied.ToString().ToLowerInvariant()} hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = resultApplied })); AddAssert("failed", () => processor.HasFailed); } diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs index 58f4c4c8db..91e33b759c 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index 5553c67141..1e10fbb2bc 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs index f2bfccb6de..79e64ba2a2 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index 153d5b8e36..e25d08f98c 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.IO.Stores; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs b/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs index 5c04ac88a7..0395ae9d99 100644 --- a/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneMasterGameplayClockContainer.cs @@ -1,13 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Testing; using osu.Framework.Timing; -using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Play; @@ -76,6 +77,16 @@ namespace osu.Game.Tests.Gameplay } [Test] + [FlakyTest] + /* + * Fail rate around 0.15% + * + * TearDown : osu.Framework.Testing.Drawables.Steps.AssertButton+TracedException : gameplay clock time = 2500 + * --TearDown + * at osu.Framework.Threading.ScheduledDelegate.RunTaskInternal() + * at osu.Framework.Threading.Scheduler.Update() + * at osu.Framework.Graphics.Drawable.UpdateSubTree() + */ public void TestSeekPerformsInGameplayTime( [Values(1.0, 0.5, 2.0)] double clockRate, [Values(0.0, 200.0, -200.0)] double userOffset, @@ -104,10 +115,10 @@ namespace osu.Game.Tests.Gameplay AddStep($"set audio offset to {userOffset}", () => localConfig.SetValue(OsuSetting.AudioOffset, userOffset)); AddStep("seek to 2500", () => gameplayClockContainer.Seek(2500)); - AddAssert("gameplay clock time = 2500", () => Precision.AlmostEquals(gameplayClockContainer.CurrentTime, 2500, 10f)); + AddStep("gameplay clock time = 2500", () => Assert.AreEqual(gameplayClockContainer.CurrentTime, 2500, 10f)); AddStep("seek to 10000", () => gameplayClockContainer.Seek(10000)); - AddAssert("gameplay clock time = 10000", () => Precision.AlmostEquals(gameplayClockContainer.CurrentTime, 10000, 10f)); + AddStep("gameplay clock time = 10000", () => Assert.AreEqual(gameplayClockContainer.CurrentTime, 10000, 10f)); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs b/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs index 1264d575a4..1893e43f43 100644 --- a/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneProxyContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index 97be1dcfaa..9e1d786d87 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs index e0a497cf24..a9c6bacc65 100644 --- a/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneStoryboardSamples.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using System.Threading; diff --git a/osu.Game.Tests/ImportTest.cs b/osu.Game.Tests/ImportTest.cs index a658a0eaeb..32b6dc649c 100644 --- a/osu.Game.Tests/ImportTest.cs +++ b/osu.Game.Tests/ImportTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using System.Threading.Tasks; diff --git a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs index 28937b2120..a91d4553de 100644 --- a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs +++ b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; diff --git a/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs b/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs index 9926acf772..d01eaca714 100644 --- a/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs +++ b/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Models/DisplayStringTest.cs b/osu.Game.Tests/Models/DisplayStringTest.cs index 2d0bda88e4..d585a0eb9f 100644 --- a/osu.Game.Tests/Models/DisplayStringTest.cs +++ b/osu.Game.Tests/Models/DisplayStringTest.cs @@ -10,8 +10,6 @@ using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Users; -#nullable enable - namespace osu.Game.Tests.Models { [TestFixture] diff --git a/osu.Game.Tests/Mods/ModDifficultyAdjustTest.cs b/osu.Game.Tests/Mods/ModDifficultyAdjustTest.cs index 85b4688eb9..4101652c49 100644 --- a/osu.Game.Tests/Mods/ModDifficultyAdjustTest.cs +++ b/osu.Game.Tests/Mods/ModDifficultyAdjustTest.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Mods [TestFixture] public class ModDifficultyAdjustTest { - private TestModDifficultyAdjust testMod; + private TestModDifficultyAdjust testMod = null!; [SetUp] public void Setup() @@ -146,7 +146,7 @@ namespace osu.Game.Tests.Mods yield return new TestModDifficultyAdjust(); } - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) { throw new System.NotImplementedException(); } diff --git a/osu.Game.Tests/Mods/ModUtilsTest.cs b/osu.Game.Tests/Mods/ModUtilsTest.cs index 6c9dddf51f..3b391f6756 100644 --- a/osu.Game.Tests/Mods/ModUtilsTest.cs +++ b/osu.Game.Tests/Mods/ModUtilsTest.cs @@ -162,19 +162,19 @@ namespace osu.Game.Tests.Mods new object[] { new Mod[] { new OsuModHidden(), new InvalidMultiplayerMod() }, - null + Array.Empty() }, // invalid free mod is valid for local. new object[] { new Mod[] { new OsuModHidden(), new InvalidMultiplayerFreeMod() }, - null + Array.Empty() }, // valid pair. new object[] { new Mod[] { new OsuModHidden(), new OsuModHardRock() }, - null + Array.Empty() }, }; @@ -214,13 +214,13 @@ namespace osu.Game.Tests.Mods new object[] { new Mod[] { new OsuModHidden(), new InvalidMultiplayerFreeMod() }, - null + Array.Empty() }, // valid pair. new object[] { new Mod[] { new OsuModHidden(), new OsuModHardRock() }, - null + Array.Empty() }, }; @@ -254,19 +254,19 @@ namespace osu.Game.Tests.Mods new object[] { new Mod[] { new OsuModHidden(), new OsuModApproachDifferent() }, - null, + Array.Empty(), }, // incompatible pair with derived class is valid for free mods. new object[] { new Mod[] { new OsuModDeflate(), new OsuModSpinIn() }, - null, + Array.Empty(), }, // valid pair. new object[] { new Mod[] { new OsuModHidden(), new OsuModHardRock() }, - null + Array.Empty() }, }; @@ -275,12 +275,12 @@ namespace osu.Game.Tests.Mods { bool isValid = ModUtils.CheckValidForGameplay(inputMods, out var invalid); - Assert.That(isValid, Is.EqualTo(expectedInvalid == null)); + Assert.That(isValid, Is.EqualTo(expectedInvalid.Length == 0)); if (isValid) Assert.IsNull(invalid); else - Assert.That(invalid.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); + Assert.That(invalid?.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); } [TestCaseSource(nameof(invalid_multiplayer_mod_test_scenarios))] @@ -288,12 +288,12 @@ namespace osu.Game.Tests.Mods { bool isValid = ModUtils.CheckValidRequiredModsForMultiplayer(inputMods, out var invalid); - Assert.That(isValid, Is.EqualTo(expectedInvalid == null)); + Assert.That(isValid, Is.EqualTo(expectedInvalid.Length == 0)); if (isValid) Assert.IsNull(invalid); else - Assert.That(invalid.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); + Assert.That(invalid?.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); } [TestCaseSource(nameof(invalid_free_mod_test_scenarios))] @@ -301,12 +301,12 @@ namespace osu.Game.Tests.Mods { bool isValid = ModUtils.CheckValidFreeModsForMultiplayer(inputMods, out var invalid); - Assert.That(isValid, Is.EqualTo(expectedInvalid == null)); + Assert.That(isValid, Is.EqualTo(expectedInvalid.Length == 0)); if (isValid) Assert.IsNull(invalid); else - Assert.That(invalid.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); + Assert.That(invalid?.Select(t => t.GetType()), Is.EquivalentTo(expectedInvalid)); } public abstract class CustomMod1 : Mod, IModCompatibilitySpecification diff --git a/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs b/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs index 312b939315..b8a3828a64 100644 --- a/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs +++ b/osu.Game.Tests/Mods/MultiModIncompatibilityTest.cs @@ -27,10 +27,10 @@ namespace osu.Game.Tests.Mods [TestCase(typeof(ManiaRuleset))] public void TestAllMultiModsFromRulesetAreIncompatible(Type rulesetType) { - var ruleset = (Ruleset)Activator.CreateInstance(rulesetType); + var ruleset = Activator.CreateInstance(rulesetType) as Ruleset; Assert.That(ruleset, Is.Not.Null); - var allMultiMods = getMultiMods(ruleset); + var allMultiMods = getMultiMods(ruleset!); Assert.Multiple(() => { diff --git a/osu.Game.Tests/Mods/TestCustomisableModRuleset.cs b/osu.Game.Tests/Mods/TestCustomisableModRuleset.cs index 3992d9abe6..9e3354935a 100644 --- a/osu.Game.Tests/Mods/TestCustomisableModRuleset.cs +++ b/osu.Game.Tests/Mods/TestCustomisableModRuleset.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Mods return Array.Empty(); } - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new NotImplementedException(); + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => throw new NotImplementedException(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); diff --git a/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs b/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs index 6ae8231deb..e7827a7398 100644 --- a/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs +++ b/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs b/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs index 1b6049fcb7..461102124a 100644 --- a/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs +++ b/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs @@ -1,10 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; +using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Extensions; +using osu.Game.Models; +using osu.Game.Tests.Resources; namespace osu.Game.Tests.NonVisual { @@ -21,6 +26,83 @@ namespace osu.Game.Tests.NonVisual Assert.IsTrue(ourInfo.MatchesOnlineID(otherInfo)); } + [Test] + public void TestAudioEqualityNoFile() + { + var beatmapSetA = TestResources.CreateTestBeatmapSetInfo(1); + var beatmapSetB = TestResources.CreateTestBeatmapSetInfo(1); + + Assert.AreNotEqual(beatmapSetA, beatmapSetB); + Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single())); + } + + [Test] + public void TestAudioEqualitySameHash() + { + var beatmapSetA = TestResources.CreateTestBeatmapSetInfo(1); + var beatmapSetB = TestResources.CreateTestBeatmapSetInfo(1); + + addAudioFile(beatmapSetA, "abc"); + addAudioFile(beatmapSetB, "abc"); + + Assert.AreNotEqual(beatmapSetA, beatmapSetB); + Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single())); + } + + [Test] + public void TestAudioEqualityDifferentHash() + { + var beatmapSetA = TestResources.CreateTestBeatmapSetInfo(1); + var beatmapSetB = TestResources.CreateTestBeatmapSetInfo(1); + + addAudioFile(beatmapSetA); + addAudioFile(beatmapSetB); + + Assert.AreNotEqual(beatmapSetA, beatmapSetB); + Assert.IsTrue(beatmapSetA.Beatmaps.Single().AudioEquals(beatmapSetB.Beatmaps.Single())); + } + + [Test] + public void TestAudioEqualityBeatmapInfoSameHash() + { + var beatmapSet = TestResources.CreateTestBeatmapSetInfo(2); + + addAudioFile(beatmapSet); + + var beatmap1 = beatmapSet.Beatmaps.First(); + var beatmap2 = beatmapSet.Beatmaps.Last(); + + Assert.AreNotEqual(beatmap1, beatmap2); + Assert.IsTrue(beatmap1.AudioEquals(beatmap2)); + } + + [Test] + public void TestAudioEqualityBeatmapInfoDifferentHash() + { + var beatmapSet = TestResources.CreateTestBeatmapSetInfo(2); + + const string filename1 = "audio1.mp3"; + const string filename2 = "audio2.mp3"; + + addAudioFile(beatmapSet, filename: filename1); + addAudioFile(beatmapSet, filename: filename2); + + var beatmap1 = beatmapSet.Beatmaps.First(); + var beatmap2 = beatmapSet.Beatmaps.Last(); + + Assert.AreNotEqual(beatmap1, beatmap2); + + beatmap1.Metadata.AudioFile = filename1; + beatmap2.Metadata.AudioFile = filename2; + + Assert.IsFalse(beatmap1.AudioEquals(beatmap2)); + } + + private static void addAudioFile(BeatmapSetInfo beatmapSetInfo, string hash = null, string filename = null) + { + beatmapSetInfo.Files.Add(new RealmNamedFileUsage(new RealmFile { Hash = hash ?? Guid.NewGuid().ToString() }, filename ?? "audio.mp3")); + } + [Test] public void TestDatabasedWithDatabased() { diff --git a/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs b/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs index 08cd80dcfa..6f3fe875e3 100644 --- a/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs +++ b/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs index cfda4f6422..554473cf77 100644 --- a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs index fd5691a9f4..216db2121c 100644 --- a/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs +++ b/osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -42,8 +44,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestCustomDirectory() { - string customPath = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) using (var host = new CustomTestHeadlessGameHost()) { using (var storageConfig = new StorageConfigManager(host.InitialStorage)) @@ -61,7 +62,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); } } } @@ -69,8 +69,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestSubDirectoryLookup() { - string customPath = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) using (var host = new CustomTestHeadlessGameHost()) { using (var storageConfig = new StorageConfigManager(host.InitialStorage)) @@ -95,7 +94,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); } } } @@ -103,8 +101,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestMigration() { - string customPath = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) using (var host = new CustomTestHeadlessGameHost()) { try @@ -171,7 +168,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); } } } @@ -179,9 +175,8 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestMigrationBetweenTwoTargets() { - string customPath = prepareCustomPath(); - string customPath2 = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) + using (prepareCustomPath(out string customPath2)) using (var host = new CustomTestHeadlessGameHost()) { try @@ -203,8 +198,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); - cleanupPath(customPath2); } } } @@ -212,8 +205,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestMigrationToSameTargetFails() { - string customPath = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) using (var host = new CustomTestHeadlessGameHost()) { try @@ -226,7 +218,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); } } } @@ -234,9 +225,8 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestMigrationFailsOnExistingData() { - string customPath = prepareCustomPath(); - string customPath2 = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) + using (prepareCustomPath(out string customPath2)) using (var host = new CustomTestHeadlessGameHost()) { try @@ -252,7 +242,7 @@ namespace osu.Game.Tests.NonVisual Assert.That(File.Exists(Path.Combine(customPath, OsuGameBase.CLIENT_DATABASE_FILENAME))); Directory.CreateDirectory(customPath2); - File.Copy(Path.Combine(customPath, OsuGameBase.CLIENT_DATABASE_FILENAME), Path.Combine(customPath2, OsuGameBase.CLIENT_DATABASE_FILENAME)); + File.WriteAllText(Path.Combine(customPath2, OsuGameBase.CLIENT_DATABASE_FILENAME), "I am a text"); // Fails because file already exists. Assert.Throws(() => osu.Migrate(customPath2)); @@ -265,8 +255,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); - cleanupPath(customPath2); } } } @@ -274,8 +262,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestMigrationToNestedTargetFails() { - string customPath = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) using (var host = new CustomTestHeadlessGameHost()) { try @@ -296,7 +283,6 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); } } } @@ -304,8 +290,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestMigrationToSeeminglyNestedTarget() { - string customPath = prepareCustomPath(); - + using (prepareCustomPath(out string customPath)) using (var host = new CustomTestHeadlessGameHost()) { try @@ -326,7 +311,26 @@ namespace osu.Game.Tests.NonVisual finally { host.Exit(); - cleanupPath(customPath); + } + } + } + + [Test] + public void TestBackupCreatedOnCorruptRealm() + { + using (var host = new CustomTestHeadlessGameHost()) + { + try + { + File.WriteAllText(host.InitialStorage.GetFullPath(OsuGameBase.CLIENT_DATABASE_FILENAME, true), "i am definitely not a realm file"); + + LoadOsuIntoHost(host); + + Assert.That(host.InitialStorage.GetFiles(string.Empty, "*_corrupt.realm"), Has.One.Items); + } + finally + { + host.Exit(); } } } @@ -341,14 +345,17 @@ namespace osu.Game.Tests.NonVisual return path; } - private static string prepareCustomPath() => Path.Combine(TestRunHeadlessGameHost.TemporaryTestDirectory, $"custom-path-{Guid.NewGuid()}"); + private static IDisposable prepareCustomPath(out string path) + { + path = Path.Combine(TestRunHeadlessGameHost.TemporaryTestDirectory, $"custom-path-{Guid.NewGuid()}"); + return new InvokeOnDisposal(path, cleanupPath); + } private static void cleanupPath(string path) { try { - if (Directory.Exists(path)) - Directory.Delete(path, true); + if (Directory.Exists(path)) Directory.Delete(path, true); } catch { @@ -360,7 +367,7 @@ namespace osu.Game.Tests.NonVisual public Storage InitialStorage { get; } public CustomTestHeadlessGameHost([CallerMemberName] string callingMethodName = @"") - : base(callingMethodName: callingMethodName) + : base(callingMethodName: callingMethodName, bypassCleanupOnSetup: true) { string defaultStorageLocation = getDefaultLocationFor(this); diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index ae8eec2629..8d1c266473 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index 460f89528b..bd0617515b 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -254,7 +254,7 @@ namespace osu.Game.Tests.NonVisual.Filtering private class CustomFilterCriteria : IRulesetFilterCriteria { - public string CustomValue { get; set; } + public string? CustomValue { get; set; } public bool Matches(BeatmapInfo beatmapInfo) => true; diff --git a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs index 8386a10ebb..14da07bc2d 100644 --- a/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs +++ b/osu.Game.Tests/NonVisual/FirstAvailableHitWindowsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -81,14 +83,14 @@ namespace osu.Game.Tests.NonVisual public override event Action NewResult { - add => throw new InvalidOperationException(); - remove => throw new InvalidOperationException(); + add => throw new InvalidOperationException($"{nameof(NewResult)} operations not supported in test context"); + remove => throw new InvalidOperationException($"{nameof(NewResult)} operations not supported in test context"); } public override event Action RevertResult { - add => throw new InvalidOperationException(); - remove => throw new InvalidOperationException(); + add => throw new InvalidOperationException($"{nameof(RevertResult)} operations not supported in test context"); + remove => throw new InvalidOperationException($"{nameof(RevertResult)} operations not supported in test context"); } public override Playfield Playfield { get; } diff --git a/osu.Game.Tests/NonVisual/FormatUtilsTest.cs b/osu.Game.Tests/NonVisual/FormatUtilsTest.cs index d69822cdc5..4d2fc53bc3 100644 --- a/osu.Game.Tests/NonVisual/FormatUtilsTest.cs +++ b/osu.Game.Tests/NonVisual/FormatUtilsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Utils; diff --git a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs index 99d394b454..541ad1e8bb 100644 --- a/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs +++ b/osu.Game.Tests/NonVisual/FramedReplayInputHandlerTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -362,12 +364,12 @@ namespace osu.Game.Tests.NonVisual private void confirmCurrentFrame(int? frame) { - Assert.AreEqual(frame is int x ? replay.Frames[x].Time : (double?)null, handler.CurrentFrame?.Time, "Unexpected current frame"); + Assert.AreEqual(frame is int x ? replay.Frames[x].Time : null, handler.CurrentFrame?.Time, "Unexpected current frame"); } private void confirmNextFrame(int? frame) { - Assert.AreEqual(frame is int x ? replay.Frames[x].Time : (double?)null, handler.NextFrame?.Time, "Unexpected next frame"); + Assert.AreEqual(frame is int x ? replay.Frames[x].Time : null, handler.NextFrame?.Time, "Unexpected next frame"); } private class TestReplayFrame : ReplayFrame diff --git a/osu.Game.Tests/NonVisual/GameplayClockTest.cs b/osu.Game.Tests/NonVisual/GameplayClockTest.cs index 3fd7c364b7..5b8aacd281 100644 --- a/osu.Game.Tests/NonVisual/GameplayClockTest.cs +++ b/osu.Game.Tests/NonVisual/GameplayClockTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs b/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs index e1eaf213d6..8cd26901c5 100644 --- a/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs +++ b/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Rulesets.Difficulty.Utils; diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index 4adb7002a0..d1c5e2d8b3 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Humanizer; using NUnit.Framework; @@ -22,7 +24,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer var user = new APIUser { Id = 33 }; AddRepeatStep("add user multiple times", () => MultiplayerClient.AddUser(user), 3); - AddAssert("room has 2 users", () => MultiplayerClient.Room?.Users.Count == 2); + AddUntilStep("room has 2 users", () => MultiplayerClient.ClientRoom?.Users.Count == 2); } [Test] @@ -31,10 +33,10 @@ namespace osu.Game.Tests.NonVisual.Multiplayer var user = new APIUser { Id = 44 }; AddStep("add user", () => MultiplayerClient.AddUser(user)); - AddAssert("room has 2 users", () => MultiplayerClient.Room?.Users.Count == 2); + AddUntilStep("room has 2 users", () => MultiplayerClient.ClientRoom?.Users.Count == 2); - AddRepeatStep("remove user multiple times", () => MultiplayerClient.RemoveUser(user), 3); - AddAssert("room has 1 user", () => MultiplayerClient.Room?.Users.Count == 1); + AddStep("remove user", () => MultiplayerClient.RemoveUser(user)); + AddUntilStep("room has 1 user", () => MultiplayerClient.ClientRoom?.Users.Count == 1); } [Test] @@ -57,7 +59,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer changeState(6, MultiplayerUserState.WaitingForLoad); checkPlayingUserCount(6); - AddStep("another user left", () => MultiplayerClient.RemoveUser((MultiplayerClient.Room?.Users.Last().User).AsNonNull())); + AddStep("another user left", () => MultiplayerClient.RemoveUser((MultiplayerClient.ServerRoom?.Users.Last().User).AsNonNull())); checkPlayingUserCount(5); AddStep("leave room", () => MultiplayerClient.LeaveRoom()); @@ -101,7 +103,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer { for (int i = 0; i < userCount; ++i) { - int userId = MultiplayerClient.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); + int userId = MultiplayerClient.ServerRoom?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); MultiplayerClient.ChangeUserState(userId, state); } }); diff --git a/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs b/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs index 10216c3339..03ca3a0a1a 100644 --- a/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs +++ b/osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs b/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs index 62c7732b66..b589f7c9f1 100644 --- a/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs +++ b/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/NonVisual/Ranking/UnstableRateTest.cs b/osu.Game.Tests/NonVisual/Ranking/UnstableRateTest.cs index 103831822c..27c8270f0f 100644 --- a/osu.Game.Tests/NonVisual/Ranking/UnstableRateTest.cs +++ b/osu.Game.Tests/NonVisual/Ranking/UnstableRateTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/NonVisual/ReverseQueueTest.cs b/osu.Game.Tests/NonVisual/ReverseQueueTest.cs index 808c8d14f0..d0ad2e22a4 100644 --- a/osu.Game.Tests/NonVisual/ReverseQueueTest.cs +++ b/osu.Game.Tests/NonVisual/ReverseQueueTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Rulesets.Difficulty.Utils; diff --git a/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs b/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs index ae999d08d5..8654abd49d 100644 --- a/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs +++ b/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/NonVisual/ScoreInfoTest.cs b/osu.Game.Tests/NonVisual/ScoreInfoTest.cs index 41b08a9e98..dcc4f91dba 100644 --- a/osu.Game.Tests/NonVisual/ScoreInfoTest.cs +++ b/osu.Game.Tests/NonVisual/ScoreInfoTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Online.API; using osu.Game.Rulesets.Mania; diff --git a/osu.Game.Tests/NonVisual/SessionStaticsTest.cs b/osu.Game.Tests/NonVisual/SessionStaticsTest.cs index cd02f15adf..5c8254b947 100644 --- a/osu.Game.Tests/NonVisual/SessionStaticsTest.cs +++ b/osu.Game.Tests/NonVisual/SessionStaticsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Configuration; diff --git a/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs b/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs index 4209f188cc..e21a3e636f 100644 --- a/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs +++ b/osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs index 76c49edf78..22aa78838a 100644 --- a/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs +++ b/osu.Game.Tests/NonVisual/Skinning/LegacySkinTextureFallbackTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -155,7 +157,7 @@ namespace osu.Game.Tests.NonVisual.Skinning { // use an incrementing width to allow assertion matching on correct textures as they turn from uploads into actual textures. int width = 1; - Textures = fileNames.ToDictionary(fileName => fileName, fileName => new TextureUpload(new Image(width, width++))); + Textures = fileNames.ToDictionary(fileName => fileName, _ => new TextureUpload(new Image(width, width++))); } public TextureUpload Get(string name) => Textures.GetValueOrDefault(name); diff --git a/osu.Game.Tests/NonVisual/TaskChainTest.cs b/osu.Game.Tests/NonVisual/TaskChainTest.cs index 3678279035..ad1a3fd63f 100644 --- a/osu.Game.Tests/NonVisual/TaskChainTest.cs +++ b/osu.Game.Tests/NonVisual/TaskChainTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using System.Threading.Tasks; using NUnit.Framework; diff --git a/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs b/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs index 97d7880def..861e342cdb 100644 --- a/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs +++ b/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Extensions; diff --git a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs index 855de9b656..13f1ed5c57 100644 --- a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs +++ b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Online.Chat; diff --git a/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs b/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs index 0622514783..185f85513b 100644 --- a/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs +++ b/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Tests/Online/TestAPIModMessagePackSerialization.cs b/osu.Game.Tests/Online/TestAPIModMessagePackSerialization.cs index 69e19826fd..a89d68bf15 100644 --- a/osu.Game.Tests/Online/TestAPIModMessagePackSerialization.cs +++ b/osu.Game.Tests/Online/TestAPIModMessagePackSerialization.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using MessagePack; using NUnit.Framework; diff --git a/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs b/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs index 91c6b6c008..61fdae0ca1 100644 --- a/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs +++ b/osu.Game.Tests/Online/TestDummyAPIRequestHandling.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Online.API; diff --git a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs index 81475f2fbe..aea579a82d 100644 --- a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs +++ b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using MessagePack; using NUnit.Framework; using osu.Game.Online; diff --git a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs index ad9ea79646..e7a6e9a543 100644 --- a/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs +++ b/osu.Game.Tests/Online/TestSceneBeatmapDownloading.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Testing; @@ -78,7 +80,7 @@ namespace osu.Game.Tests.Online { AddStep("download beatmap", () => beatmaps.Download(test_db_model)); - AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_db_model).Cancel()); + AddStep("cancel download from request", () => beatmaps.GetExistingDownload(test_db_model)!.Cancel()); AddUntilStep("is removed from download list", () => beatmaps.GetExistingDownload(test_db_model) == null); AddAssert("is notification cancelled", () => recentNotification.State == ProgressNotificationState.Cancelled); diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs index db988a544d..536322805b 100644 --- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -124,10 +126,10 @@ namespace osu.Game.Tests.Online AddStep("start downloading", () => beatmapDownloader.Download(testBeatmapSet)); addAvailabilityCheckStep("state downloading 0%", () => BeatmapAvailability.Downloading(0.0f)); - AddStep("set progress 40%", () => ((TestDownloadRequest)beatmapDownloader.GetExistingDownload(testBeatmapSet)).SetProgress(0.4f)); + AddStep("set progress 40%", () => ((TestDownloadRequest)beatmapDownloader.GetExistingDownload(testBeatmapSet))!.SetProgress(0.4f)); addAvailabilityCheckStep("state downloading 40%", () => BeatmapAvailability.Downloading(0.4f)); - AddStep("finish download", () => ((TestDownloadRequest)beatmapDownloader.GetExistingDownload(testBeatmapSet)).TriggerSuccess(testBeatmapFile)); + AddStep("finish download", () => ((TestDownloadRequest)beatmapDownloader.GetExistingDownload(testBeatmapSet))!.TriggerSuccess(testBeatmapFile)); addAvailabilityCheckStep("state importing", BeatmapAvailability.Importing); AddStep("allow importing", () => beatmaps.AllowImport.SetResult(true)); @@ -210,25 +212,25 @@ namespace osu.Game.Tests.Online { } - protected override BeatmapModelManager CreateBeatmapModelManager(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) + protected override BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm) { - return new TestBeatmapModelManager(this, storage, realm, onlineLookupQueue); + return new TestBeatmapImporter(this, storage, realm); } - internal class TestBeatmapModelManager : BeatmapModelManager + internal class TestBeatmapImporter : BeatmapImporter { private readonly TestBeatmapManager testBeatmapManager; - public TestBeatmapModelManager(TestBeatmapManager testBeatmapManager, Storage storage, RealmAccess databaseAccess, BeatmapOnlineLookupQueue beatmapOnlineLookupQueue) - : base(databaseAccess, storage, beatmapOnlineLookupQueue) + public TestBeatmapImporter(TestBeatmapManager testBeatmapManager, Storage storage, RealmAccess databaseAccess) + : base(storage, databaseAccess) { this.testBeatmapManager = testBeatmapManager; } - public override Live Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) + public override Live ImportModel(BeatmapSetInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) { testBeatmapManager.AllowImport.Task.WaitSafely(); - return (testBeatmapManager.CurrentImport = base.Import(item, archive, lowPriority, cancellationToken)); + return (testBeatmapManager.CurrentImport = base.ImportModel(item, archive, batchImport, cancellationToken)); } } } @@ -244,7 +246,7 @@ namespace osu.Game.Tests.Online => new TestDownloadRequest(set); } - private class TestDownloadRequest : ArchiveDownloadRequest + internal class TestDownloadRequest : ArchiveDownloadRequest { public new void SetProgress(float progress) => base.SetProgress(progress); public new void TriggerSuccess(string filename) => base.TriggerSuccess(filename); diff --git a/osu.Game.Tests/Online/TestSubmittableScoreJsonSerialization.cs b/osu.Game.Tests/Online/TestSubmittableScoreJsonSerialization.cs index 662660bce4..f0f6727393 100644 --- a/osu.Game.Tests/Online/TestSubmittableScoreJsonSerialization.cs +++ b/osu.Game.Tests/Online/TestSubmittableScoreJsonSerialization.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using NUnit.Framework; using osu.Game.IO.Serialization; diff --git a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs index 9e7ea02101..73ed2bb868 100644 --- a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs +++ b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs b/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs index 6851df3832..6c639ee539 100644 --- a/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs +++ b/osu.Game.Tests/OnlinePlay/TestSceneCatchUpSyncManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index 81b624f908..ee29cc8644 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -132,10 +134,11 @@ namespace osu.Game.Tests.Resources DifficultyName = $"{version} {beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})", StarRating = diff, Length = length, + BeatmapSet = beatmapSet, BPM = bpm, Hash = Guid.NewGuid().ToString().ComputeMD5Hash(), Ruleset = rulesetInfo, - Metadata = metadata, + Metadata = metadata.DeepClone(), Difficulty = new BeatmapDifficulty { OverallDifficulty = diff, diff --git a/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs b/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs index 51163efd6a..4601737558 100644 --- a/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs +++ b/osu.Game.Tests/Rulesets/Mods/ModTimeRampTest.cs @@ -17,8 +17,8 @@ namespace osu.Game.Tests.Rulesets.Mods private const double start_time = 1000; private const double duration = 9000; - private TrackVirtual track; - private OsuPlayfield playfield; + private TrackVirtual track = null!; + private OsuPlayfield playfield = null!; [SetUp] public void SetUp() diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index 7ecd509193..ff282fff62 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs new file mode 100644 index 0000000000..ecc4b3ec63 --- /dev/null +++ b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs @@ -0,0 +1,79 @@ +// Copyright (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.Testing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.UI; +using osu.Game.Tests.Visual; + +namespace osu.Game.Tests.Rulesets +{ + [HeadlessTest] + public class TestSceneBrokenRulesetHandling : OsuTestScene + { + [Resolved] + private OsuGameBase gameBase { get; set; } = null!; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("reset ruleset", () => Ruleset.Value = new OsuRuleset().RulesetInfo); + } + + [Test] + public void TestNullModsReturnedByRulesetAreIgnored() + { + AddStep("set ruleset with null mods", () => Ruleset.Value = new TestRulesetWithNullMods().RulesetInfo); + AddAssert("no null mods in available mods", () => gameBase.AvailableMods.Value.SelectMany(kvp => kvp.Value).All(mod => mod != null)); + } + + [Test] + public void TestRulesetRevertedIfModsCannotBeRetrieved() + { + RulesetInfo ruleset = null!; + + AddStep("store current ruleset", () => ruleset = Ruleset.Value); + + AddStep("set API incompatible ruleset", () => Ruleset.Value = new TestAPIIncompatibleRuleset().RulesetInfo); + AddAssert("ruleset not changed", () => Ruleset.Value.Equals(ruleset)); + } + +#nullable disable // purposefully disabling nullability to simulate broken or unannotated API user code. + + private class TestRulesetWithNullMods : Ruleset + { + public override string ShortName => "nullmods"; + public override string Description => "nullmods"; + + public override IEnumerable GetModsFor(ModType type) => new Mod[] { null }; + + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + } + + private class TestAPIIncompatibleRuleset : Ruleset + { + public override string ShortName => "incompatible"; + public override string Description => "incompatible"; + + // simulate API incompatibility by throwing similar exceptions. + public override IEnumerable GetModsFor(ModType type) => throw new MissingMethodException(); + + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + } + +#nullable enable + } +} diff --git a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs index 20439ac969..9f732be9e3 100644 --- a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs +++ b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs index 28ad7ed6a7..f1ecd3b526 100644 --- a/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs +++ b/osu.Game.Tests/Rulesets/TestSceneRulesetSkinProvidingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 8de9f0a292..892ceea185 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs index f898774ce6..d44fd786d7 100644 --- a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs +++ b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Game.Scoring; diff --git a/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs index a6e8622b6f..0994803d83 100644 --- a/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs +++ b/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 1429d22c1a..c1f647cb07 100644 --- a/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs +++ b/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; diff --git a/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs index bd578dcbc4..ca6ac63619 100644 --- a/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs +++ b/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index dde8715764..c3c10215a5 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -13,7 +15,6 @@ using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; -using osu.Game.IO.Archives; using osu.Game.Skinning; using SharpCompress.Archives.Zip; @@ -26,7 +27,7 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportDifferentFilename() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk")); // When the import filename doesn't match, it should be appended (and update the skin.ini). assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu); @@ -35,7 +36,7 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportWeirdIniFileCase() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner", iniFilename: "Skin.InI"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner", iniFilename: "Skin.InI"), "skin.osk")); // When the import filename doesn't match, it should be appended (and update the skin.ini). assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu); @@ -44,7 +45,7 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportMissingSectionHeader() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner", includeSectionHeader: false), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner", includeSectionHeader: false), "skin.osk")); // When the import filename doesn't match, it should be appended (and update the skin.ini). assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu); @@ -53,7 +54,7 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportMatchingFilename() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "test skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "test skin.osk")); // When the import filename matches it shouldn't be appended. assertCorrectMetadata(import1, "test skin", "skinner", osu); @@ -62,7 +63,7 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSingleImportNoIniFile() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithNonIniFile(), "test skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithNonIniFile(), "test skin.osk")); // When the import filename matches it shouldn't be appended. assertCorrectMetadata(import1, "test skin", "Unknown", osu); @@ -71,7 +72,7 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestEmptyImportImportsWithFilename() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createEmptyOsk(), "test skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createEmptyOsk(), "test skin.osk")); // When the import filename matches it shouldn't be appended. assertCorrectMetadata(import1, "test skin", "Unknown", osu); @@ -82,20 +83,20 @@ namespace osu.Game.Tests.Skins.IO #region Cases where imports should match existing [Test] - public Task TestImportTwiceWithSameMetadataAndFilename() => runSkinTest(async osu => + public Task TestImportTwiceWithSameMetadataAndFilename([Values] bool batchImport) => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk"), batchImport); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk"), batchImport); assertImportedOnce(import1, import2); }); [Test] - public Task TestImportTwiceWithNoMetadataSameDownloadFilename() => runSkinTest(async osu => + public Task TestImportTwiceWithNoMetadataSameDownloadFilename([Values] bool batchImport) => runSkinTest(async osu => { // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download.osk"), batchImport); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download.osk"), batchImport); assertImportedOnce(import1, import2); }); @@ -103,10 +104,10 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportUpperCasedOskArchive() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.OsK")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "name 1.OsK")); assertCorrectMetadata(import1, "name 1", "author 1", osu); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.oSK")); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "name 1.oSK")); assertImportedOnce(import1, import2); }); @@ -116,7 +117,7 @@ namespace osu.Game.Tests.Skins.IO { MemoryStream exportStream = new MemoryStream(); - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "custom.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "custom.osk")); assertCorrectMetadata(import1, "name 1 [custom]", "author 1", osu); import1.PerformRead(s => @@ -126,17 +127,17 @@ namespace osu.Game.Tests.Skins.IO string exportFilename = import1.GetDisplayString(); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(exportStream, $"{exportFilename}.osk")); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(exportStream, $"{exportFilename}.osk")); assertCorrectMetadata(import2, "name 1 [custom]", "author 1", osu); assertImportedOnce(import1, import2); }); [Test] - public Task TestSameMetadataNameSameFolderName() => runSkinTest(async osu => + public Task TestSameMetadataNameSameFolderName([Values] bool batchImport) => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 1"), batchImport); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 1"), batchImport); assertImportedOnce(import1, import2); assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu); @@ -149,8 +150,8 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin2.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk")); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin2.osk")); assertImportedBoth(import1, import2); }); @@ -159,8 +160,8 @@ namespace osu.Game.Tests.Skins.IO public Task TestImportTwiceWithNoMetadataDifferentDownloadFilename() => runSkinTest(async osu => { // if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety. - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download2.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download.osk")); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download2.osk")); assertImportedBoth(import1, import2); }); @@ -168,8 +169,8 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestImportTwiceWithSameFilenameDifferentMetadata() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2", "skinner"), "skin.osk")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2.1", "skinner"), "skin.osk")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin v2", "skinner"), "skin.osk")); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin v2.1", "skinner"), "skin.osk")); assertImportedBoth(import1, import2); assertCorrectMetadata(import1, "test skin v2 [skin]", "skinner", osu); @@ -179,8 +180,8 @@ namespace osu.Game.Tests.Skins.IO [Test] public Task TestSameMetadataNameDifferentFolderName() => runSkinTest(async osu => { - var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1")); - var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 2")); + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 1")); + var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 2")); assertImportedBoth(import1, import2); assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu); @@ -356,10 +357,10 @@ namespace osu.Game.Tests.Skins.IO } } - private async Task> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null) + private async Task> loadSkinIntoOsu(OsuGameBase osu, ImportTask import, bool batchImport = false) { var skinManager = osu.Dependencies.Get(); - return await skinManager.Import(archive); + return await skinManager.Import(import, batchImport); } } } diff --git a/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs index e811979aed..6da335a9b7 100644 --- a/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.IO; using osu.Game.Skinning; diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs index cfc140ce39..419eb87b1a 100644 --- a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Game.IO; diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs index 0c1981b35d..1493c10969 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinLookupDisables.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; @@ -56,7 +58,7 @@ namespace osu.Game.Tests.Skins { AddStep($"Set beatmap skin enabled to {allowBeatmapLookups}", () => config.SetValue(OsuSetting.BeatmapSkins, allowBeatmapLookups)); - ISkin expected() => allowBeatmapLookups ? (ISkin)beatmapSource : userSource; + ISkin expected() => allowBeatmapLookups ? beatmapSource : userSource; AddAssert("Check lookup is from correct source", () => requester.FindProvider(s => s.GetDrawableComponent(new TestSkinComponent()) != null) == expected()); } diff --git a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs index fe0423dcfc..f4cea2c8cc 100644 --- a/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneBeatmapSkinResources.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -8,7 +10,7 @@ using osu.Framework.Extensions; using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; -using osu.Game.IO.Archives; +using osu.Game.Database; using osu.Game.Tests.Resources; using osu.Game.Tests.Visual; @@ -25,7 +27,7 @@ namespace osu.Game.Tests.Skins [BackgroundDependencyLoader] private void load() { - var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).GetResultSafely(); + var imported = beatmaps.Import(new ImportTask(TestResources.OpenResource("Archives/ogg-beatmap.osz"), "ogg-beatmap.osz")).GetResultSafely(); imported?.PerformRead(s => { diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index d68398236a..5452bfc939 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs b/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs index ffb3d41d18..1229b63a90 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinProvidingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Skins/TestSceneSkinResources.cs b/osu.Game.Tests/Skins/TestSceneSkinResources.cs index 0271198049..42c1eeb6d1 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinResources.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinResources.cs @@ -1,12 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Testing; using osu.Game.Audio; -using osu.Game.IO.Archives; +using osu.Game.Database; using osu.Game.Skinning; using osu.Game.Tests.Resources; using osu.Game.Tests.Visual; @@ -24,7 +26,7 @@ namespace osu.Game.Tests.Skins [BackgroundDependencyLoader] private void load() { - var imported = skins.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-skin.osk"))).GetResultSafely(); + var imported = skins.Import(new ImportTask(TestResources.OpenResource("Archives/ogg-skin.osk"), "ogg-skin.osk")).GetResultSafely(); skin = imported.PerformRead(skinInfo => skins.GetSkin(skinInfo)); } diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 330d3dd2ae..79b44c109a 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs index 99be72e958..15903b2074 100644 --- a/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs +++ b/osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using ManagedBass.Fx; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs index 884e74346b..5aaaca2b2c 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs b/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs index 0bd1263076..a44ab41d03 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneSeasonalBackgroundLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs index ef115ab66b..aaccea09d4 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs index fede99f450..7cad6f504b 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index 6cb171974a..6bcc45d97e 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs index e6fb4372ff..b609b06921 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs index 068d2bdcbd..3308ffe714 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs index 77c9debef6..2fe2264348 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardFavouriteButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs index a5b52f75f6..0af876bfe8 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardThumbnail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs index 8132fe6ab8..ada521f7f6 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs index 4063fa1252..94b2d10fcf 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index 888002eb36..3f30fa367c 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -152,7 +154,7 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add two collections with same name", () => manager.Collections.AddRange(new[] { new BeatmapCollection { Name = { Value = "1" } }, - new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0] } }, + new BeatmapCollection { Name = { Value = "1" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); } @@ -162,7 +164,7 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add two collections", () => manager.Collections.AddRange(new[] { new BeatmapCollection { Name = { Value = "1" } }, - new BeatmapCollection { Name = { Value = "2" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0] } }, + new BeatmapCollection { Name = { Value = "2" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); assertCollectionCount(2); @@ -198,7 +200,7 @@ namespace osu.Game.Tests.Visual.Collections { AddStep("add two collections", () => manager.Collections.AddRange(new[] { - new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0] } }, + new BeatmapCollection { Name = { Value = "1" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); assertCollectionCount(1); diff --git a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs index c345320e28..13d7a33600 100644 --- a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs +++ b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs index 86a9d555a3..9dd75b6e5e 100644 --- a/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs +++ b/osu.Game.Tests/Visual/Components/TestSceneIdleTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs index cc8503589d..3c89267610 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePollingComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading.Tasks; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs index 82b6710a17..cb29475ba5 100644 --- a/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestScenePreviewTrackManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 073a228224..ecd7732862 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs b/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs index 5d8a6dabd7..796a3cf9fc 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs index fa15c00cd4..291630fa3a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeScreen.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Editing [TestFixture] public class TestSceneComposeScreen : EditorClockTestScene { - private EditorBeatmap editorBeatmap; + private EditorBeatmap editorBeatmap = null!; [Cached] private EditorClipboard clipboard = new EditorClipboard(); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs index 87dbb90138..52e44efb30 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposeSelectBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs index dddd9f07ab..31fc107892 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneComposerSelection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -10,6 +12,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; @@ -61,6 +64,21 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("context menu is visible", () => contextMenuContainer.ChildrenOfType().Single().State == MenuState.Open); } + [Test] + public void TestSelectAndShowContextMenuOutsideBounds() + { + var addedObject = new HitCircle { StartTime = 100, Position = OsuPlayfield.BASE_SIZE }; + AddStep("add hitobject", () => EditorBeatmap.Add(addedObject)); + + AddStep("descale blueprint container", () => this.ChildrenOfType().Single().Scale = new Vector2(0.5f)); + AddStep("move mouse to bottom-right", () => InputManager.MoveMouseTo(blueprintContainer.ToScreenSpace(blueprintContainer.LayoutRectangle.BottomRight + new Vector2(10)))); + + AddStep("right click", () => InputManager.Click(MouseButton.Right)); + + AddUntilStep("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObject); + AddUntilStep("context menu is visible", () => contextMenuContainer.ChildrenOfType().Single().State == MenuState.Open); + } + [Test] public void TestNudgeSelection() { diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs b/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs index 10917df075..1ecbc24d90 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDesignSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using System.Linq; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs index 81cb286058..1f88fa8f35 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDifficultySwitching.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index ef07c3e411..53b6db2277 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index b109234fec..6ad6f0b299 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Screens; @@ -34,12 +35,12 @@ namespace osu.Game.Tests.Visual.Editing { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); - protected override bool EditorComponentsReady => Editor.ChildrenOfType().SingleOrDefault()?.IsLoaded == true; - protected override bool IsolateSavingFromDatabase => false; [Resolved] - private BeatmapManager beatmapManager { get; set; } + private BeatmapManager beatmapManager { get; set; } = null!; + + private Guid currentBeatmapSetID => EditorBeatmap.BeatmapInfo.BeatmapSet?.ID ?? Guid.Empty; public override void SetUpSteps() { @@ -50,19 +51,19 @@ namespace osu.Game.Tests.Visual.Editing AddStep("make new beatmap unique", () => EditorBeatmap.Metadata.Title = Guid.NewGuid().ToString()); } - protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new DummyWorkingBeatmap(Audio, null); + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null) => new DummyWorkingBeatmap(Audio, null); [Test] public void TestCreateNewBeatmap() { AddStep("save beatmap", () => Editor.Save()); - AddAssert("new beatmap in database", () => beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID)?.Value.DeletePending == false); + AddAssert("new beatmap in database", () => beatmapManager.QueryBeatmapSet(s => s.ID == currentBeatmapSetID)?.Value.DeletePending == false); } [Test] public void TestExitWithoutSave() { - EditorBeatmap editorBeatmap = null; + EditorBeatmap editorBeatmap = null!; AddStep("store editor beatmap", () => editorBeatmap = EditorBeatmap); @@ -78,12 +79,33 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for exit", () => !Editor.IsCurrentScreen()); AddStep("release", () => InputManager.ReleaseButton(MouseButton.Left)); - AddAssert("new beatmap not persisted", () => beatmapManager.QueryBeatmapSet(s => s.ID == editorBeatmap.BeatmapInfo.BeatmapSet.ID)?.Value.DeletePending == true); + AddAssert("new beatmap not persisted", () => beatmapManager.QueryBeatmapSet(s => s.ID == editorBeatmap.BeatmapInfo.BeatmapSet.AsNonNull().ID)?.Value.DeletePending == true); } [Test] + [FlakyTest] + /* + * Fail rate around 1.2%. + * + * Failing with realm refetch occasionally being null. + * My only guess is that the WorkingBeatmap at SetupScreen is dummy instead of the true one. + * If it's something else, we have larger issues with realm, but I don't think that's the case. + * + * at osu.Framework.Logging.ThrowingTraceListener.Fail(String message1, String message2) + * at System.Diagnostics.TraceInternal.Fail(String message, String detailMessage) + * at System.Diagnostics.TraceInternal.TraceProvider.Fail(String message, String detailMessage) + * at System.Diagnostics.Debug.Fail(String message, String detailMessage) + * at osu.Game.Database.ModelManager`1.<>c__DisplayClass8_0.b__0(Realm realm) ModelManager.cs:line 50 + * at osu.Game.Database.RealmExtensions.Write(Realm realm, Action`1 function) RealmExtensions.cs:line 14 + * at osu.Game.Database.ModelManager`1.performFileOperation(TModel item, Action`1 operation) ModelManager.cs:line 47 + * at osu.Game.Database.ModelManager`1.AddFile(TModel item, Stream contents, String filename) ModelManager.cs:line 37 + * at osu.Game.Screens.Edit.Setup.ResourcesSection.ChangeAudioTrack(FileInfo source) ResourcesSection.cs:line 115 + * at osu.Game.Tests.Visual.Editing.TestSceneEditorBeatmapCreation.b__11_0() TestSceneEditorBeatmapCreation.cs:line 101 + */ public void TestAddAudioTrack() { + AddAssert("track is virtual", () => Beatmap.Value.Track is TrackVirtual); + AddAssert("switch track to real track", () => { var setup = Editor.ChildrenOfType().First(); @@ -93,17 +115,26 @@ namespace osu.Game.Tests.Visual.Editing string extractedFolder = $"{temp}_extracted"; Directory.CreateDirectory(extractedFolder); - using (var zip = ZipArchive.Open(temp)) - zip.WriteToDirectory(extractedFolder); + try + { + using (var zip = ZipArchive.Open(temp)) + zip.WriteToDirectory(extractedFolder); - bool success = setup.ChildrenOfType().First().ChangeAudioTrack(Path.Combine(extractedFolder, "03. Renatus - Soleily 192kbps.mp3")); + bool success = setup.ChildrenOfType().First().ChangeAudioTrack(new FileInfo(Path.Combine(extractedFolder, "03. Renatus - Soleily 192kbps.mp3"))); - File.Delete(temp); - Directory.Delete(extractedFolder, true); + // ensure audio file is copied to beatmap as "audio.mp3" rather than original filename. + Assert.That(Beatmap.Value.Metadata.AudioFile == "audio.mp3"); - return success; + return success; + } + finally + { + File.Delete(temp); + Directory.Delete(extractedFolder, true); + } }); + AddAssert("track is not virtual", () => Beatmap.Value.Track is not TrackVirtual); AddAssert("track length changed", () => Beatmap.Value.Track.Length > 60000); } @@ -133,7 +164,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("new beatmap persisted", () => { var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == firstDifficultyName); - var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + var set = beatmapManager.QueryBeatmapSet(s => s.ID == currentBeatmapSetID); return beatmap != null && beatmap.DifficultyName == firstDifficultyName @@ -152,7 +183,7 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for created", () => { - string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; return difficultyName != null && difficultyName != firstDifficultyName; }); @@ -168,7 +199,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("new beatmap persisted", () => { var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == secondDifficultyName); - var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + var set = beatmapManager.QueryBeatmapSet(s => s.ID == currentBeatmapSetID); return beatmap != null && beatmap.DifficultyName == secondDifficultyName @@ -219,7 +250,7 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("new beatmap persisted", () => { var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == originalDifficultyName); - var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + var set = beatmapManager.QueryBeatmapSet(s => s.ID == currentBeatmapSetID); return beatmap != null && beatmap.DifficultyName == originalDifficultyName @@ -235,7 +266,7 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for created", () => { - string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; return difficultyName != null && difficultyName != originalDifficultyName; }); @@ -254,13 +285,13 @@ namespace osu.Game.Tests.Visual.Editing AddStep("save beatmap", () => Editor.Save()); - BeatmapInfo refetchedBeatmap = null; - Live refetchedBeatmapSet = null; + BeatmapInfo? refetchedBeatmap = null; + Live? refetchedBeatmapSet = null; AddStep("refetch from database", () => { refetchedBeatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == copyDifficultyName); - refetchedBeatmapSet = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + refetchedBeatmapSet = beatmapManager.QueryBeatmapSet(s => s.ID == currentBeatmapSetID); }); AddAssert("new beatmap persisted", () => @@ -296,7 +327,7 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for created", () => { - string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; return difficultyName != null && difficultyName != "New Difficulty"; }); AddAssert("new difficulty has correct name", () => EditorBeatmap.BeatmapInfo.DifficultyName == "New Difficulty (1)"); @@ -332,7 +363,7 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for created", () => { - string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + string? difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; return difficultyName != null && difficultyName != duplicate_difficulty_name; }); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs index ab53f4fd93..109a49310a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorChangeStates.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs index e41f8372b4..23e137865c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs index 393d3886e7..3be6371f28 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs index 028509ccd4..56435c69a4 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs index ad6fc55a32..913155aafb 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs new file mode 100644 index 0000000000..327d581e37 --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs @@ -0,0 +1,57 @@ +// 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; +using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Edit; +using osu.Game.Screens.Edit.GameplayTest; +using osu.Game.Screens.Select; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Visual.Editing +{ + public class TestSceneEditorNavigation : OsuGameTestScene + { + [Test] + public void TestEditorGameplayTestAlwaysUsesOriginalRuleset() + { + BeatmapSetInfo beatmapSet = null!; + + AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely()); + AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach()); + + AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet)); + AddUntilStep("wait for song select", + () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet) + && Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect + && songSelect.IsLoaded); + AddStep("switch ruleset", () => Game.Ruleset.Value = new ManiaRuleset().RulesetInfo); + + AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); + AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); + AddStep("test gameplay", () => ((Editor)Game.ScreenStack.CurrentScreen).TestGameplay()); + + AddUntilStep("wait for player", () => + { + // notifications may fire at almost any inopportune time and cause annoying test failures. + // relentlessly attempt to dismiss any and all interfering overlays, which includes notifications. + // this is theoretically not foolproof, but it's the best that can be done here. + Game.CloseAllOverlays(); + return Game.ScreenStack.CurrentScreen is EditorPlayer editorPlayer && editorPlayer.IsLoaded; + }); + + AddAssert("current ruleset is osu!", () => Game.Ruleset.Value.Equals(new OsuRuleset().RulesetInfo)); + + AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(PlaySongSelect).Yield())); + AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect); + AddAssert("previous ruleset restored", () => Game.Ruleset.Value.Equals(new ManiaRuleset().RulesetInfo)); + } + } +} diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs index 2abc8a8dec..43a3cb1342 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSamplePlayback.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs index e75c7f25a3..d7e9cc1bc0 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs @@ -1,13 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Utils; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Overlays; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Screens.Select; @@ -20,7 +25,9 @@ namespace osu.Game.Tests.Visual.Editing [Test] public void TestCantExitWithoutSaving() { + AddUntilStep("Wait for dialog overlay load", () => ((Drawable)Game.Dependencies.Get()).IsLoaded); AddRepeatStep("Exit", () => InputManager.Key(Key.Escape), 10); + AddAssert("Sample playback disabled", () => Editor.SamplePlaybackDisabled.Value); AddAssert("Editor is still active screen", () => Game.ScreenStack.CurrentScreen is Editor); } @@ -37,6 +44,8 @@ namespace osu.Game.Tests.Visual.Editing SaveEditor(); + AddAssert("Hash updated", () => !string.IsNullOrEmpty(EditorBeatmap.BeatmapInfo.BeatmapSet?.Hash)); + AddAssert("Beatmap has correct metadata", () => EditorBeatmap.BeatmapInfo.Metadata.Artist == "artist" && EditorBeatmap.BeatmapInfo.Metadata.Title == "title"); AddAssert("Beatmap has correct author", () => EditorBeatmap.BeatmapInfo.Metadata.Author.Username == "author"); AddAssert("Beatmap has correct difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName == "difficulty"); @@ -115,8 +124,8 @@ namespace osu.Game.Tests.Visual.Editing // After placement these must be non-default as defaults are read-only. AddAssert("Placed object has non-default control points", () => - EditorBeatmap.HitObjects[0].SampleControlPoint != SampleControlPoint.DEFAULT && - EditorBeatmap.HitObjects[0].DifficultyControlPoint != DifficultyControlPoint.DEFAULT); + !ReferenceEquals(EditorBeatmap.HitObjects[0].SampleControlPoint, SampleControlPoint.DEFAULT) && + !ReferenceEquals(EditorBeatmap.HitObjects[0].DifficultyControlPoint, DifficultyControlPoint.DEFAULT)); ReloadEditorToSameBeatmap(); @@ -124,8 +133,56 @@ namespace osu.Game.Tests.Visual.Editing // After placement these must be non-default as defaults are read-only. AddAssert("Placed object still has non-default control points", () => - EditorBeatmap.HitObjects[0].SampleControlPoint != SampleControlPoint.DEFAULT && - EditorBeatmap.HitObjects[0].DifficultyControlPoint != DifficultyControlPoint.DEFAULT); + !ReferenceEquals(EditorBeatmap.HitObjects[0].SampleControlPoint, SampleControlPoint.DEFAULT) && + !ReferenceEquals(EditorBeatmap.HitObjects[0].DifficultyControlPoint, DifficultyControlPoint.DEFAULT)); + } + + [Test] + public void TestLengthAndStarRatingUpdated() + { + WorkingBeatmap working = null; + double lastStarRating = 0; + double lastLength = 0; + + AddStep("Add timing point", () => EditorBeatmap.ControlPointInfo.Add(500, new TimingControlPoint())); + AddStep("Change to placement mode", () => InputManager.Key(Key.Number2)); + AddStep("Move to playfield", () => InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre)); + AddStep("Place single hitcircle", () => InputManager.Click(MouseButton.Left)); + AddAssert("One hitobject placed", () => EditorBeatmap.HitObjects.Count == 1); + + SaveEditor(); + AddStep("Get working beatmap", () => working = Game.BeatmapManager.GetWorkingBeatmap(EditorBeatmap.BeatmapInfo, true)); + + AddAssert("Beatmap length is zero", () => working.BeatmapInfo.Length == 0); + checkDifficultyIncreased(); + + AddStep("Move forward", () => InputManager.Key(Key.Right)); + AddStep("Place another hitcircle", () => InputManager.Click(MouseButton.Left)); + AddAssert("Two hitobjects placed", () => EditorBeatmap.HitObjects.Count == 2); + + SaveEditor(); + AddStep("Get working beatmap", () => working = Game.BeatmapManager.GetWorkingBeatmap(EditorBeatmap.BeatmapInfo, true)); + + checkDifficultyIncreased(); + checkLengthIncreased(); + + void checkLengthIncreased() + { + AddStep("Beatmap length increased", () => + { + Assert.That(working.BeatmapInfo.Length, Is.GreaterThan(lastLength)); + lastLength = working.BeatmapInfo.Length; + }); + } + + void checkDifficultyIncreased() + { + AddStep("Beatmap difficulty increased", () => + { + Assert.That(working.BeatmapInfo.StarRating, Is.GreaterThan(lastStarRating)); + lastStarRating = working.BeatmapInfo.StarRating; + }); + } } [Test] diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs index 2efd125f81..962260e1bd 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs index 863f42520b..c8ca273db5 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeekSnapping.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs index da28387c4d..6f248f1247 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs index da0c83bb11..3657878075 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs index 79ea866efe..a5d115331d 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index c9d44fdab7..adb495f3d3 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index 7c05abc2cd..a429c6f58b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Humanizer; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index 4501eea88e..6313842dfd 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Humanizer; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs b/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs index b34974dfc7..328e41ebea 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneLabelledTimeSignature.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs b/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs index 4ecfb0975b..d87bbd8a10 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneMetadataSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs b/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs index bf0a7876a9..78f650f0fa 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePlaybackControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs index 85a98eca47..7ad12c37bc 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneRectangularPositionSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs index 2f6cf46b21..ddb458d570 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs b/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs index d8141619ab..f36524290a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTapButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs index a1218aa3e7..7d881bc259 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTapTimingControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs index 6b54bcb4f0..d2984728b0 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Edit.Compose.Components.Timeline; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs index d55852ec43..603dbf4c67 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs index 81ab4712ab..7e0981ce69 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs index b78512e469..b02f0b09b4 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs index d726bd004e..2cada1989e 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; @@ -12,6 +14,16 @@ namespace osu.Game.Tests.Visual.Editing public override Drawable CreateTestComponent() => Empty(); [Test] + [FlakyTest] + /* + * Fail rate around 0.3% + * + * TearDown : osu.Framework.Testing.Drawables.Steps.AssertButton+TracedException : range halved + * --TearDown + * at osu.Framework.Threading.ScheduledDelegate.RunTaskInternal() + * at osu.Framework.Threading.Scheduler.Update() + * at osu.Framework.Graphics.Drawable.UpdateSubTree() + */ public void TestVisibleRangeUpdatesOnZoomChange() { double initialVisibleRange = 0; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs index a358166477..e262bd756a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimingScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs b/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs index eb7e90f0a7..82b0d70cff 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneWaveform.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs b/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs index 2d056bafdd..9dc403814b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -78,6 +80,21 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("Inner container width matches scroll container", () => innerBox.DrawWidth == scrollContainer.DrawWidth); } + [Test] + public void TestZoomRangeUpdate() + { + AddStep("set zoom to 2", () => scrollContainer.Zoom = 2); + AddStep("set min zoom to 5", () => scrollContainer.MinZoom = 5); + AddAssert("zoom = 5", () => scrollContainer.Zoom == 5); + + AddStep("set max zoom to 10", () => scrollContainer.MaxZoom = 10); + AddAssert("zoom = 5", () => scrollContainer.Zoom == 5); + + AddStep("set min zoom to 20", () => scrollContainer.MinZoom = 20); + AddStep("set max zoom to 40", () => scrollContainer.MaxZoom = 40); + AddAssert("zoom = 20", () => scrollContainer.Zoom == 20); + } + [Test] public void TestZoom0() { diff --git a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs index 93bfb288d2..437f06c47f 100644 --- a/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs +++ b/osu.Game.Tests/Visual/Editing/TimelineTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs b/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs index cbf8515567..f173170da5 100644 --- a/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs index 6de9d7c478..3ecf560eb1 100644 --- a/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/SkinnableHUDComponentTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs index e10ef57a25..a8d7148bd2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAllRulesetPlayers.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 346a88a2d5..47c8dc0f8d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -1,13 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using System.Linq; using osu.Framework.Testing; -using osu.Game.Beatmaps.Timing; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osu.Game.Screens.Play.Break; @@ -29,19 +31,20 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { + // It doesn't matter which ruleset is used - this beatmap is only used for reference. + var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo); + AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2)); - seekToBreak(0); + + seekTo(beatmap.Beatmap.Breaks[0].StartTime); AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting); AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType().Single().AccuracyDisplay.Current.Value == 1); + AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000)); AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); - seekToBreak(0); - seekToBreak(1); - - AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); - + seekTo(beatmap.Beatmap.HitObjects[^1].GetEndTime()); AddUntilStep("results displayed", () => getResultsScreen()?.IsLoaded == true); AddAssert("score has combo", () => getResultsScreen().Score.Combo > 100); @@ -56,12 +59,18 @@ namespace osu.Game.Tests.Visual.Gameplay ResultsScreen getResultsScreen() => Stack.CurrentScreen as ResultsScreen; } - private void seekToBreak(int breakIndex) + private void seekTo(double time) { - AddStep($"seek to break {breakIndex}", () => Player.GameplayClockContainer.Seek(destBreak().StartTime)); - AddUntilStep("wait for seek to complete", () => Player.DrawableRuleset.FrameStableClock.CurrentTime >= destBreak().StartTime); + AddStep($"seek to {time}", () => Player.GameplayClockContainer.Seek(time)); - BreakPeriod destBreak() => Beatmap.Value.Beatmap.Breaks.ElementAt(breakIndex); + // Prevent test timeouts by seeking in 10 second increments. + for (double t = 0; t < time; t += 10000) + { + double expectedTime = t; + AddUntilStep($"current time >= {t}", () => Player.DrawableRuleset.FrameStableClock.CurrentTime >= expectedTime); + } + + AddUntilStep("wait for seek to complete", () => Player.DrawableRuleset.FrameStableClock.CurrentTime >= time); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs index 8ca49837da..cfd282c404 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs index e9aa85f4ce..d4f3d0f390 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapSkinFallbacks.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs index be17721b88..e31b325d54 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBreakTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index 11bd701e19..13ceb05aff 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -59,6 +61,16 @@ namespace osu.Game.Tests.Visual.Gameplay /// Tests whether can still pause after cancelling completion by reverting back to true. /// [Test] + [FlakyTest] + /* + * Fail rate around 0.45% + * + * TearDown : System.TimeoutException : "completion set by processor" timed out + * --TearDown + * at osu.Framework.Testing.Drawables.Steps.UntilStepButton.<>c__DisplayClass11_0.<.ctor>b__0() + * at osu.Framework.Testing.Drawables.Steps.StepButton.PerformStep(Boolean userTriggered) + * at osu.Framework.Testing.TestScene.runNextStep(Action onCompletion, Action`1 onError, Func`2 stopCondition) + */ public void TestCanPauseAfterCancellation() { complete(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index e1755b8fc3..a79ba0ae5d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -320,8 +322,8 @@ namespace osu.Game.Tests.Visual.Gameplay { switch (h) { - case TestPooledHitObject _: - case TestPooledParentHitObject _: + case TestPooledHitObject: + case TestPooledParentHitObject: return null; case TestParentHitObject p: diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs index b2f4fa2738..ca7d7b42d8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableStoryboardSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index 83d7d769df..ce01bf2fb5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Graphics.Containers; @@ -51,7 +53,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - HealthProcessor.FailConditions += (_, __) => true; + HealthProcessor.FailConditions += (_, _) => true; } private double lastFrequency = double.MaxValue; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index bf491db45a..5e87eff717 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Rulesets; @@ -47,7 +49,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - HealthProcessor.FailConditions += (_, __) => true; + HealthProcessor.FailConditions += (_, _) => true; } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs index c335f7c99e..90e36ecae2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailingLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs index ae0decaee1..97ffbfc796 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFrameStabilityContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs index 74212de210..663e398c01 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs index abd43e7427..f3a6302da0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayMenuOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 814b41cdbc..0a32513834 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs index 815cc09448..f1084bca5f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySamplePlayback.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index ac39395567..79e3cf000e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Audio; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 83c557ee51..dd0f965914 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -14,6 +16,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD.HitErrorMeters; using osu.Game.Skinning; using osu.Game.Tests.Gameplay; using osuTK.Input; @@ -145,6 +148,26 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("key counters still hidden", () => !keyCounterFlow.IsPresent); } + [Test] + public void TestHiddenHUDDoesntBlockComponentUpdates() + { + int updateCount = 0; + + AddStep("set hud to never show", () => localConfig.SetValue(OsuSetting.HUDVisibilityMode, HUDVisibilityMode.Never)); + + createNew(); + + AddUntilStep("wait for hud load", () => hudOverlay.IsLoaded); + AddUntilStep("wait for components to be hidden", () => hudOverlay.ChildrenOfType().Single().Alpha == 0); + + AddStep("bind on update", () => + { + hudOverlay.ChildrenOfType().First().OnUpdate += _ => updateCount++; + }); + + AddUntilStep("wait for updates", () => updateCount > 0); + } + [Test] public void TestHiddenHUDDoesntBlockSkinnableComponentsLoad() { @@ -153,7 +176,7 @@ namespace osu.Game.Tests.Visual.Gameplay createNew(); AddUntilStep("wait for hud load", () => hudOverlay.IsLoaded); - AddUntilStep("wait for components to be hidden", () => !hudOverlay.ChildrenOfType().Single().IsPresent); + AddUntilStep("wait for components to be hidden", () => hudOverlay.ChildrenOfType().Single().Alpha == 0); AddStep("reload components", () => hudOverlay.ChildrenOfType().Single().Reload()); AddUntilStep("skinnable components loaded", () => hudOverlay.ChildrenOfType().Single().ComponentsLoaded); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 7febb54010..707f807e64 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -142,6 +144,36 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("no circle added", () => !this.ChildrenOfType().Any()); } + [Test] + public void TestProcessingWhileHidden() + { + AddStep("OD 1", () => recreateDisplay(new OsuHitWindows(), 1)); + + AddStep("hide displays", () => + { + foreach (var hitErrorMeter in this.ChildrenOfType()) + hitErrorMeter.Hide(); + }); + + AddRepeatStep("hit", () => newJudgement(), ColourHitErrorMeter.MAX_DISPLAYED_JUDGEMENTS * 2); + + AddAssert("bars added", () => this.ChildrenOfType().Any()); + AddAssert("circle added", () => this.ChildrenOfType().Any()); + + AddUntilStep("wait for bars to disappear", () => !this.ChildrenOfType().Any()); + AddUntilStep("ensure max circles not exceeded", () => + { + return this.ChildrenOfType() + .All(m => m.ChildrenOfType().Count() <= ColourHitErrorMeter.MAX_DISPLAYED_JUDGEMENTS); + }); + + AddStep("show displays", () => + { + foreach (var hitErrorMeter in this.ChildrenOfType()) + hitErrorMeter.Show(); + }); + } + [Test] public void TestClear() { @@ -241,14 +273,14 @@ namespace osu.Game.Tests.Visual.Gameplay public override event Action NewResult { - add => throw new InvalidOperationException(); - remove => throw new InvalidOperationException(); + add => throw new InvalidOperationException($"{nameof(NewResult)} operations not supported in test context"); + remove => throw new InvalidOperationException($"{nameof(NewResult)} operations not supported in test context"); } public override event Action RevertResult { - add => throw new InvalidOperationException(); - remove => throw new InvalidOperationException(); + add => throw new InvalidOperationException($"{nameof(RevertResult)} operations not supported in test context"); + remove => throw new InvalidOperationException($"{nameof(RevertResult)} operations not supported in test context"); } public override Playfield Playfield { get; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs index ddb0872541..50fd1b2a51 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHoldForMenuButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs index 70a43fafb5..c690203f82 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyBindings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 87ab42fe60..bfda6f50cb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs index b90bd93002..7f4276f819 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index 0ada3cf05f..3fd36d509d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Overlays; using osu.Game.Users; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs index 759e4fa4ec..966138c0b3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps.Timing; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNoConflictingModAcronyms.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNoConflictingModAcronyms.cs new file mode 100644 index 0000000000..b2ba3d99ad --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNoConflictingModAcronyms.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. + +#nullable disable +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Testing; + +namespace osu.Game.Tests.Visual.Gameplay +{ + [HeadlessTest] + public class TestSceneNoConflictingModAcronyms : TestSceneAllRulesetPlayers + { + protected override void AddCheckSteps() + { + AddStep("Check all mod acronyms are unique", () => + { + var mods = Ruleset.Value.CreateInstance().AllMods; + + IEnumerable acronyms = mods.Select(m => m.Acronym); + + Assert.That(acronyms, Is.Unique); + }); + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs index b308f3d7d8..3e637f1870 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneOverlayActivation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs index 82095cb809..bddf051871 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs index ce5cd629e0..26706d9465 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneParticleSpewer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index ab5d766609..5bd0a29308 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs index 49c1163c6c..e1c755b90c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs index aefe0db36a..a86e707400 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePerformancePointsCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 950c755cc1..56588e4d4e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs new file mode 100644 index 0000000000..6491987abe --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLocalScoreImport.cs @@ -0,0 +1,145 @@ +// Copyright (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 NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Extensions; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Graphics.Containers; +using osu.Framework.Platform; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Screens.Ranking; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestScenePlayerLocalScoreImport : PlayerTestScene + { + private BeatmapManager beatmaps = null!; + private RulesetStore rulesets = null!; + + private BeatmapSetInfo? importedSet; + + [BackgroundDependencyLoader] + private void load(GameHost host, AudioManager audio) + { + Dependencies.Cache(rulesets = new RealmRulesetStore(Realm)); + Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, Realm, rulesets, null, audio, Resources, host, Beatmap.Default)); + Dependencies.Cache(new ScoreManager(rulesets, () => beatmaps, LocalStorage, Realm, Scheduler, API)); + Dependencies.Cache(Realm); + } + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("import beatmap", () => + { + beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); + importedSet = beatmaps.GetAllUsableBeatmapSets().First(); + }); + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => beatmaps.GetWorkingBeatmap(importedSet?.Beatmaps.First()).Beatmap; + + private Ruleset? customRuleset; + + protected override Ruleset CreatePlayerRuleset() => customRuleset ?? new OsuRuleset(); + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false); + + protected override bool HasCustomSteps => true; + + protected override bool AllowFail => allowFail; + + private bool allowFail; + + [SetUp] + public void SetUp() + { + allowFail = false; + customRuleset = null; + } + + [Test] + public void TestSaveFailedReplay() + { + AddStep("allow fail", () => allowFail = true); + + CreateTest(); + + AddUntilStep("fail screen displayed", () => Player.ChildrenOfType().First().State.Value == Visibility.Visible); + AddUntilStep("score not in database", () => Realm.Run(r => r.Find(Player.Score.ScoreInfo.ID) == null)); + AddStep("click save button", () => Player.ChildrenOfType().First().ChildrenOfType().First().TriggerClick()); + AddUntilStep("score not in database", () => Realm.Run(r => r.Find(Player.Score.ScoreInfo.ID) != null)); + } + + [Test] + public void TestLastPlayedUpdated() + { + DateTimeOffset? getLastPlayed() => Realm.Run(r => r.Find(Beatmap.Value.BeatmapInfo.ID)?.LastPlayed); + + AddAssert("last played is null", () => getLastPlayed() == null); + + CreateTest(); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + AddUntilStep("wait for last played to update", () => getLastPlayed() != null); + } + + [Test] + public void TestScoreStoredLocally() + { + CreateTest(); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + AddUntilStep("score in database", () => Realm.Run(r => r.Find(Player.Score.ScoreInfo.ID) != null)); + } + + [Test] + public void TestScoreStoredLocallyCustomRuleset() + { + Ruleset createCustomRuleset() => new CustomRuleset(); + + AddStep("import custom ruleset", () => Realm.Write(r => r.Add(createCustomRuleset().RulesetInfo))); + AddStep("set custom ruleset", () => customRuleset = createCustomRuleset()); + + CreateTest(); + + AddAssert("score has custom ruleset", () => Player.Score.ScoreInfo.Ruleset.Equals(customRuleset.AsNonNull().RulesetInfo)); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + AddUntilStep("score in database", () => Realm.Run(r => r.Find(Player.Score.ScoreInfo.ID) != null)); + } + + private class CustomRuleset : OsuRuleset, ILegacyRuleset + { + public override string Description => "custom"; + public override string ShortName => "custom"; + + int ILegacyRuleset.LegacyID => -1; + + public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index 7c2f1c5bb2..ec0eea62d9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Lists; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 58b5df2612..96efca6b65 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; @@ -363,21 +365,9 @@ namespace osu.Game.Tests.Visual.Gameplay ImportedScore = score; - // It was discovered that Score members could sometimes be half-populated. - // In particular, the RulesetID property could be set to 0 even on non-osu! maps. - // We want to test that the state of that property is consistent in this test. - // EF makes this impossible. - // - // First off, because of the EF navigational property-explicit foreign key field duality, - // it can happen that - for example - the Ruleset navigational property is correctly initialised to mania, - // but the RulesetID foreign key property is not initialised and remains 0. - // EF silently bypasses this by prioritising the Ruleset navigational property over the RulesetID foreign key one. - // - // Additionally, adding an entity to an EF DbSet CAUSES SIDE EFFECTS with regard to the foreign key property. - // In the above instance, if a ScoreInfo with Ruleset = {mania} and RulesetID = 0 is attached to an EF context, - // RulesetID WILL BE SILENTLY SET TO THE CORRECT VALUE of 3. - // - // For the above reasons, actual importing is disabled in this test. + // Calling base.ImportScore is omitted as it will fail for the test method which uses a custom ruleset. + // This can be resolved by doing something similar to what TestScenePlayerLocalScoreImport is doing, + // but requires a bit of restructuring. } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs index 911fffbe7f..1fa4885b7a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index 8622fe8f53..faa6a429c5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.ComponentModel; using System.Linq; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index e89350de1a..c259d5f0a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; @@ -140,6 +142,28 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); } + [Test] + public void TestLocallyAvailableWithoutReplay() + { + Live imported = null; + + AddStep("import score", () => imported = scoreManager.Import(getScoreInfo(false, false))); + + AddStep("create button without replay", () => + { + Child = downloadButton = new TestReplayDownloadButton(imported.Value) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + }); + + AddUntilStep("wait for load", () => downloadButton.IsLoaded); + + AddUntilStep("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded); + AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); + } + [Test] public void TestScoreImportThenDelete() { @@ -187,11 +211,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType().First().Enabled.Value); } - private ScoreInfo getScoreInfo(bool replayAvailable) + private ScoreInfo getScoreInfo(bool replayAvailable, bool hasOnlineId = true) { return new APIScore { - OnlineID = online_score_id, + OnlineID = hasOnlineId ? online_score_id : 0, RulesetID = 0, Beatmap = CreateAPIBeatmapSet(new OsuRuleset().RulesetInfo).Beatmaps.First(), HasReplay = replayAvailable, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs index fcd65eaff3..6319b91a38 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index 8362739d3b..54b2e66f2f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index 283fe594ea..8a4818d2f8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 74ce9726e7..f319290441 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -43,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestToggleEditor() { - AddToggleStep("toggle editor visibility", visible => skinEditor.ToggleVisibility()); + AddToggleStep("toggle editor visibility", _ => skinEditor.ToggleVisibility()); } [Test] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs index 5385a9983b..f88b4be3d8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 5f838b8813..3eb92b3e97 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs index 9c713b4616..1288f2a9f1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs index f507172931..eacab6d34f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs index 35130f3109..16593effd6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Globalization; @@ -101,7 +103,7 @@ namespace osu.Game.Tests.Visual.Gameplay Child = new SkinProvidingContainer(secondarySource) { RelativeSizeAxes = Axes.Both, - Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation")) + Child = consumer = new SkinConsumer("test", _ => new NamedBox("Default Implementation")) } }; }); @@ -130,7 +132,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; }); - AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation")))); + AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", _ => new NamedBox("Default Implementation")))); AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); } @@ -153,7 +155,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; }); - AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation")))); + AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", _ => new NamedBox("Default Implementation")))); AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); AddStep("disable", () => target.Disable()); AddAssert("consumer using base source", () => consumer.Drawable is BaseSourceBox); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 5f2d9ee9e8..ee2827122d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index 057798c922..2d6ad28b90 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs index a871e37ad4..1b3538cc21 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index 31abcb6748..36b07043dc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs index e08e03b789..e1fc65404d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs index 9750838433..7044ddad37 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSliderPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 733e8f4290..07efb25b46 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index b5cdd61ee5..a42e86933f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs index 034519fbf8..c55e98c1a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Online.API; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 2d2e05c4c9..5fad661e9b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -165,11 +167,16 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("start failing sends", () => { spectatorClient.ShouldFailSendingFrames = true; - framesReceivedSoFar = replay.Frames.Count; frameSendAttemptsSoFar = spectatorClient.FrameSendAttempts; }); - AddUntilStep("wait for send attempts", () => spectatorClient.FrameSendAttempts > frameSendAttemptsSoFar + 5); + AddUntilStep("wait for next send attempt", () => + { + framesReceivedSoFar = replay.Frames.Count; + return spectatorClient.FrameSendAttempts > frameSendAttemptsSoFar + 1; + }); + + AddUntilStep("wait for more send attempts", () => spectatorClient.FrameSendAttempts > frameSendAttemptsSoFar + 10); AddAssert("frames did not increase", () => framesReceivedSoFar == replay.Frames.Count); AddStep("stop failing sends", () => spectatorClient.ShouldFailSendingFrames = false); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs index 717485bcc1..708a5e94de 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index 014ccb1652..30c2790fb4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs index 909cab5e3d..f0e184d727 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardSamplePlayback.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -119,7 +121,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void createPlayerTest() { - CreateTest(null); + CreateTest(); AddAssert("storyboard loaded", () => Player.Beatmap.Value.Storyboard != null); waitUntilStoryboardSamplesPlay(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index b87183cbc7..e2b2ad85a3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading.Tasks; @@ -42,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay base.SetUpSteps(); AddStep("enable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, true)); AddStep("set dim level to 0", () => LocalConfig.SetValue(OsuSetting.DimLevel, 0)); - AddStep("reset fail conditions", () => currentFailConditions = (_, __) => false); + AddStep("reset fail conditions", () => currentFailConditions = (_, _) => false); AddStep("set storyboard duration to 2s", () => currentStoryboardDuration = 2000); AddStep("set ShowResults = true", () => showResults = true); } @@ -50,17 +52,18 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardSkipOutro() { - CreateTest(null); + AddStep("set storyboard duration to long", () => currentStoryboardDuration = 200000); + CreateTest(); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("skip outro", () => InputManager.Key(osuTK.Input.Key.Space)); - AddAssert("player is no longer current screen", () => !Player.IsCurrentScreen()); + AddUntilStep("player is no longer current screen", () => !Player.IsCurrentScreen()); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } [Test] public void TestStoryboardNoSkipOutro() { - CreateTest(null); + CreateTest(); AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= currentStoryboardDuration); AddUntilStep("wait for score shown", () => Player.IsScoreShown); } @@ -68,7 +71,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestStoryboardExitDuringOutroStillExits() { - CreateTest(null); + CreateTest(); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("exit via pause", () => Player.ExitViaPause()); AddAssert("player exited", () => !Player.IsCurrentScreen() && Player.GetChildScreen() == null); @@ -78,7 +81,7 @@ namespace osu.Game.Tests.Visual.Gameplay [TestCase(true)] public void TestStoryboardToggle(bool enabledAtBeginning) { - CreateTest(null); + CreateTest(); AddStep($"{(enabledAtBeginning ? "enable" : "disable")} storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, enabledAtBeginning)); AddStep("toggle storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, !enabledAtBeginning)); AddUntilStep("wait for score shown", () => Player.IsScoreShown); @@ -89,7 +92,7 @@ namespace osu.Game.Tests.Visual.Gameplay { CreateTest(() => { - AddStep("fail on first judgement", () => currentFailConditions = (_, __) => true); + AddStep("fail on first judgement", () => currentFailConditions = (_, _) => true); // Fail occurs at 164ms with the provided beatmap. // Fail animation runs for 2.5s realtime but the gameplay time change is *variable* due to the frequency transform being applied, so we need a bit of lenience. @@ -127,7 +130,7 @@ namespace osu.Game.Tests.Visual.Gameplay { SkipOverlay.FadeContainer fadeContainer() => Player.ChildrenOfType().First(); - CreateTest(null); + CreateTest(); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddUntilStep("skip overlay content becomes visible", () => fadeContainer().State == Visibility.Visible); @@ -141,7 +144,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestPerformExitNoOutro() { - CreateTest(null); + CreateTest(); AddStep("disable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, false)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); AddStep("exit via pause", () => Player.ExitViaPause()); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs index c0f1112905..a31347589b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs index ca8ecd490d..60b8691bfb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneUnstableRateCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs index c68cd39c65..66e3612113 100644 --- a/osu.Game.Tests/Visual/Menus/IntroTestScene.cs +++ b/osu.Game.Tests/Visual/Menus/IntroTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index db5891bd4e..57f16bbcce 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs index 7ad49b5dcd..85a3a51ddb 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs index abe8936330..7ab04a22e5 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index 11cea25865..ae63022823 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs index c44363d9ea..1f2eb57b79 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Threading; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs index 642cc68de5..dbe7b9cc74 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs index 10a82089b3..720e32a242 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -22,10 +24,11 @@ namespace osu.Game.Tests.Visual.Menus public void TestMusicPlayAction() { AddStep("ensure playing something", () => Game.MusicController.EnsurePlayingSomething()); + AddUntilStep("music playing", () => Game.MusicController.IsPlaying); AddStep("toggle playback", () => globalActionContainer.TriggerPressed(GlobalAction.MusicPlay)); - AddAssert("music paused", () => !Game.MusicController.IsPlaying && Game.MusicController.UserPauseRequested); + AddUntilStep("music paused", () => !Game.MusicController.IsPlaying && Game.MusicController.UserPauseRequested); AddStep("toggle playback", () => globalActionContainer.TriggerPressed(GlobalAction.MusicPlay)); - AddAssert("music resumed", () => Game.MusicController.IsPlaying && !Game.MusicController.UserPauseRequested); + AddUntilStep("music resumed", () => Game.MusicController.IsPlaying && !Game.MusicController.UserPauseRequested); } [Test] diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index bbab6380ba..7a2b4d5ca5 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs index 4b22af38c5..ba73361566 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index dbc7e54b5e..90e218675c 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -1,16 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; +using JetBrains.Annotations; using Moq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; +using osu.Game.Graphics.Containers; using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Tests.Visual.Menus @@ -23,21 +33,44 @@ namespace osu.Game.Tests.Visual.Menus [Resolved] private IRulesetStore rulesets { get; set; } - private readonly Mock notifications = new Mock(); + [Cached] + private readonly NowPlayingOverlay nowPlayingOverlay = new NowPlayingOverlay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Y = Toolbar.HEIGHT, + }; + + [Cached] + private readonly VolumeOverlay volumeOverlay = new VolumeOverlay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }; + + private readonly Mock notifications = new Mock(); private readonly BindableInt unreadNotificationCount = new BindableInt(); [BackgroundDependencyLoader] private void load() { - Dependencies.CacheAs(notifications.Object); + Dependencies.CacheAs(notifications.Object); notifications.SetupGet(n => n.UnreadCount).Returns(unreadNotificationCount); } [SetUp] public void SetUp() => Schedule(() => { - Child = toolbar = new TestToolbar { State = { Value = Visibility.Visible } }; + Remove(nowPlayingOverlay); + Remove(volumeOverlay); + + Children = new Drawable[] + { + nowPlayingOverlay, + volumeOverlay, + toolbar = new TestToolbar { State = { Value = Visibility.Visible } }, + }; }); [Test] @@ -95,9 +128,98 @@ namespace osu.Game.Tests.Visual.Menus AddAssert("toolbar is visible", () => toolbar.State.Value == Visibility.Visible); } + [Test] + public void TestScrollInput() + { + OsuScrollContainer scroll = null; + + AddStep("add scroll layer", () => Add(scroll = new OsuScrollContainer + { + Depth = 1f, + RelativeSizeAxes = Axes.Both, + Child = new Box + { + RelativeSizeAxes = Axes.X, + Height = DrawHeight * 2, + Colour = ColourInfo.GradientVertical(Color4.Gray, Color4.DarkGray), + } + })); + + AddStep("hover toolbar", () => InputManager.MoveMouseTo(toolbar)); + AddStep("perform scroll", () => InputManager.ScrollVerticalBy(500)); + AddAssert("not scrolled", () => scroll.Current == 0); + } + + [Test] + public void TestVolumeControlViaMusicButtonScroll() + { + AddStep("hover toolbar music button", () => InputManager.MoveMouseTo(this.ChildrenOfType().Single())); + + AddStep("reset volume", () => Audio.Volume.Value = 1); + AddStep("hide volume overlay", () => volumeOverlay.Hide()); + + AddRepeatStep("scroll down", () => InputManager.ScrollVerticalBy(-10), 5); + AddAssert("volume lowered down", () => Audio.Volume.Value < 1); + AddRepeatStep("scroll up", () => InputManager.ScrollVerticalBy(10), 5); + AddAssert("volume raised up", () => Audio.Volume.Value == 1); + + AddStep("move mouse away", () => InputManager.MoveMouseTo(Vector2.Zero)); + AddAssert("button not hovered", () => !this.ChildrenOfType().Single().IsHovered); + + AddStep("set volume to 0.5", () => Audio.Volume.Value = 0.5); + AddStep("hide volume overlay", () => volumeOverlay.Hide()); + + AddRepeatStep("scroll down", () => InputManager.ScrollVerticalBy(-10), 5); + AddAssert("volume not changed", () => Audio.Volume.Value == 0.5); + AddRepeatStep("scroll up", () => InputManager.ScrollVerticalBy(10), 5); + AddAssert("volume not changed", () => Audio.Volume.Value == 0.5); + } + + [Test] + public void TestVolumeControlViaMusicButtonArrowKeys() + { + AddStep("hover toolbar music button", () => InputManager.MoveMouseTo(this.ChildrenOfType().Single())); + + AddStep("reset volume", () => Audio.Volume.Value = 1); + AddStep("hide volume overlay", () => volumeOverlay.Hide()); + + AddRepeatStep("arrow down", () => InputManager.Key(Key.Down), 5); + AddAssert("volume lowered down", () => Audio.Volume.Value < 1); + AddRepeatStep("arrow up", () => InputManager.Key(Key.Up), 5); + AddAssert("volume raised up", () => Audio.Volume.Value == 1); + + AddStep("hide volume overlay", () => volumeOverlay.Hide()); + AddStep("move mouse away", () => InputManager.MoveMouseTo(Vector2.Zero)); + AddAssert("button not hovered", () => !this.ChildrenOfType().Single().IsHovered); + + AddStep("set volume", () => Audio.Volume.Value = 0.5); + AddStep("hide volume overlay", () => volumeOverlay.Hide()); + + AddRepeatStep("arrow down", () => InputManager.Key(Key.Down), 5); + AddAssert("volume not changed", () => Audio.Volume.Value == 0.5); + AddRepeatStep("arrow up", () => InputManager.Key(Key.Up), 5); + AddAssert("volume not changed", () => Audio.Volume.Value == 0.5); + } + public class TestToolbar : Toolbar { public new Bindable OverlayActivationMode => base.OverlayActivationMode as Bindable; } + + // interface mocks break hot reload, mocking this stub implementation instead works around it. + // see: https://github.com/moq/moq4/issues/1252 + [UsedImplicitly] + public class TestNotificationOverlay : INotificationOverlay + { + public virtual void Post(Notification notification) + { + } + + public virtual void Hide() + { + } + + public virtual IBindable UnreadCount => null; + } } } diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs index 87d836687f..d96f80df40 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbarClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs index af874cec91..91fa09b414 100644 --- a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs +++ b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs index a738debecc..631f2e707a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -55,7 +57,7 @@ namespace osu.Game.Tests.Visual.Multiplayer // To emulate `MultiplayerClient.CurrentMatchPlayingUserIds` we need a bindable list of *only IDs*. // This tracks the list of users 1:1. - MultiplayerUsers.BindCollectionChanged((c, e) => + MultiplayerUsers.BindCollectionChanged((_, e) => { switch (e.Action) { diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs index bafc579134..2b461cf6f6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -89,7 +91,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestCreatedWithCorrectMode() { - AddAssert("room created with correct mode", () => MultiplayerClient.APIRoom?.QueueMode.Value == Mode); + AddUntilStep("room created with correct mode", () => MultiplayerClient.ClientAPIRoom?.QueueMode.Value == Mode); } protected void RunGameplay() diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs index 0785315b26..5947cabf7f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; @@ -17,6 +15,7 @@ using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; using osu.Game.Screens.Play; @@ -31,19 +30,19 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestFirstItemSelectedByDefault() { - AddAssert("first item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); + AddUntilStep("first item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID); } [Test] public void TestItemAddedToTheEndOfQueue() { addItem(() => OtherBeatmap); - AddAssert("playlist has 2 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2); + AddUntilStep("playlist has 2 items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 2); addItem(() => InitialBeatmap); - AddAssert("playlist has 3 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 3); + AddUntilStep("playlist has 3 items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 3); - AddAssert("first item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); + AddUntilStep("first item still selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID); } [Test] @@ -51,9 +50,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { RunGameplay(); - AddAssert("playlist has only one item", () => MultiplayerClient.APIRoom?.Playlist.Count == 1); - AddAssert("playlist item is expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true); - AddAssert("last item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); + AddUntilStep("playlist has only one item", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 1); + AddUntilStep("playlist item is expired", () => MultiplayerClient.ClientAPIRoom?.Playlist[0].Expired == true); + AddUntilStep("last item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID); } [Test] @@ -64,13 +63,13 @@ namespace osu.Game.Tests.Visual.Multiplayer RunGameplay(); - AddAssert("first item expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true); - AddAssert("next item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[1].ID); + AddUntilStep("first item expired", () => MultiplayerClient.ClientAPIRoom?.Playlist[0].Expired == true); + AddUntilStep("next item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[1].ID); RunGameplay(); - AddAssert("second item expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == true); - AddAssert("next item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[2].ID); + AddUntilStep("second item expired", () => MultiplayerClient.ClientAPIRoom?.Playlist[1].Expired == true); + AddUntilStep("next item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[2].ID); } [Test] @@ -83,9 +82,9 @@ namespace osu.Game.Tests.Visual.Multiplayer RunGameplay(); AddStep("change queue mode", () => MultiplayerClient.ChangeSettings(queueMode: QueueMode.HostOnly)); - AddAssert("playlist has 3 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 3); - AddAssert("item 2 is not expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == false); - AddAssert("current item is the other beatmap", () => MultiplayerClient.Room?.Settings.PlaylistItemId == 2); + AddUntilStep("playlist has 3 items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 3); + AddUntilStep("item 2 is not expired", () => MultiplayerClient.ClientAPIRoom?.Playlist[1].Expired == false); + AddUntilStep("current item is the other beatmap", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == 2); } [Test] @@ -141,6 +140,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for song select", () => (songSelect = CurrentSubScreen as Screens.Select.SongSelect) != null); AddUntilStep("wait for loaded", () => songSelect.AsNonNull().BeatmapSetsLoaded); + AddUntilStep("wait for ongoing operation to complete", () => !(CurrentScreen as OnlinePlayScreen).ChildrenOfType().Single().InProgress.Value); if (ruleset != null) AddStep($"set {ruleset.Name} ruleset", () => songSelect.AsNonNull().Ruleset.Value = ruleset); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs index 0674fc7a39..317e410f37 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs index ea895a23d2..be1f21a7b2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableLoungeRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; @@ -40,11 +42,11 @@ namespace osu.Game.Tests.Visual.Multiplayer var mockLounge = new Mock(); mockLounge .Setup(l => l.Join(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny>())) - .Callback, Action>((a, b, c, d) => + .Callback, Action>((_, _, _, d) => { Task.Run(() => { - allowResponseCallback.Wait(); + allowResponseCallback.Wait(10000); allowResponseCallback.Reset(); Schedule(() => d?.Invoke("Incorrect password")); }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 3172a68b81..23ef440a4d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs index 60f47a01a9..0a59e0e858 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomParticipantsList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index e2b4b2870f..1797c82fb9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -16,6 +18,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Database; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Cursor; using osu.Game.Models; using osu.Game.Online.API; using osu.Game.Online.Rooms; @@ -193,12 +196,15 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDownloadButtonHiddenWhenBeatmapExists() { - var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; Live imported = null; - Debug.Assert(beatmap.BeatmapSet != null); + AddStep("import beatmap", () => + { + var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; - AddStep("import beatmap", () => imported = manager.Import(beatmap.BeatmapSet)); + Debug.Assert(beatmap.BeatmapSet != null); + imported = manager.Import(beatmap.BeatmapSet); + }); createPlaylistWithBeatmaps(() => imported.PerformRead(s => s.Beatmaps.Detach())); @@ -243,40 +249,35 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestExpiredItems() { - AddStep("create playlist", () => + createPlaylist(p => { - Child = playlist = new TestPlaylist + p.Items.Clear(); + p.Items.AddRange(new[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500, 300), - Items = + new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo) { - new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo) + ID = 0, + RulesetID = new OsuRuleset().RulesetInfo.OnlineID, + Expired = true, + RequiredMods = new[] { - ID = 0, - RulesetID = new OsuRuleset().RulesetInfo.OnlineID, - Expired = true, - RequiredMods = new[] - { - new APIMod(new OsuModHardRock()), - new APIMod(new OsuModDoubleTime()), - new APIMod(new OsuModAutoplay()) - } - }, - new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo) + new APIMod(new OsuModHardRock()), + new APIMod(new OsuModDoubleTime()), + new APIMod(new OsuModAutoplay()) + } + }, + new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo) + { + ID = 1, + RulesetID = new OsuRuleset().RulesetInfo.OnlineID, + RequiredMods = new[] { - ID = 1, - RulesetID = new OsuRuleset().RulesetInfo.OnlineID, - RequiredMods = new[] - { - new APIMod(new OsuModHardRock()), - new APIMod(new OsuModDoubleTime()), - new APIMod(new OsuModAutoplay()) - } + new APIMod(new OsuModHardRock()), + new APIMod(new OsuModDoubleTime()), + new APIMod(new OsuModAutoplay()) } } - }; + }); }); AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); @@ -319,19 +320,44 @@ namespace osu.Game.Tests.Visual.Multiplayer => AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType().ElementAt(2 + index * 2).Alpha > 0) == visible); + private void createPlaylistWithBeatmaps(Func> beatmaps) => createPlaylist(p => + { + int index = 0; + + p.Items.Clear(); + + foreach (var b in beatmaps()) + { + p.Items.Add(new PlaylistItem(b) + { + ID = index++, + OwnerID = 2, + RulesetID = new OsuRuleset().RulesetInfo.OnlineID, + RequiredMods = new[] + { + new APIMod(new OsuModHardRock()), + new APIMod(new OsuModDoubleTime()), + new APIMod(new OsuModAutoplay()) + } + }); + } + }); + private void createPlaylist(Action setupPlaylist = null) { AddStep("create playlist", () => { - Child = playlist = new TestPlaylist + Child = new OsuContextMenuContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500, 300) + RelativeSizeAxes = Axes.Both, + Child = playlist = new TestPlaylist + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500, 300) + } }; - setupPlaylist?.Invoke(playlist); - for (int i = 0; i < 20; i++) { playlist.Items.Add(new PlaylistItem(i % 2 == 1 @@ -358,39 +384,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); } - }); - AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); - } - - private void createPlaylistWithBeatmaps(Func> beatmaps) - { - AddStep("create playlist", () => - { - Child = playlist = new TestPlaylist - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500, 300) - }; - - int index = 0; - - foreach (var b in beatmaps()) - { - playlist.Items.Add(new PlaylistItem(b) - { - ID = index++, - OwnerID = 2, - RulesetID = new OsuRuleset().RulesetInfo.OnlineID, - RequiredMods = new[] - { - new APIMod(new OsuModHardRock()), - new APIMod(new OsuModDoubleTime()), - new APIMod(new OsuModAutoplay()) - } - }); - } + setupPlaylist?.Invoke(playlist); }); AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index a8471edbf8..457af3e4af 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs index c3487751b9..a08791ecff 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneGameplayChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Moq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs index c3ec7a5369..800b523a9d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -22,7 +24,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestFirstItemSelectedByDefault() { - AddAssert("first item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); + AddUntilStep("first item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID); } [Test] @@ -30,7 +32,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { selectNewItem(() => InitialBeatmap); - AddAssert("playlist item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); + AddUntilStep("playlist item still selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID); } [Test] @@ -38,7 +40,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { selectNewItem(() => OtherBeatmap); - AddAssert("playlist item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); + AddUntilStep("playlist item still selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID); } [Test] @@ -46,10 +48,10 @@ namespace osu.Game.Tests.Visual.Multiplayer { RunGameplay(); - AddAssert("playlist contains two items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2); - AddAssert("first playlist item expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true); - AddAssert("second playlist item not expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == false); - AddAssert("second playlist item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[1].ID); + AddUntilStep("playlist contains two items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 2); + AddUntilStep("first playlist item expired", () => MultiplayerClient.ClientAPIRoom?.Playlist[0].Expired == true); + AddUntilStep("second playlist item not expired", () => MultiplayerClient.ClientAPIRoom?.Playlist[1].Expired == false); + AddUntilStep("second playlist item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[1].ID); } [Test] @@ -58,12 +60,12 @@ namespace osu.Game.Tests.Visual.Multiplayer RunGameplay(); IBeatmapInfo firstBeatmap = null; - AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.APIRoom?.Playlist[0].Beatmap); + AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.ServerAPIRoom?.Playlist[0].Beatmap); selectNewItem(() => OtherBeatmap); - AddAssert("first playlist item hasn't changed", () => MultiplayerClient.APIRoom?.Playlist[0].Beatmap == firstBeatmap); - AddAssert("second playlist item changed", () => MultiplayerClient.APIRoom?.Playlist[1].Beatmap != firstBeatmap); + AddUntilStep("first playlist item hasn't changed", () => MultiplayerClient.ServerAPIRoom?.Playlist[0].Beatmap == firstBeatmap); + AddUntilStep("second playlist item changed", () => MultiplayerClient.ClientAPIRoom?.Playlist[1].Beatmap != firstBeatmap); } [Test] @@ -74,7 +76,7 @@ namespace osu.Game.Tests.Visual.Multiplayer QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("api room updated", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddUntilStep("api room updated", () => MultiplayerClient.ClientAPIRoom?.QueueMode.Value == QueueMode.AllPlayers); } [Test] @@ -82,7 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { addItem(() => OtherBeatmap); - AddAssert("playlist contains two items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2); + AddUntilStep("playlist contains two items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 2); } private void selectNewItem(Func beatmap) @@ -102,6 +104,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for song select", () => CurrentSubScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded); BeatmapInfo otherBeatmap = null; + AddUntilStep("wait for ongoing operation to complete", () => !(CurrentScreen as OnlinePlayScreen).ChildrenOfType().Single().InProgress.Value); AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(otherBeatmap = beatmap())); AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen); @@ -117,6 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddUntilStep("wait for song select", () => CurrentSubScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded); + AddUntilStep("wait for ongoing operation to complete", () => !(CurrentScreen as OnlinePlayScreen).ChildrenOfType().Single().InProgress.Value); AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(beatmap())); AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs index 93cd281bc5..82e7bf8969 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; @@ -155,6 +157,28 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3); } + [Test] + public void TestAccessTypeFiltering() + { + AddStep("add rooms", () => + { + RoomManager.AddRooms(1, withPassword: true); + RoomManager.AddRooms(1, withPassword: false); + }); + + AddStep("apply default filter", () => container.Filter.SetDefault()); + + AddUntilStep("both rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 2); + + AddStep("filter public rooms", () => container.Filter.Value = new FilterCriteria { Permissions = RoomPermissionsFilter.Public }); + + AddUntilStep("private room hidden", () => container.Rooms.All(r => !r.Room.HasPassword.Value)); + + AddStep("filter private rooms", () => container.Filter.Value = new FilterCriteria { Permissions = RoomPermissionsFilter.Private }); + + AddUntilStep("public room hidden", () => container.Rooms.All(r => r.Room.HasPassword.Value)); + } + [Test] public void TestPasswordProtectedRooms() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 6f43511e8a..8cdcdfdfdf 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online.API; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 955710bd50..506d7541a7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs index ff6c02c4e5..a800b21bc9 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using Moq; @@ -88,7 +90,7 @@ namespace osu.Game.Tests.Visual.Multiplayer setRoomCountdown(countdownStart.Duration); break; - case StopCountdownRequest _: + case StopCountdownRequest: multiplayerRoom.Countdown = null; raiseRoomUpdated(); break; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs index 2244dcfc56..70c6271d24 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 60215dc8b3..80c356ec67 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index c048722804..7df68392cf 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -31,20 +31,21 @@ namespace osu.Game.Tests.Visual.Multiplayer public class TestSceneMultiSpectatorScreen : MultiplayerTestScene { [Resolved] - private OsuGameBase game { get; set; } + private OsuGameBase game { get; set; } = null!; [Resolved] - private OsuConfigManager config { get; set; } + private OsuConfigManager config { get; set; } = null!; [Resolved] - private BeatmapManager beatmapManager { get; set; } + private BeatmapManager beatmapManager { get; set; } = null!; - private MultiSpectatorScreen spectatorScreen; + private MultiSpectatorScreen spectatorScreen = null!; private readonly List playingUsers = new List(); - private BeatmapSetInfo importedSet; - private BeatmapInfo importedBeatmap; + private BeatmapSetInfo importedSet = null!; + private BeatmapInfo importedBeatmap = null!; + private int importedBeatmapId; [BackgroundDependencyLoader] @@ -338,7 +339,7 @@ namespace osu.Game.Tests.Visual.Multiplayer sendFrames(getPlayerIds(count), 300); } - Player player = null; + Player? player = null; AddStep($"get {PLAYER_1_ID} player instance", () => player = getInstance(PLAYER_1_ID).ChildrenOfType().Single()); @@ -367,7 +368,7 @@ namespace osu.Game.Tests.Visual.Multiplayer b.Storyboard.GetLayer("Background").Add(sprite); }); - private void testLeadIn(Action applyToBeatmap = null) + private void testLeadIn(Action? applyToBeatmap = null) { start(PLAYER_1_ID); @@ -385,7 +386,7 @@ namespace osu.Game.Tests.Visual.Multiplayer assertRunning(PLAYER_1_ID); } - private void loadSpectateScreen(bool waitForPlayerLoad = true, Action applyToBeatmap = null) + private void loadSpectateScreen(bool waitForPlayerLoad = true, Action? applyToBeatmap = null) { AddStep("load screen", () => { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 8e45d99eae..d35887c443 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -49,17 +49,17 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayer : ScreenTestScene { - private BeatmapManager beatmaps; - private RulesetStore rulesets; - private BeatmapSetInfo importedSet; + private BeatmapManager beatmaps = null!; + private RulesetStore rulesets = null!; + private BeatmapSetInfo importedSet = null!; - private TestMultiplayerComponents multiplayerComponents; + private TestMultiplayerComponents multiplayerComponents = null!; private TestMultiplayerClient multiplayerClient => multiplayerComponents.MultiplayerClient; private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager; [Resolved] - private OsuConfigManager config { get; set; } + private OsuConfigManager config { get; set; } = null!; [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) @@ -114,25 +114,25 @@ namespace osu.Game.Tests.Visual.Multiplayer // all ready AddUntilStep("all players ready", () => { - var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); + var nextUnready = multiplayerClient.ClientRoom?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); if (nextUnready != null) multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); - return multiplayerClient.Room?.Users.All(u => u.State == MultiplayerUserState.Ready) == true; + return multiplayerClient.ClientRoom?.Users.All(u => u.State == MultiplayerUserState.Ready) == true; }); AddStep("unready all players at once", () => { - Debug.Assert(multiplayerClient.Room != null); + Debug.Assert(multiplayerClient.ServerRoom != null); - foreach (var u in multiplayerClient.Room.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Idle); + foreach (var u in multiplayerClient.ServerRoom.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Idle); }); AddStep("ready all players at once", () => { - Debug.Assert(multiplayerClient.Room != null); + Debug.Assert(multiplayerClient.ServerRoom != null); - foreach (var u in multiplayerClient.Room.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Ready); + foreach (var u in multiplayerClient.ServerRoom.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Ready); }); } @@ -144,7 +144,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private void removeLastUser() { - APIUser lastUser = multiplayerClient.Room?.Users.Last().User; + APIUser? lastUser = multiplayerClient.ServerRoom?.Users.Last().User; if (lastUser == null || lastUser == multiplayerClient.LocalUser?.User) return; @@ -154,7 +154,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private void kickLastUser() { - APIUser lastUser = multiplayerClient.Room?.Users.Last().User; + APIUser? lastUser = multiplayerClient.ServerRoom?.Users.Last().User; if (lastUser == null || lastUser == multiplayerClient.LocalUser?.User) return; @@ -164,14 +164,14 @@ namespace osu.Game.Tests.Visual.Multiplayer private void markNextPlayerReady() { - var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); + var nextUnready = multiplayerClient.ServerRoom?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); if (nextUnready != null) multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); } private void markNextPlayerIdle() { - var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Ready); + var nextUnready = multiplayerClient.ServerRoom?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Ready); if (nextUnready != null) multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Idle); } @@ -241,8 +241,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddAssert("Check participant count correct", () => multiplayerClient.APIRoom?.ParticipantCount.Value == 1); - AddAssert("Check participant list contains user", () => multiplayerClient.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); + AddUntilStep("Check participant count correct", () => multiplayerClient.ClientAPIRoom?.ParticipantCount.Value == 1); + AddUntilStep("Check participant list contains user", () => multiplayerClient.ClientAPIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); } [Test] @@ -301,8 +301,8 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); - AddAssert("Check participant count correct", () => multiplayerClient.APIRoom?.ParticipantCount.Value == 1); - AddAssert("Check participant list contains user", () => multiplayerClient.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); + AddUntilStep("Check participant count correct", () => multiplayerClient.ClientAPIRoom?.ParticipantCount.Value == 1); + AddUntilStep("Check participant list contains user", () => multiplayerClient.ClientAPIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); } [Test] @@ -321,7 +321,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddAssert("room has password", () => multiplayerClient.APIRoom?.Password.Value == "password"); + AddUntilStep("room has password", () => multiplayerClient.ClientAPIRoom?.Password.Value == "password"); } [Test] @@ -349,7 +349,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("select room", () => InputManager.Key(Key.Down)); AddStep("join room", () => InputManager.Key(Key.Enter)); - DrawableLoungeRoom.PasswordEntryPopover passwordEntryPopover = null; + DrawableLoungeRoom.PasswordEntryPopover? passwordEntryPopover = null; AddUntilStep("password prompt appeared", () => (passwordEntryPopover = InputManager.ChildrenOfType().FirstOrDefault()) != null); AddStep("enter password in text box", () => passwordEntryPopover.ChildrenOfType().First().Text = "password"); AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); @@ -375,7 +375,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddStep("change password", () => multiplayerClient.ChangeSettings(password: "password2")); - AddUntilStep("local password changed", () => multiplayerClient.APIRoom?.Password.Value == "password2"); + AddUntilStep("local password changed", () => multiplayerClient.ClientAPIRoom?.Password.Value == "password2"); } [Test] @@ -402,16 +402,18 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestPlayStartsWithCorrectBeatmapWhileAtSongSelect() { - createRoom(() => new Room + PlaylistItem? item = null; + createRoom(() => { - Name = { Value = "Test Room" }, - Playlist = + item = new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) { - new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) - { - RulesetID = new OsuRuleset().RulesetInfo.OnlineID - } - } + RulesetID = new OsuRuleset().RulesetInfo.OnlineID + }; + return new Room + { + Name = { Value = "Test Room" }, + Playlist = { item } + }; }); pressReadyButton(); @@ -419,37 +421,39 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Enter song select", () => { var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen; - ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId); + ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(item); }); AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true); - AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.Room?.Playlist.First().BeatmapID); + AddUntilStep("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.ClientRoom?.Playlist.First().BeatmapID); AddStep("Select next beatmap", () => InputManager.Key(Key.Down)); - AddUntilStep("Beatmap doesn't match current item", () => Beatmap.Value.BeatmapInfo.OnlineID != multiplayerClient.Room?.Playlist.First().BeatmapID); + AddUntilStep("Beatmap doesn't match current item", () => Beatmap.Value.BeatmapInfo.OnlineID != multiplayerClient.ClientRoom?.Playlist.First().BeatmapID); AddStep("start match externally", () => multiplayerClient.StartMatch().WaitSafely()); AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player); - AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.Room?.Playlist.First().BeatmapID); + AddUntilStep("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.ClientRoom?.Playlist.First().BeatmapID); } [Test] public void TestPlayStartsWithCorrectRulesetWhileAtSongSelect() { - createRoom(() => new Room + PlaylistItem? item = null; + createRoom(() => { - Name = { Value = "Test Room" }, - Playlist = + item = new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) { - new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) - { - RulesetID = new OsuRuleset().RulesetInfo.OnlineID - } - } + RulesetID = new OsuRuleset().RulesetInfo.OnlineID + }; + return new Room + { + Name = { Value = "Test Room" }, + Playlist = { item } + }; }); pressReadyButton(); @@ -457,37 +461,39 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Enter song select", () => { var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen; - ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId); + ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(item); }); AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true); - AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.Room?.Playlist.First().RulesetID); + AddUntilStep("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.ClientRoom?.Playlist.First().RulesetID); AddStep("Switch ruleset", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Ruleset.Value = new CatchRuleset().RulesetInfo); - AddUntilStep("Ruleset doesn't match current item", () => Ruleset.Value.OnlineID != multiplayerClient.Room?.Playlist.First().RulesetID); + AddUntilStep("Ruleset doesn't match current item", () => Ruleset.Value.OnlineID != multiplayerClient.ClientRoom?.Playlist.First().RulesetID); AddStep("start match externally", () => multiplayerClient.StartMatch().WaitSafely()); AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player); - AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.Room?.Playlist.First().RulesetID); + AddUntilStep("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.ClientRoom?.Playlist.First().RulesetID); } [Test] public void TestPlayStartsWithCorrectModsWhileAtSongSelect() { - createRoom(() => new Room + PlaylistItem? item = null; + createRoom(() => { - Name = { Value = "Test Room" }, - Playlist = + item = new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) { - new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) - { - RulesetID = new OsuRuleset().RulesetInfo.OnlineID - } - } + RulesetID = new OsuRuleset().RulesetInfo.OnlineID + }; + return new Room + { + Name = { Value = "Test Room" }, + Playlist = { item } + }; }); pressReadyButton(); @@ -495,25 +501,25 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Enter song select", () => { var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen; - ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId); + ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(item); }); AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true); - AddAssert("Mods match current item", - () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); + AddUntilStep("Mods match current item", + () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.ClientRoom.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); AddStep("Switch required mods", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Mods.Value = new Mod[] { new OsuModDoubleTime() }); - AddAssert("Mods don't match current item", - () => !SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); + AddUntilStep("Mods don't match current item", + () => !SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.ClientRoom.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); AddStep("start match externally", () => multiplayerClient.StartMatch().WaitSafely()); AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player); - AddAssert("Mods match current item", - () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); + AddUntilStep("Mods match current item", + () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.ClientRoom.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); } [Test] @@ -676,7 +682,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestGameplayExitFlow() { - Bindable holdDelay = null; + Bindable? holdDelay = null; AddStep("Set hold delay to zero", () => { @@ -707,7 +713,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for lounge", () => multiplayerComponents.CurrentScreen is Screens.OnlinePlay.Multiplayer.Multiplayer); AddStep("stop holding", () => InputManager.ReleaseKey(Key.Escape)); - AddStep("set hold delay to default", () => holdDelay.SetDefault()); + AddStep("set hold delay to default", () => holdDelay?.SetDefault()); } [Test] @@ -888,7 +894,7 @@ namespace osu.Game.Tests.Visual.Multiplayer RulesetID = new OsuRuleset().RulesetInfo.OnlineID, })).WaitSafely()); - AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2); + AddUntilStep("item arrived in playlist", () => multiplayerClient.ClientRoom?.Playlist.Count == 2); AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent()); AddUntilStep("queue contains item", () => this.ChildrenOfType().Single().Items.Single().ID == 2); @@ -919,10 +925,10 @@ namespace osu.Game.Tests.Visual.Multiplayer RulesetID = new OsuRuleset().RulesetInfo.OnlineID, })).WaitSafely()); - AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2); + AddUntilStep("item arrived in playlist", () => multiplayerClient.ClientRoom?.Playlist.Count == 2); AddStep("delete item as other user", () => multiplayerClient.RemoveUserPlaylistItem(1234, 2).WaitSafely()); - AddUntilStep("item removed from playlist", () => multiplayerClient.Room?.Playlist.Count == 1); + AddUntilStep("item removed from playlist", () => multiplayerClient.ClientRoom?.Playlist.Count == 1); AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent()); AddUntilStep("queue is empty", () => this.ChildrenOfType().Single().Items.Count == 0); @@ -955,7 +961,7 @@ namespace osu.Game.Tests.Visual.Multiplayer runGameplay(); AddStep("exit gameplay for other user", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Idle)); - AddUntilStep("wait for room to be idle", () => multiplayerClient.Room?.State == MultiplayerRoomState.Open); + AddUntilStep("wait for room to be idle", () => multiplayerClient.ClientRoom?.State == MultiplayerRoomState.Open); runGameplay(); @@ -967,9 +973,9 @@ namespace osu.Game.Tests.Visual.Multiplayer multiplayerClient.StartMatch().WaitSafely(); }); - AddUntilStep("wait for loading", () => multiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad); + AddUntilStep("wait for loading", () => multiplayerClient.ClientRoom?.State == MultiplayerRoomState.WaitingForLoad); AddStep("set player loaded", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Loaded)); - AddUntilStep("wait for gameplay to start", () => multiplayerClient.Room?.State == MultiplayerRoomState.Playing); + AddUntilStep("wait for gameplay to start", () => multiplayerClient.ClientRoom?.State == MultiplayerRoomState.Playing); AddUntilStep("wait for local user to enter spectator", () => multiplayerComponents.CurrentScreen is MultiSpectatorScreen); } } @@ -990,11 +996,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for ready button to be enabled", () => readyButton.Enabled.Value); MultiplayerUserState lastState = MultiplayerUserState.Idle; - MultiplayerRoomUser user = null; + MultiplayerRoomUser? user = null; AddStep("click ready button", () => { - user = playingUserId == null ? multiplayerClient.LocalUser : multiplayerClient.Room?.Users.Single(u => u.UserID == playingUserId); + user = playingUserId == null ? multiplayerClient.LocalUser : multiplayerClient.ServerRoom?.Users.Single(u => u.UserID == playingUserId); lastState = user?.State ?? MultiplayerUserState.Idle; InputManager.MoveMouseTo(readyButton); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index cbbd535cee..95fd449dd3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index c25884039f..93ccf3977b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics; using osu.Game.Online.Multiplayer; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs index de3df754a2..1a3fefa603 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerLoungeSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index 111f51675d..a98030e1e3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index eacd80925d..ab4f9c37b2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -105,7 +107,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("change ruleset", () => Ruleset.Value = new TaikoRuleset().RulesetInfo); AddStep("select beatmap", () => songSelect.Carousel.SelectBeatmap(selectedBeatmap = beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == new TaikoRuleset().LegacyID))); + AddUntilStep("wait for selection", () => Beatmap.Value.BeatmapInfo.Equals(selectedBeatmap)); + AddUntilStep("wait for ongoing operation to complete", () => !OnlinePlayDependencies.OngoingOperationTracker.InProgress.Value); + AddStep("set mods", () => SelectedMods.Value = new[] { new TaikoModDoubleTime() }); AddStep("confirm selection", () => songSelect.FinaliseSelection()); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 7ae81c9800..5d6a6c8104 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -72,6 +74,25 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] + [FlakyTest] + /* + * Fail rate around 1.5% + * + * TearDown : System.AggregateException : One or more errors occurred. (Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')) + ----> System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index') + * --TearDown + * at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) + * at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) + * at osu.Framework.Extensions.TaskExtensions.WaitSafely(Task task) + * at osu.Framework.Testing.TestScene.checkForErrors() + * at osu.Framework.Testing.TestScene.RunTestsFromNUnit() + *--ArgumentOutOfRangeException + * at osu.Framework.Bindables.BindableList`1.removeAt(Int32 index, BindableList`1 caller) + * at osu.Framework.Bindables.BindableList`1.removeAt(Int32 index, BindableList`1 caller) + * at osu.Framework.Bindables.BindableList`1.removeAt(Int32 index, BindableList`1 caller) + * at osu.Game.Online.Multiplayer.MultiplayerClient.<>c__DisplayClass106_0.b__0() in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Online\Multiplayer\MultiplayerClient .cs:line 702 + * at osu.Framework.Threading.ScheduledDelegate.RunTaskInternal() + */ public void TestCreatedRoom() { AddStep("add playlist item", () => @@ -88,6 +109,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] + [FlakyTest] // See above public void TestTaikoOnlyMod() { AddStep("add playlist item", () => @@ -108,6 +130,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] + [FlakyTest] // See above public void TestSettingValidity() { AddAssert("create button not enabled", () => !this.ChildrenOfType().Single().Enabled.Value); @@ -124,6 +147,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] + [FlakyTest] // See above public void TestStartMatchWhileSpectating() { AddStep("set playlist", () => @@ -150,10 +174,11 @@ namespace osu.Game.Tests.Visual.Multiplayer ClickButtonWhenEnabled(); - AddUntilStep("match started", () => MultiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad); + AddUntilStep("match started", () => MultiplayerClient.ClientRoom?.State == MultiplayerRoomState.WaitingForLoad); } [Test] + [FlakyTest] // See above public void TestFreeModSelectionHasAllowedMods() { AddStep("add playlist item with allowed mod", () => @@ -174,13 +199,13 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("mod select contents loaded", () => this.ChildrenOfType().Any() && this.ChildrenOfType().All(col => col.IsLoaded && col.ItemsLoaded)); AddUntilStep("mod select contains only double time mod", - () => this.ChildrenOfType() - .SingleOrDefault()? + () => this.ChildrenOfType().Single().UserModsSelectOverlay .ChildrenOfType() .SingleOrDefault(panel => !panel.Filtered.Value)?.Mod is OsuModDoubleTime); } [Test] + [FlakyTest] // See above public void TestModSelectKeyWithAllowedMods() { AddStep("add playlist item with allowed mod", () => @@ -198,10 +223,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("press toggle mod select key", () => InputManager.Key(Key.F1)); - AddUntilStep("mod select shown", () => this.ChildrenOfType().Single().State.Value == Visibility.Visible); + AddUntilStep("mod select shown", () => this.ChildrenOfType().Single().UserModsSelectOverlay.State.Value == Visibility.Visible); } [Test] + [FlakyTest] // See above public void TestModSelectKeyWithNoAllowedMods() { AddStep("add playlist item with no allowed mods", () => @@ -218,10 +244,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("press toggle mod select key", () => InputManager.Key(Key.F1)); AddWaitStep("wait some", 3); - AddAssert("mod select not shown", () => this.ChildrenOfType().Single().State.Value == Visibility.Hidden); + AddAssert("mod select not shown", () => this.ChildrenOfType().Single().UserModsSelectOverlay.State.Value == Visibility.Hidden); } [Test] + [FlakyTest] // See above public void TestNextPlaylistItemSelectedAfterCompletion() { AddStep("add two playlist items", () => @@ -252,7 +279,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("last playlist item selected", () => { - var lastItem = this.ChildrenOfType().Single(p => p.Item.ID == MultiplayerClient.APIRoom?.Playlist.Last().ID); + var lastItem = this.ChildrenOfType().Single(p => p.Item.ID == MultiplayerClient.ServerAPIRoom?.Playlist.Last().ID); return lastItem.IsSelectedItem; }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index 8da077cd44..edd1491865 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Framework.Utils; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; @@ -51,20 +52,20 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("one unique panel", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 1); AddStep("add non-resolvable user", () => MultiplayerClient.TestAddUnresolvedUser()); - AddAssert("null user added", () => MultiplayerClient.Room.AsNonNull().Users.Count(u => u.User == null) == 1); + AddUntilStep("null user added", () => MultiplayerClient.ClientRoom.AsNonNull().Users.Count(u => u.User == null) == 1); AddUntilStep("two unique panels", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 2); AddStep("kick null user", () => this.ChildrenOfType().Single(p => p.User.User == null) .ChildrenOfType().Single().TriggerClick()); - AddAssert("null user kicked", () => MultiplayerClient.Room.AsNonNull().Users.Count == 1); + AddUntilStep("null user kicked", () => MultiplayerClient.ClientRoom.AsNonNull().Users.Count == 1); } [Test] public void TestRemoveUser() { - APIUser secondUser = null; + APIUser? secondUser = null; AddStep("add a user", () => { @@ -78,7 +79,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("remove host", () => MultiplayerClient.RemoveUser(API.LocalUser.Value)); - AddAssert("single panel is for second user", () => this.ChildrenOfType().Single().User.User == secondUser); + AddAssert("single panel is for second user", () => this.ChildrenOfType().Single().User.UserID == secondUser?.Id); } [Test] @@ -215,7 +216,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("kick second user", () => this.ChildrenOfType().Single(d => d.IsPresent).TriggerClick()); - AddAssert("second user kicked", () => MultiplayerClient.Room?.Users.Single().UserID == API.LocalUser.Value.Id); + AddUntilStep("second user kicked", () => MultiplayerClient.ClientRoom?.Users.Single().UserID == API.LocalUser.Value.Id); } [Test] @@ -366,17 +367,21 @@ namespace osu.Game.Tests.Visual.Multiplayer private void createNewParticipantsList() { - ParticipantsList participantsList = null; + ParticipantsList? participantsList = null; - AddStep("create new list", () => Child = participantsList = new ParticipantsList + AddStep("create new list", () => Child = new OsuContextMenuContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Size = new Vector2(380, 0.7f) + RelativeSizeAxes = Axes.Both, + Child = participantsList = new ParticipantsList + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Size = new Vector2(380, 0.7f) + } }); - AddUntilStep("wait for list to load", () => participantsList.IsLoaded); + AddUntilStep("wait for list to load", () => participantsList?.IsLoaded == true); } private void checkProgressBarVisibility(bool visible) => diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs index e05580fed6..f6a6b3c667 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Screens; @@ -28,10 +30,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("initialise gameplay", () => { - Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.APIRoom, new PlaylistItem(Beatmap.Value.BeatmapInfo) + Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.ServerAPIRoom, new PlaylistItem(Beatmap.Value.BeatmapInfo) { RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID, - }, MultiplayerClient.Room?.Users.ToArray())); + }, MultiplayerClient.ServerRoom?.Users.ToArray())); }); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen() && player.IsLoaded); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs index 1231866b36..5ee385810b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs index 117aaeba83..e709a955b3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -50,7 +52,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(500, 300), - Items = { BindTarget = MultiplayerClient.APIRoom!.Playlist } + Items = { BindTarget = MultiplayerClient.ClientAPIRoom!.Playlist } }; }); @@ -68,7 +70,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestDeleteButtonAlwaysVisibleForHost() { AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddUntilStep("wait for queue mode change", () => MultiplayerClient.ClientAPIRoom?.QueueMode.Value == QueueMode.AllPlayers); addPlaylistItem(() => API.LocalUser.Value.OnlineID); assertDeleteButtonVisibility(1, true); @@ -80,7 +82,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestDeleteButtonOnlyVisibleForItemOwnerIfNotHost() { AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddUntilStep("wait for queue mode change", () => MultiplayerClient.ClientAPIRoom?.QueueMode.Value == QueueMode.AllPlayers); AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 1234 })); AddStep("set other user as host", () => MultiplayerClient.TransferHost(1234)); @@ -99,7 +101,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestCurrentItemDoesNotHaveDeleteButton() { AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddUntilStep("wait for queue mode change", () => MultiplayerClient.ClientAPIRoom?.QueueMode.Value == QueueMode.AllPlayers); addPlaylistItem(() => API.LocalUser.Value.OnlineID); @@ -107,7 +109,7 @@ namespace osu.Game.Tests.Visual.Multiplayer assertDeleteButtonVisibility(1, true); AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely()); - AddUntilStep("wait for next item to be selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == 2); + AddUntilStep("wait for next item to be selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == 2); AddUntilStep("wait for two items in playlist", () => playlist.ChildrenOfType().Count() == 2); assertDeleteButtonVisibility(0, false); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs index cc08135939..a638702ceb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index 13917f4eb0..91c87548c7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -97,10 +99,10 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestToggleWhenIdle(MultiplayerUserState initialState) { ClickButtonWhenEnabled(); - AddUntilStep("user is spectating", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Spectating); + AddUntilStep("user is spectating", () => MultiplayerClient.ClientRoom?.Users[0].State == MultiplayerUserState.Spectating); ClickButtonWhenEnabled(); - AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle", () => MultiplayerClient.ClientRoom?.Users[0].State == MultiplayerUserState.Idle); } [TestCase(MultiplayerRoomState.Closed)] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs index c0958c7fe8..089b4a020d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectatorPlayerGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs index 0237298fa1..56260941a8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs index 98dc243ab5..bbccdb0d17 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs index f8d62c9840..88afe1ce7c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs index b0a977dcbb..cb80fb56df 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs index 5e4013b0f1..321e0c2c89 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 19e1f62fd5..d80537a2e5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -74,8 +76,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddUntilStep("room type is team vs", () => multiplayerClient.Room?.Settings.MatchType == MatchType.TeamVersus); - AddAssert("user state arrived", () => multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState); + AddUntilStep("room type is team vs", () => multiplayerClient.ClientRoom?.Settings.MatchType == MatchType.TeamVersus); + AddUntilStep("user state arrived", () => multiplayerClient.ClientRoom?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState); } [Test] @@ -94,7 +96,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddAssert("user on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + AddUntilStep("user on team 0", () => (multiplayerClient.ClientRoom?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); AddStep("add another user", () => multiplayerClient.AddUser(new APIUser { Username = "otheruser", Id = 44 })); AddStep("press own button", () => @@ -102,17 +104,17 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().First()); InputManager.Click(MouseButton.Left); }); - AddAssert("user on team 1", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1); + AddUntilStep("user on team 1", () => (multiplayerClient.ClientRoom?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1); AddStep("press own button again", () => InputManager.Click(MouseButton.Left)); - AddAssert("user on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + AddUntilStep("user on team 0", () => (multiplayerClient.ClientRoom?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); AddStep("press other user's button", () => { InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddAssert("user still on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + AddUntilStep("user still on team 0", () => (multiplayerClient.ClientRoom?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); } [Test] @@ -131,14 +133,14 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddUntilStep("match type head to head", () => multiplayerClient.APIRoom?.Type.Value == MatchType.HeadToHead); + AddUntilStep("match type head to head", () => multiplayerClient.ClientAPIRoom?.Type.Value == MatchType.HeadToHead); AddStep("change match type", () => multiplayerClient.ChangeSettings(new MultiplayerRoomSettings { MatchType = MatchType.TeamVersus }).WaitSafely()); - AddUntilStep("api room updated to team versus", () => multiplayerClient.APIRoom?.Type.Value == MatchType.TeamVersus); + AddUntilStep("api room updated to team versus", () => multiplayerClient.ClientAPIRoom?.Type.Value == MatchType.TeamVersus); } [Test] @@ -156,13 +158,13 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddUntilStep("room type is head to head", () => multiplayerClient.Room?.Settings.MatchType == MatchType.HeadToHead); + AddUntilStep("room type is head to head", () => multiplayerClient.ClientRoom?.Settings.MatchType == MatchType.HeadToHead); AddUntilStep("team displays are not displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam == null)); AddStep("change to team vs", () => multiplayerClient.ChangeSettings(matchType: MatchType.TeamVersus)); - AddUntilStep("room type is team vs", () => multiplayerClient.Room?.Settings.MatchType == MatchType.TeamVersus); + AddUntilStep("room type is team vs", () => multiplayerClient.ClientRoom?.Settings.MatchType == MatchType.TeamVersus); AddUntilStep("team displays are displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam != null)); } diff --git a/osu.Game.Tests/Visual/Navigation/TestEFToRealmMigration.cs b/osu.Game.Tests/Visual/Navigation/TestEFToRealmMigration.cs index 2ea768b878..c3559589ed 100644 --- a/osu.Game.Tests/Visual/Navigation/TestEFToRealmMigration.cs +++ b/osu.Game.Tests/Visual/Navigation/TestEFToRealmMigration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Runtime.InteropServices; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs index 8c96ec699f..bff30b83f9 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index b7a74dcd27..5bd879de14 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs b/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs index 06306ad197..4ca55e8744 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs new file mode 100644 index 0000000000..f4078676c9 --- /dev/null +++ b/osu.Game.Tests/Visual/Navigation/TestSceneFirstRunGame.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Framework.Platform; +using osu.Game.Configuration; +using osu.Game.Online.API; +using osu.Game.Overlays.Notifications; + +namespace osu.Game.Tests.Visual.Navigation +{ + [System.ComponentModel.Description("game with first-run setup overlay")] + public class TestSceneFirstRunGame : OsuGameTestScene + { + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddUntilStep("Wait for first-run setup", () => Game.FirstRunOverlay.State.Value == Visibility.Visible); + } + + [Test] + public void TestImportantNotificationDoesntInterruptSetup() + { + AddStep("post important notification", () => Game.Notifications.Post(new SimpleNotification { Text = "Important notification" })); + AddAssert("no notification posted", () => Game.Notifications.UnreadCount.Value == 0); + AddAssert("first-run setup still visible", () => Game.FirstRunOverlay.State.Value == Visibility.Visible); + + AddUntilStep("finish first-run setup", () => + { + Game.FirstRunOverlay.NextButton.TriggerClick(); + return Game.FirstRunOverlay.State.Value == Visibility.Hidden; + }); + AddWaitStep("wait for post delay", 5); + AddAssert("notifications shown", () => Game.Notifications.State.Value == Visibility.Visible); + AddAssert("notification posted", () => Game.Notifications.UnreadCount.Value == 1); + } + + protected override TestOsuGame CreateTestGame() => new FirstRunGame(LocalStorage, API); + + private class FirstRunGame : TestOsuGame + { + public FirstRunGame(Storage storage, IAPIProvider api, string[] args = null) + : base(storage, api, args) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + LocalConfig.SetValue(OsuSetting.ShowFirstRunSetup, true); + } + } + } +} diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs b/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs new file mode 100644 index 0000000000..1c2b1fe37d --- /dev/null +++ b/osu.Game.Tests/Visual/Navigation/TestSceneInterProcessCommunication.cs @@ -0,0 +1,86 @@ +// 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; +using osu.Framework; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics.Containers; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Game.IPC; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.Navigation +{ + [TestFixture] + [Ignore("This test cannot be run headless, as it requires the game host running the nested game to have IPC bound.")] + public class TestSceneInterProcessCommunication : OsuGameTestScene + { + private HeadlessGameHost ipcSenderHost = null!; + + private OsuSchemeLinkIPCChannel osuSchemeLinkIPCReceiver = null!; + private OsuSchemeLinkIPCChannel osuSchemeLinkIPCSender = null!; + + private const int requested_beatmap_set_id = 1; + + [Resolved] + private GameHost gameHost { get; set; } = null!; + + public override void SetUpSteps() + { + base.SetUpSteps(); + AddStep("set up request handling", () => + { + ((DummyAPIAccess)API).HandleRequest = request => + { + switch (request) + { + case GetBeatmapSetRequest gbr: + + var apiBeatmapSet = CreateAPIBeatmapSet(); + apiBeatmapSet.OnlineID = requested_beatmap_set_id; + apiBeatmapSet.Beatmaps = apiBeatmapSet.Beatmaps.Append(new APIBeatmap + { + DifficultyName = "Target difficulty", + OnlineID = 75, + }).ToArray(); + gbr.TriggerSuccess(apiBeatmapSet); + return true; + } + + return false; + }; + }); + AddStep("create IPC receiver channel", () => osuSchemeLinkIPCReceiver = new OsuSchemeLinkIPCChannel(gameHost, Game)); + AddStep("create IPC sender channel", () => + { + ipcSenderHost = new HeadlessGameHost(gameHost.Name, new HostOptions { BindIPC = true }); + osuSchemeLinkIPCSender = new OsuSchemeLinkIPCChannel(ipcSenderHost); + }); + } + + [Test] + public void TestOsuSchemeLinkIPCChannel() + { + AddStep("open beatmap via IPC", () => osuSchemeLinkIPCSender.HandleLinkAsync($@"osu://s/{requested_beatmap_set_id}").WaitSafely()); + AddUntilStep("beatmap overlay displayed", () => Game.ChildrenOfType().FirstOrDefault()?.State.Value == Visibility.Visible); + AddUntilStep("beatmap overlay showing content", () => Game.ChildrenOfType().FirstOrDefault()?.Header.BeatmapSet.Value.OnlineID == requested_beatmap_set_id); + } + + public override void TearDownSteps() + { + AddStep("dispose IPC receiver", () => osuSchemeLinkIPCReceiver.Dispose()); + AddStep("dispose IPC sender", () => + { + osuSchemeLinkIPCSender.Dispose(); + ipcSenderHost.Dispose(); + }); + base.TearDownSteps(); + } + } +} diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs b/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs index 2662b3930c..2592936ab6 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneMouseWheelVolumeAdjust.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Extensions; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs index e4871f611e..cf62c73ad4 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneOsuGame.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs index 2ce914ba3d..d1b1ce5c4b 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePerformFromScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs index 63226de750..6469962b08 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs index 6c32171b29..5e76fe1519 100644 --- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs +++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 51bb27f93e..a61352f954 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs index 68c44f49cc..2f0f2f68a5 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneSkinEditorNavigation.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Extensions; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Framework.Threading; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; @@ -14,6 +18,7 @@ using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD.HitErrorMeters; using osu.Game.Skinning.Editor; using osu.Game.Tests.Beatmaps.IO; +using osuTK; using osuTK.Input; using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation; @@ -24,29 +29,6 @@ namespace osu.Game.Tests.Visual.Navigation private TestPlaySongSelect songSelect; private SkinEditor skinEditor => Game.ChildrenOfType().FirstOrDefault(); - private void advanceToSongSelect() - { - PushAndConfirm(() => songSelect = new TestPlaySongSelect()); - AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded); - - AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely()); - - AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault); - } - - private void openSkinEditor() - { - AddStep("open skin editor", () => - { - InputManager.PressKey(Key.ControlLeft); - InputManager.PressKey(Key.ShiftLeft); - InputManager.Key(Key.S); - InputManager.ReleaseKey(Key.ControlLeft); - InputManager.ReleaseKey(Key.ShiftLeft); - }); - AddUntilStep("skin editor loaded", () => skinEditor != null); - } - [Test] public void TestEditComponentDuringGameplay() { @@ -86,6 +68,68 @@ namespace osu.Game.Tests.Visual.Navigation AddAssert("value is less than default", () => hitErrorMeter.JudgementLineThickness.Value < hitErrorMeter.JudgementLineThickness.Default); } + [Test] + public void TestComponentsDeselectedOnSkinEditorHide() + { + advanceToSongSelect(); + openSkinEditor(); + switchToGameplayScene(); + + AddUntilStep("wait for components", () => skinEditor.ChildrenOfType().Any()); + + AddStep("select all components", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.Key(Key.A); + InputManager.ReleaseKey(Key.ControlLeft); + }); + + AddUntilStep("components selected", () => skinEditor.SelectedComponents.Count > 0); + + toggleSkinEditor(); + + AddUntilStep("no components selected", () => skinEditor.SelectedComponents.Count == 0); + } + + [Test] + public void TestSwitchScreenWhileDraggingComponent() + { + Vector2 firstBlueprintCentre = Vector2.Zero; + ScheduledDelegate movementDelegate = null; + + advanceToSongSelect(); + + openSkinEditor(); + + AddStep("add skinnable component", () => + { + skinEditor.ChildrenOfType().First().TriggerClick(); + }); + + AddUntilStep("newly added component selected", () => skinEditor.SelectedComponents.Count == 1); + + AddStep("start drag", () => + { + firstBlueprintCentre = skinEditor.ChildrenOfType().First().ScreenSpaceDrawQuad.Centre; + + InputManager.MoveMouseTo(firstBlueprintCentre); + InputManager.PressButton(MouseButton.Left); + }); + + AddStep("start movement", () => movementDelegate = Scheduler.AddDelayed(() => { InputManager.MoveMouseTo(firstBlueprintCentre += new Vector2(1)); }, 10, true)); + + toggleSkinEditor(); + AddStep("exit song select", () => songSelect.Exit()); + + AddUntilStep("wait for blueprints removed", () => !skinEditor.ChildrenOfType().Any()); + + AddStep("stop drag", () => + { + InputManager.ReleaseButton(MouseButton.Left); + movementDelegate?.Cancel(); + }); + } + [Test] public void TestAutoplayCompatibleModsRetainedOnEnteringGameplay() { @@ -144,9 +188,40 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("mod overlay closed", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden); } + private void advanceToSongSelect() + { + PushAndConfirm(() => songSelect = new TestPlaySongSelect()); + AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded); + } + + private void openSkinEditor() + { + toggleSkinEditor(); + AddUntilStep("skin editor loaded", () => skinEditor != null); + } + + private void toggleSkinEditor() + { + AddStep("toggle skin editor", () => + { + InputManager.PressKey(Key.ControlLeft); + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.S); + InputManager.ReleaseKey(Key.ControlLeft); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + } + private void switchToGameplayScene() { - AddStep("Click gameplay scene button", () => skinEditor.ChildrenOfType().First(b => b.Text == "Gameplay").TriggerClick()); + AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely()); + AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault); + + AddStep("Click gameplay scene button", () => + { + InputManager.MoveMouseTo(skinEditor.ChildrenOfType().First(b => b.Text == "Gameplay")); + InputManager.Click(MouseButton.Left); + }); AddUntilStep("wait for player", () => { diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs index 961b7dedc3..bd3dcb8597 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs index 1aa56896d3..1072508e33 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs index bd723eeed6..cd53bf3af5 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupImport.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs index 85dd501fd3..1aadff7a20 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Development; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs index 7e3d8290be..f5c7ee2f19 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 8f0da8d182..b9d800e6fd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs index f94ae24a14..c78a36d2bd 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs index 8d8879490d..ba600332bb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapDownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs index 5999125013..8ef120d252 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs index c550c9afda..b73028be5b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 9d206af40e..416e8aebcc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -18,13 +20,10 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - [TestFixture] public class TestSceneBeatmapSetOverlay : OsuTestScene { private readonly TestBeatmapSetOverlay overlay; - protected override bool UseOnlineAPI => true; - private int nextBeatmapSetId = 1; public TestSceneBeatmapSetOverlay() @@ -41,12 +40,6 @@ namespace osu.Game.Tests.Visual.Online AddStep(@"show loading", () => overlay.ShowBeatmapSet(null)); } - [Test] - public void TestOnline() - { - AddStep(@"show online", () => overlay.FetchAndShowBeatmapSet(55)); - } - [Test] public void TestLocalBeatmaps() { @@ -107,6 +100,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("status is loved", () => overlay.ChildrenOfType().Single().Status == BeatmapOnlineStatus.Loved); AddAssert("scores container is visible", () => overlay.ChildrenOfType().Single().Alpha == 1); + AddAssert("mod selector is visible", () => overlay.ChildrenOfType().Single().Alpha == 1); AddStep("go to second beatmap", () => overlay.ChildrenOfType().ElementAt(1).TriggerClick()); diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index 629c413d85..31cebc2f0b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs index 82b34c50c2..26e1e49ca3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlaySuccessRate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs b/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs index 2af1c9a0f0..08c6914f83 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBundledBeatmapDownloader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps.Drawables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 8f000afb91..c5ac3dd442 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -106,6 +108,7 @@ namespace osu.Game.Tests.Visual.Online Version = "2018.712.0", DisplayVersion = "2018.712.0", UpdateStream = streams[OsuGameBase.CLIENT_STREAM_NAME], + CreatedAt = new DateTime(2018, 7, 12), ChangelogEntries = new List { new APIChangelogEntry @@ -169,6 +172,7 @@ namespace osu.Game.Tests.Visual.Online { Version = "2019.920.0", DisplayVersion = "2019.920.0", + CreatedAt = new DateTime(2019, 9, 20), UpdateStream = new APIUpdateStream { Name = "Test", diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs index 22220a7d9c..018d40d1bc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs index 39a4f1a8a1..8e17c490b1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs index e521db1c9d..214c05e64d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelListing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs index 444bd7e5fb..79dc17cfa6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index 4d227af2cb..a537f0660c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index e3792c0780..0b982a5745 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Collections.Generic; @@ -37,8 +39,8 @@ namespace osu.Game.Tests.Visual.Online private TestChatOverlay chatOverlay; private ChannelManager channelManager; - private APIUser testUser; - private Channel testPMChannel; + private readonly APIUser testUser = new APIUser { Username = "test user", Id = 5071479 }; + private Channel[] testChannels; private Channel testChannel1 => testChannels[0]; @@ -50,8 +52,6 @@ namespace osu.Game.Tests.Visual.Online [SetUp] public void SetUp() => Schedule(() => { - testUser = new APIUser { Username = "test user", Id = 5071479 }; - testPMChannel = new Channel(testUser); testChannels = Enumerable.Range(1, 10).Select(createPublicChannel).ToArray(); Child = new DependencyProvidingContainer @@ -78,6 +78,14 @@ namespace osu.Game.Tests.Visual.Online { switch (req) { + case CreateChannelRequest createRequest: + createRequest.TriggerSuccess(new APIChatChannel + { + ChannelID = ((int)createRequest.Channel.Id), + RecentMessages = new List() + }); + return true; + case GetUpdatesRequest getUpdates: getUpdates.TriggerFailure(new WebException()); return true; @@ -179,7 +187,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Show overlay", () => chatOverlay.Show()); AddAssert("Listing is visible", () => listingIsVisible); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); waitForChannel1Visible(); } @@ -201,12 +209,11 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestChannelCloseButton() { + var testPMChannel = new Channel(testUser); + AddStep("Show overlay", () => chatOverlay.Show()); - AddStep("Join PM and public channels", () => - { - channelManager.JoinChannel(testChannel1); - channelManager.JoinChannel(testPMChannel); - }); + joinTestChannel(0); + joinChannel(testPMChannel); AddStep("Select PM channel", () => clickDrawable(getChannelListItem(testPMChannel))); AddStep("Click close button", () => { @@ -227,7 +234,7 @@ namespace osu.Game.Tests.Visual.Online public void TestChatCommand() { AddStep("Show overlay", () => chatOverlay.Show()); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); AddStep("Open chat with user", () => channelManager.PostCommand($"chat {testUser.Username}")); AddAssert("PM channel is selected", () => @@ -246,14 +253,16 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestMultiplayerChannelIsNotShown() { - Channel multiplayerChannel = null; + Channel multiplayerChannel; AddStep("Show overlay", () => chatOverlay.Show()); - AddStep("Join multiplayer channel", () => channelManager.JoinChannel(multiplayerChannel = new Channel(new APIUser()) + + joinChannel(multiplayerChannel = new Channel(new APIUser()) { Name = "#mp_1", Type = ChannelType.Multiplayer, - })); + }); + AddAssert("Channel is joined", () => channelManager.JoinedChannels.Contains(multiplayerChannel)); AddUntilStep("Channel not present in listing", () => !chatOverlay.ChildrenOfType() .Where(item => item.IsPresent) @@ -267,7 +276,7 @@ namespace osu.Game.Tests.Visual.Online Message message = null; AddStep("Show overlay", () => chatOverlay.Show()); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); AddStep("Send message in channel 1", () => { @@ -289,8 +298,8 @@ namespace osu.Game.Tests.Visual.Online Message message = null; AddStep("Show overlay", () => chatOverlay.Show()); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); - AddStep("Join channel 2", () => channelManager.JoinChannel(testChannel2)); + joinTestChannel(0); + joinTestChannel(1); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); AddStep("Send message in channel 2", () => { @@ -312,8 +321,8 @@ namespace osu.Game.Tests.Visual.Online Message message = null; AddStep("Show overlay", () => chatOverlay.Show()); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); - AddStep("Join channel 2", () => channelManager.JoinChannel(testChannel2)); + joinTestChannel(0); + joinTestChannel(1); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); AddStep("Send message in channel 2", () => { @@ -335,7 +344,7 @@ namespace osu.Game.Tests.Visual.Online { Message message = null; - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Send message in channel 1", () => { testChannel1.AddNewMessages(message = new Message @@ -355,7 +364,7 @@ namespace osu.Game.Tests.Visual.Online { Message message = null; - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Send message in channel 1", () => { testChannel1.AddNewMessages(message = new Message @@ -376,7 +385,7 @@ namespace osu.Game.Tests.Visual.Online { AddStep("Show overlay", () => chatOverlay.Show()); AddAssert("TextBox is focused", () => InputManager.FocusedDrawable == chatOverlayTextBox); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); waitForChannel1Visible(); AddAssert("TextBox is focused", () => InputManager.FocusedDrawable == chatOverlayTextBox); @@ -402,11 +411,11 @@ namespace osu.Game.Tests.Visual.Online chatOverlay.Show(); chatOverlay.SlowLoading = true; }); - AddStep("Join channel 1", () => channelManager.JoinChannel(testChannel1)); + joinTestChannel(0); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); AddUntilStep("Channel 1 loading", () => !channelIsVisible && chatOverlay.GetSlowLoadingChannel(testChannel1).LoadState == LoadState.Loading); - AddStep("Join channel 2", () => channelManager.JoinChannel(testChannel2)); + joinTestChannel(1); AddStep("Select channel 2", () => clickDrawable(getChannelListItem(testChannel2))); AddUntilStep("Channel 2 loading", () => !channelIsVisible && chatOverlay.GetSlowLoadingChannel(testChannel2).LoadState == LoadState.Loading); @@ -459,19 +468,17 @@ namespace osu.Game.Tests.Visual.Online Channel pmChannel1 = createPrivateChannel(); Channel pmChannel2 = createPrivateChannel(); - AddStep("Show overlay with channels", () => - { - channelManager.JoinChannel(testChannel1); - channelManager.JoinChannel(testChannel2); - channelManager.JoinChannel(pmChannel1); - channelManager.JoinChannel(pmChannel2); - channelManager.JoinChannel(announceChannel); - chatOverlay.Show(); - }); + joinTestChannel(0); + joinTestChannel(1); + joinChannel(pmChannel1); + joinChannel(pmChannel2); + joinChannel(announceChannel); + + AddStep("Show overlay", () => chatOverlay.Show()); AddStep("Select channel 1", () => clickDrawable(getChannelListItem(testChannel1))); - waitForChannel1Visible(); + AddStep("Press document next keys", () => InputManager.Keys(PlatformAction.DocumentNext)); waitForChannel2Visible(); @@ -488,6 +495,18 @@ namespace osu.Game.Tests.Visual.Online waitForChannel1Visible(); } + private void joinTestChannel(int i) + { + AddStep($"Join test channel {i}", () => channelManager.JoinChannel(testChannels[i])); + AddUntilStep("wait for join completed", () => testChannels[i].Joined.Value); + } + + private void joinChannel(Channel channel) + { + AddStep($"Join channel {channel}", () => channelManager.JoinChannel(channel)); + AddUntilStep("wait for join completed", () => channel.Joined.Value); + } + private void waitForChannel1Visible() => AddUntilStep("Channel 1 is visible", () => channelIsVisible && currentDrawableChannel?.Channel == testChannel1); @@ -547,7 +566,7 @@ namespace osu.Game.Tests.Visual.Online private Channel createPrivateChannel() { - int id = RNG.Next(0, 10000); + int id = RNG.Next(0, DummyAPIAccess.DUMMY_USER_ID - 1); return new Channel(new APIUser { Id = id, @@ -557,12 +576,13 @@ namespace osu.Game.Tests.Visual.Online private Channel createAnnounceChannel() { - int id = RNG.Next(0, 10000); + const int announce_channel_id = 133337; + return new Channel { - Name = $"Announce {id}", + Name = $"Announce {announce_channel_id}", Type = ChannelType.Announce, - Id = id, + Id = announce_channel_id, }; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs b/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs index a241aa0517..5d28d553a0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs index 31e5a9b86c..a94b9e61c0 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs index 03eac5d85b..95b718041e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs index edee26c081..62f8f72929 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; diff --git a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs index 960d3fa248..074fea0604 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs index b26850feb2..cab0ffa3ba 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs index 31bb276cd4..fdcde0f2a5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics.UserInterface; using osuTK; diff --git a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs index 87458da578..3206640f9a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFavouriteButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs index 471d361c4e..5454c87dff 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; @@ -53,7 +55,7 @@ namespace osu.Game.Tests.Visual.Online Id = 3103765, IsOnline = true, Statistics = new UserStatistics { GlobalRank = 1111 }, - Country = new Country { FlagName = "JP" }, + CountryCode = CountryCode.JP, CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" }, new APIUser @@ -62,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online Id = 2, IsOnline = false, Statistics = new UserStatistics { GlobalRank = 2222 }, - Country = new Country { FlagName = "AU" }, + CountryCode = CountryCode.AU, CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", IsSupporter = true, SupportLevel = 3, @@ -71,7 +73,7 @@ namespace osu.Game.Tests.Visual.Online { Username = "Evast", Id = 8195163, - Country = new Country { FlagName = "BY" }, + CountryCode = CountryCode.BY, CoverUrl = "https://assets.ppy.sh/user-profile-covers/8195163/4a8e2ad5a02a2642b631438cfa6c6bd7e2f9db289be881cb27df18331f64144c.jpeg", IsOnline = false, LastVisit = DateTimeOffset.Now diff --git a/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs index dc468bb62d..b7e918207f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFullscreenOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tests/Visual/Online/TestSceneGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs index fa433571cf..2f3331b141 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index 2639a6506c..afc20dedff 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs index a1251ca793..181b086b00 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs index 8bf2ef34f2..7f0a00c474 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays.Profile.Sections.Kudosu; using System.Collections.Generic; using System; diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs index aa442ded02..10d9a5664e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardModSelector.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Online LeaderboardModSelector modSelector; FillFlowContainer selectedMods; - var ruleset = new Bindable(); + var ruleset = new Bindable(); Add(selectedMods = new FillFlowContainer { diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs index afa559280c..8c38027df3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays.BeatmapSet; using osu.Framework.Graphics; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs b/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs index c7ca3b4457..57514cdf37 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneMessageNotifier.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs index 17675bfbc0..8d73165d99 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Overlays.News; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs index 994c4fce53..cad045623b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Overlays.News; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs index f94c018b27..3e5dd91b2c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs index 382d76676a..266e98db15 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -217,7 +219,7 @@ namespace osu.Game.Tests.Visual.Online { base.LoadComplete(); - Metadata.BindValueChanged(metadata => + Metadata.BindValueChanged(_ => { foreach (var b in this.ChildrenOfType()) b.Action = () => YearChanged?.Invoke(b.Year); diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs index b689b85490..2df9089a8a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs index 0587e8884f..07ccfcec88 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOfflineCommentsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs index fe1701a554..388c0a9d60 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs new file mode 100644 index 0000000000..0d9c47db7b --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.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. + +#nullable disable + +using NUnit.Framework; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneOnlineBeatmapSetOverlay : OsuTestScene + { + private readonly BeatmapSetOverlay overlay; + + protected override bool UseOnlineAPI => true; + + public TestSceneOnlineBeatmapSetOverlay() + { + Add(overlay = new BeatmapSetOverlay()); + } + + [Test] + public void TestOnline() + { + AddStep(@"show online", () => overlay.FetchAndShowBeatmapSet(55)); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index ec183adbbc..b4bac5ee7e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs b/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs index a96fde6c20..118da682a7 100644 --- a/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs +++ b/osu.Game.Tests/Visual/Online/TestScenePlayHistorySubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays.Profile.Sections.Historical; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs index ae90872439..3068ba0185 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneProfileRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Rulesets.Catch; diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index 61574a7f23..1b1a5c7c6a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs index 458ba80712..6a39db4870 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Rankings; @@ -21,7 +23,7 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsCountryFilter() { - var countryBindable = new Bindable(); + var countryBindable = new Bindable(); AddRange(new Drawable[] { @@ -54,20 +56,12 @@ namespace osu.Game.Tests.Visual.Online } }); - var country = new Country - { - FlagName = "BY", - FullName = "Belarus" - }; - var unknownCountry = new Country - { - FlagName = "CK", - FullName = "Cook Islands" - }; + const CountryCode country = CountryCode.BY; + const CountryCode unknown_country = CountryCode.CK; AddStep("Set country", () => countryBindable.Value = country); - AddStep("Set null country", () => countryBindable.Value = null); - AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry); + AddStep("Set default country", () => countryBindable.Value = default); + AddStep("Set country with no flag", () => countryBindable.Value = unknown_country); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index 677952681c..c776cfe377 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Overlays; @@ -17,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsHeader() { - var countryBindable = new Bindable(); + var countryBindable = new Bindable(); var ruleset = new Bindable(); var scope = new Bindable(); @@ -28,21 +30,12 @@ namespace osu.Game.Tests.Visual.Online Ruleset = { BindTarget = ruleset } }); - var country = new Country - { - FlagName = "BY", - FullName = "Belarus" - }; - - var unknownCountry = new Country - { - FlagName = "CK", - FullName = "Cook Islands" - }; + const CountryCode country = CountryCode.BY; + const CountryCode unknown_country = CountryCode.CK; AddStep("Set country", () => countryBindable.Value = country); AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); - AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry); + AddStep("Set country with no flag", () => countryBindable.Value = unknown_country); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 027f17fff4..5476049882 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; @@ -19,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online private TestRankingsOverlay rankingsOverlay; - private readonly Bindable countryBindable = new Bindable(); + private readonly Bindable countryBindable = new Bindable(); private readonly Bindable scope = new Bindable(); [SetUp] @@ -46,15 +48,15 @@ namespace osu.Game.Tests.Visual.Online public void TestFlagScopeDependency() { AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); - AddAssert("Check country is Null", () => countryBindable.Value == null); - AddStep("Set country", () => countryBindable.Value = us_country); + AddAssert("Check country is default", () => countryBindable.IsDefault); + AddStep("Set country", () => countryBindable.Value = CountryCode.US); AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); } [Test] public void TestShowCountry() { - AddStep("Show US", () => rankingsOverlay.ShowCountry(us_country)); + AddStep("Show US", () => rankingsOverlay.ShowCountry(CountryCode.US)); } private void loadRankingsOverlay() @@ -67,15 +69,9 @@ namespace osu.Game.Tests.Visual.Online }; } - private static readonly Country us_country = new Country - { - FlagName = "US", - FullName = "United States" - }; - private class TestRankingsOverlay : RankingsOverlay { - public new Bindable Country => base.Country; + public new Bindable Country => base.Country; } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs index d60222fa0b..5aafcf3f6b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs index 35e219f839..81b76d19ac 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsTables.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Rankings.Tables; @@ -55,8 +57,7 @@ namespace osu.Game.Tests.Visual.Online { new CountryStatistics { - Country = new Country { FlagName = "US", FullName = "United States" }, - FlagName = "US", + Code = CountryCode.US, ActiveUsers = 2_972_623, PlayCount = 3_086_515_743, RankedScore = 449_407_643_332_546, @@ -64,8 +65,7 @@ namespace osu.Game.Tests.Visual.Online }, new CountryStatistics { - Country = new Country { FlagName = "RU", FullName = "Russian Federation" }, - FlagName = "RU", + Code = CountryCode.RU, ActiveUsers = 1_609_989, PlayCount = 1_637_052_841, RankedScore = 221_660_827_473_004, @@ -84,7 +84,7 @@ namespace osu.Game.Tests.Visual.Online User = new APIUser { Username = "first active user", - Country = new Country { FlagName = "JP" }, + CountryCode = CountryCode.JP, Active = true, }, Accuracy = 0.9972, @@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Online User = new APIUser { Username = "inactive user", - Country = new Country { FlagName = "AU" }, + CountryCode = CountryCode.AU, Active = false, }, Accuracy = 0.9831, @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.Online User = new APIUser { Username = "second active user", - Country = new Country { FlagName = "PL" }, + CountryCode = CountryCode.PL, Active = true, }, Accuracy = 0.9584, diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs b/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs index 7e33b5240c..8f03f240f7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoreboardTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 8a304110dd..864b2b6878 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -16,6 +18,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; using osuTK.Graphics; @@ -144,21 +147,17 @@ namespace osu.Game.Tests.Visual.Online { var scores = new APIScoresCollection { - Scores = new List + Scores = new List { - new APIScore + new SoloScoreInfo { - Date = DateTimeOffset.Now, - OnlineID = onlineID++, + EndedAt = DateTimeOffset.Now, + ID = onlineID++, User = new APIUser { Id = 6602580, Username = @"waaiiru", - Country = new Country - { - FullName = @"Spain", - FlagName = @"ES", - }, + CountryCode = CountryCode.ES, }, Mods = new[] { @@ -173,19 +172,15 @@ namespace osu.Game.Tests.Visual.Online TotalScore = 1234567890, Accuracy = 1, }, - new APIScore + new SoloScoreInfo { - Date = DateTimeOffset.Now, - OnlineID = onlineID++, + EndedAt = DateTimeOffset.Now, + ID = onlineID++, User = new APIUser { Id = 4608074, Username = @"Skycries", - Country = new Country - { - FullName = @"Brazil", - FlagName = @"BR", - }, + CountryCode = CountryCode.BR, }, Mods = new[] { @@ -199,19 +194,15 @@ namespace osu.Game.Tests.Visual.Online TotalScore = 1234789, Accuracy = 0.9997, }, - new APIScore + new SoloScoreInfo { - Date = DateTimeOffset.Now, - OnlineID = onlineID++, + EndedAt = DateTimeOffset.Now, + ID = onlineID++, User = new APIUser { Id = 1014222, Username = @"eLy", - Country = new Country - { - FullName = @"Japan", - FlagName = @"JP", - }, + CountryCode = CountryCode.JP, }, Mods = new[] { @@ -224,19 +215,15 @@ namespace osu.Game.Tests.Visual.Online TotalScore = 12345678, Accuracy = 0.9854, }, - new APIScore + new SoloScoreInfo { - Date = DateTimeOffset.Now, - OnlineID = onlineID++, + EndedAt = DateTimeOffset.Now, + ID = onlineID++, User = new APIUser { Id = 1541390, Username = @"Toukai", - Country = new Country - { - FullName = @"Canada", - FlagName = @"CA", - }, + CountryCode = CountryCode.CA, }, Mods = new[] { @@ -248,19 +235,15 @@ namespace osu.Game.Tests.Visual.Online TotalScore = 1234567, Accuracy = 0.8765, }, - new APIScore + new SoloScoreInfo { - Date = DateTimeOffset.Now, - OnlineID = onlineID++, + EndedAt = DateTimeOffset.Now, + ID = onlineID++, User = new APIUser { Id = 7151382, Username = @"Mayuri Hana", - Country = new Country - { - FullName = @"Thailand", - FlagName = @"TH", - }, + CountryCode = CountryCode.TH, }, Rank = ScoreRank.D, PP = 160, @@ -271,15 +254,26 @@ namespace osu.Game.Tests.Visual.Online } }; + const int initial_great_count = 2000; + const int initial_tick_count = 100; + + int greatCount = initial_great_count; + int tickCount = initial_tick_count; + foreach (var s in scores.Scores) { - s.Statistics = new Dictionary + s.Statistics = new Dictionary { - { "count_300", RNG.Next(2000) }, - { "count_100", RNG.Next(2000) }, - { "count_50", RNG.Next(2000) }, - { "count_miss", RNG.Next(2000) } + { HitResult.Great, greatCount }, + { HitResult.LargeTickHit, tickCount }, + { HitResult.Ok, RNG.Next(100) }, + { HitResult.Meh, RNG.Next(100) }, + { HitResult.Miss, initial_great_count - greatCount }, + { HitResult.LargeTickMiss, initial_tick_count - tickCount }, }; + + greatCount -= 100; + tickCount -= RNG.Next(1, 5); } return scores; @@ -287,19 +281,15 @@ namespace osu.Game.Tests.Visual.Online private APIScoreWithPosition createUserBest() => new APIScoreWithPosition { - Score = new APIScore + Score = new SoloScoreInfo { - Date = DateTimeOffset.Now, - OnlineID = onlineID++, + EndedAt = DateTimeOffset.Now, + ID = onlineID++, User = new APIUser { Id = 7151382, Username = @"Mayuri Hana", - Country = new Country - { - FullName = @"Thailand", - FlagName = @"TH", - }, + CountryCode = CountryCode.TH, }, Rank = ScoreRank.D, PP = 160, diff --git a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs index d7fa5a1f6d..32262c18a8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs b/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs index 266dcb013b..d7feade128 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs index 8d5eebd31f..292facab11 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneStandAloneChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Online.Chat; diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs index f168ae5035..d4355d2f11 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Overlays.Comments; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs index 3f4a5cd420..42a8462604 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserHistoryGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 6c3678b0d2..2a70fd7df3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; @@ -58,7 +60,7 @@ namespace osu.Game.Tests.Visual.Online { Username = @"flyte", Id = 3103765, - Country = new Country { FlagName = @"JP" }, + CountryCode = CountryCode.JP, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", Status = { Value = new UserStatusOnline() } }) { Width = 300 }, @@ -66,7 +68,7 @@ namespace osu.Game.Tests.Visual.Online { Username = @"peppy", Id = 2, - Country = new Country { FlagName = @"AU" }, + CountryCode = CountryCode.AU, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", IsSupporter = true, SupportLevel = 3, @@ -75,7 +77,7 @@ namespace osu.Game.Tests.Visual.Online { Username = @"Evast", Id = 8195163, - Country = new Country { FlagName = @"BY" }, + CountryCode = CountryCode.BY, CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8195163/4a8e2ad5a02a2642b631438cfa6c6bd7e2f9db289be881cb27df18331f64144c.jpeg", IsOnline = false, LastVisit = DateTimeOffset.Now diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index dda9543159..1abe06ed76 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 78e2ceb45b..caa2d2571d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -22,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online { Username = @"Somebody", Id = 1, - Country = new Country { FullName = @"Alien" }, + CountryCode = CountryCode.Unknown, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", JoinDate = DateTimeOffset.Now.AddDays(-1), LastVisit = DateTimeOffset.Now, @@ -80,7 +82,7 @@ namespace osu.Game.Tests.Visual.Online Username = @"peppy", Id = 2, IsSupporter = true, - Country = new Country { FullName = @"Australia", FlagName = @"AU" }, + CountryCode = CountryCode.AU, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg" })); @@ -88,7 +90,7 @@ namespace osu.Game.Tests.Visual.Online { Username = @"flyte", Id = 3103765, - Country = new Country { FullName = @"Japan", FlagName = @"JP" }, + CountryCode = CountryCode.JP, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" })); @@ -97,7 +99,7 @@ namespace osu.Game.Tests.Visual.Online Username = @"BanchoBot", Id = 3, IsBot = true, - Country = new Country { FullName = @"Saint Helena", FlagName = @"SH" }, + CountryCode = CountryCode.SH, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg" })); diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs index 30774689a2..4260fff02d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfilePreviousUsernames.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs index 0973076c40..163f0e62df 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileRecentSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs index 7dfdca8276..0eb6ec3c04 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -19,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online { public TestSceneUserProfileScores() { - var firstScore = new APIScore + var firstScore = new SoloScoreInfo { PP = 1047.21, Rank = ScoreRank.SH, @@ -32,7 +34,7 @@ namespace osu.Game.Tests.Visual.Online }, DifficultyName = "Extreme" }, - Date = DateTimeOffset.Now, + EndedAt = DateTimeOffset.Now, Mods = new[] { new APIMod { Acronym = new OsuModHidden().Acronym }, @@ -42,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online Accuracy = 0.9813 }; - var secondScore = new APIScore + var secondScore = new SoloScoreInfo { PP = 134.32, Rank = ScoreRank.A, @@ -55,7 +57,7 @@ namespace osu.Game.Tests.Visual.Online }, DifficultyName = "[4K] Regret" }, - Date = DateTimeOffset.Now, + EndedAt = DateTimeOffset.Now, Mods = new[] { new APIMod { Acronym = new OsuModHardRock().Acronym }, @@ -64,7 +66,7 @@ namespace osu.Game.Tests.Visual.Online Accuracy = 0.998546 }; - var thirdScore = new APIScore + var thirdScore = new SoloScoreInfo { PP = 96.83, Rank = ScoreRank.S, @@ -77,11 +79,11 @@ namespace osu.Game.Tests.Visual.Online }, DifficultyName = "Insane" }, - Date = DateTimeOffset.Now, + EndedAt = DateTimeOffset.Now, Accuracy = 0.9726 }; - var noPPScore = new APIScore + var noPPScore = new SoloScoreInfo { Rank = ScoreRank.B, Beatmap = new APIBeatmap @@ -93,7 +95,7 @@ namespace osu.Game.Tests.Visual.Online }, DifficultyName = "[4K] Cataclysmic Hypernova" }, - Date = DateTimeOffset.Now, + EndedAt = DateTimeOffset.Now, Accuracy = 0.55879 }; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index b9272e7294..d517aaa105 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs index e7b6a94642..32d427ba6d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs index a9fed7b302..fdc15af73d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneVotePill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Overlays.Comments; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs index 27e989df76..99e301f3ba 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs index 3a2bafb128..03b94aded7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index af2e4fc91a..39432ee059 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using Markdig.Syntax.Inlines; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs index 3506d459ce..558bff2f3c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System; using System.Net; using NUnit.Framework; using osu.Game.Online.API; @@ -23,24 +26,40 @@ namespace osu.Game.Tests.Visual.Online public void TestMainPage() { setUpWikiResponse(responseMainPage); - AddStep("Show Main Page", () => wiki.Show()); + AddStep("Show main page", () => wiki.Show()); } [Test] public void TestArticlePage() { setUpWikiResponse(responseArticlePage); - AddStep("Show Article Page", () => wiki.ShowPage("Article_styling_criteria/Formatting")); + AddStep("Show article page", () => wiki.ShowPage("Article_styling_criteria/Formatting")); + } + + [Test] + public void TestRedirection() + { + const string redirection_path = "Redirection_path_for_article"; + + setUpWikiResponse(responseArticlePage, redirection_path); + AddStep("Show article page", () => wiki.ShowPage(redirection_path)); + + AddUntilStep("Current page is article", () => wiki.Header.Current.Value == "Formatting"); + + setUpWikiResponse(responseArticleParentPage); + AddStep("Show parent page", () => wiki.Header.ShowParentPage?.Invoke()); + + AddUntilStep("Current page is parent", () => wiki.Header.Current.Value == "Article styling criteria"); } [Test] public void TestErrorPage() { - setUpWikiResponse(null, true); + setUpWikiResponse(responseArticlePage); AddStep("Show Error Page", () => wiki.ShowPage("Error")); } - private void setUpWikiResponse(APIWikiPage r, bool isFailed = false) + private void setUpWikiResponse(APIWikiPage r, string redirectionPath = null) => AddStep("set up response", () => { dummyAPI.HandleRequest = request => @@ -48,10 +67,13 @@ namespace osu.Game.Tests.Visual.Online if (!(request is GetWikiRequest getWikiRequest)) return false; - if (isFailed) - getWikiRequest.TriggerFailure(new WebException()); - else + if (getWikiRequest.Path.Equals(r.Path, StringComparison.OrdinalIgnoreCase) || + getWikiRequest.Path.Equals(redirectionPath, StringComparison.OrdinalIgnoreCase)) + { getWikiRequest.TriggerSuccess(r); + } + else + getWikiRequest.TriggerFailure(new WebException()); return true; }; @@ -80,5 +102,17 @@ namespace osu.Game.Tests.Visual.Online Markdown = "# Formatting\n\n*For the writing standards, see: [Article style criteria/Writing](../Writing)*\n\n*Notice: This article uses [RFC 2119](https://tools.ietf.org/html/rfc2119 \"IETF Tools\") to describe requirement levels.*\n\n## Locales\n\nListed below are the properly-supported locales for the wiki:\n\n| File Name | Locale Name | Native Script |\n| :-- | :-- | :-- |\n| `en.md` | English | English |\n| `ar.md` | Arabic | اَلْعَرَبِيَّةُ |\n| `be.md` | Belarusian | Беларуская мова |\n| `bg.md` | Bulgarian | Български |\n| `cs.md` | Czech | Česky |\n| `da.md` | Danish | Dansk |\n| `de.md` | German | Deutsch |\n| `gr.md` | Greek | Ελληνικά |\n| `es.md` | Spanish | Español |\n| `fi.md` | Finnish | Suomi |\n| `fr.md` | French | Français |\n| `hu.md` | Hungarian | Magyar |\n| `id.md` | Indonesian | Bahasa Indonesia |\n| `it.md` | Italian | Italiano |\n| `ja.md` | Japanese | 日本語 |\n| `ko.md` | Korean | 한국어 |\n| `nl.md` | Dutch | Nederlands |\n| `no.md` | Norwegian | Norsk |\n| `pl.md` | Polish | Polski |\n| `pt.md` | Portuguese | Português |\n| `pt-br.md` | Brazilian Portuguese | Português (Brasil) |\n| `ro.md` | Romanian | Română |\n| `ru.md` | Russian | Русский |\n| `sk.md` | Slovak | Slovenčina |\n| `sv.md` | Swedish | Svenska |\n| `th.md` | Thai | ไทย |\n| `tr.md` | Turkish | Türkçe |\n| `uk.md` | Ukrainian | Українська мова |\n| `vi.md` | Vietnamese | Tiếng Việt |\n| `zh.md` | Chinese (Simplified) | 简体中文 |\n| `zh-tw.md` | Traditional Chinese (Taiwan) | 繁體中文(台灣) |\n\n*Note: The website will give readers their selected language's version of an article. If it is not available, the English version will be given.*\n\n### Content parity\n\nTranslations are subject to strict content parity with their English article, in the sense that they must have the same message, regardless of grammar and syntax. Any changes to the translations' meanings must be accompanied by equivalent changes to the English article.\n\nThere are some cases where the content is allowed to differ:\n\n- Articles originally written in a language other than English (in this case, English should act as the translation)\n- Explanations of English words that are common terms in the osu! community\n- External links\n- Tags\n- Subcommunity-specific explanations\n\n## Front matter\n\nFront matter must be placed at the very top of the file. It is written in [YAML](https://en.wikipedia.org/wiki/YAML#Example \"YAML Wikipedia article\") and describes additional information about the article. This must be surrounded by three hyphens (`---`) on the lines above and below it, and an empty line must follow it before the title heading.\n\n### Articles that need help\n\n*Note: Avoid translating English articles with this tag. In addition to this, this tag should be added when the translation needs its own clean up.*\n\nThe `needs_cleanup` tag may be added to articles that need rewriting or formatting help. It is also acceptable to open an issue on GitHub for this purpose. This tag must be written as shown below:\n\n```yaml\nneeds_cleanup: true\n```\n\nWhen adding this tag to an article, [comments](#comments) should also be added to explain what needs to be done to remove the tag.\n\n### Outdated articles\n\n*Note: Avoid translating English articles with this tag. If the English article has this tag, the translation must also have this tag.*\n\nTranslated articles that are outdated must use the `outdated` tag when the English variant is updated. English articles may also become outdated when the content they contain is misleading or no longer relevant. This tag must be written as shown below:\n\n```yaml\noutdated: true\n```\n\nWhen adding this tag to an article, [comments](#comments) should also be added to explain what needs to be updated to remove the tag.\n\n### Tagging articles\n\nTags help the website's search engine query articles better. Tags should be written in the same language as the article and include the original list of tags. Tags should use lowercase letters where applicable.\n\nFor example, an article called \"Beatmap discussion\" may include the following tags:\n\n```yaml\ntags:\n - beatmap discussions\n - modding V2\n - MV2\n```\n\n### Translations without reviews\n\n*Note: Wiki maintainers will determine and apply this mark prior to merging.*\n\nSometimes, translations are added to the wiki without review from other native speakers of the language. In this case, the `no_native_review` mark is added to let future translators know that it may need to be checked again. This tag must be written as shown below:\n\n```yaml\nno_native_review: true\n```\n\n## Article naming\n\n*See also: [Folder names](#folder-names) and [Titles](#titles)*\n\nArticle titles should be singular and use sentence case. See [Wikipedia's naming conventions article](https://en.wikipedia.org/wiki/Wikipedia:Naming_conventions_(plurals) \"Wikipedia\") for more details.\n\nArticle titles should match the folder name it is in (spaces may replace underscores (`_`) where appropriate). If the folder name changes, the article title should be changed to match it and vice versa.\n\n---\n\nContest and tournament articles are an exception. The folder name must use abbreviations, acronyms, or initialisms. The article's title must be the full name of the contest or tournament.\n\n## Folder and file structure\n\n### Folder names\n\n*See also: [Article naming](#article-naming)*\n\nFolder names must be in English and use sentence case.\n\nFolder names must only use these characters:\n\n- uppercase and lowercase letters\n- numbers\n- underscores (`_`)\n- hyphens (`-`)\n- exclamation marks (`!`)\n\n### Article file names\n\nThe file name of an article can be found in the `File Name` column of the [locales section](#locales). The location of a translated article must be placed in the same folder as the English article.\n\n### Index articles\n\nAn index article must be created if the folder is intended to only hold other articles. Index articles must contain a list of articles that are inside its own folder. They may also contain other information, such as a lead paragraph or descriptions of the linked articles.\n\n### Disambiguation articles\n\n[Disambiguation](/wiki/Disambiguation) articles must be placed in the `/wiki/Disambiguation` folder. The main page must be updated to include the disambiguation article. Refer to [Disambiguation/Mod](/wiki/Disambiguation/Mod) as an example.\n\nRedirects must be updated to have the ambiguous keyword(s) redirect to the disambiguation article.\n\nArticles linked from a disambiguation article must have a [For other uses](#for-other-uses) hatnote.\n\n## HTML\n\nHTML must not be used, with exception for [comments](#comments). The structure of the article must be redone if HTML is used.\n\n### Comments\n\nHTML comments should be used for marking to-dos, but may also be used to annotate text. They should be on their own line, but can be placed inline in a paragraph. If placed inline, the start of the comment must not have a space.\n\nBad example:\n\n```markdown\nHTML comments should be used for marking to-dos or annotate text.\n```\n\nGood example:\n\n```markdown\nHTML comments should be used for marking to-dos or annotate text.\n```\n\n## Editing\n\n### End of line sequence\n\n*Caution: Uploading Markdown files using `CRLF` (carriage return and line feed) via GitHub will result in those files using `CRLF`. To prevent this, set the line ending to `LF` (line feed) before uploading.*\n\nMarkdown files must be checked in using the `LF` end of line sequence.\n\n### Escaping\n\nMarkdown syntax should be escaped as needed. However, article titles are parsed as plain text and so must not be escaped.\n\n### Paragraphs\n\nEach paragraph must be followed by one empty line.\n\n### Line breaks\n\nLine breaks must use a backslash (`\\`).\n\nLine breaks must be used sparingly.\n\n## Hatnote\n\n*Not to be confused with [Notice](#notice).*\n\nHatnotes are short notes placed at the top of an article or section to help readers navigate to related articles or inform them about related topics.\n\nHatnotes must be italicised and be placed immediately after the heading. If multiple hatnotes are used, they must be on the same paragraph separated with a line break.\n\n### Main page\n\n*Main page* hatnotes direct the reader to the main article of a topic. When this hatnote is used, it implies that the section it is on is a summary of what the linked page is about. This hatnote should have only one link. These must be formatted as follows:\n\n```markdown\n*Main page: {article}*\n\n*Main pages: {article} and {article}*\n```\n\n### See also\n\n*See also* hatnotes suggest to readers other points of interest from a given article or section. These must be formatted as follows:\n\n```markdown\n*See also: {article}*\n\n*See also: {article} and {article}*\n```\n\n### For see\n\n*For see* hatnotes are similar to *see also* hatnotes, but are generally more descriptive and direct. This hatnote may use more than one link if necessary. These must be formatted as follows:\n\n```markdown\n*For {description}, see: {article}`*\n\n*For {description}, see: {article} and {article}`*\n```\n\n### Not to be confused with\n\n*Not to be confused with* hatnotes help distinguish ambiguous or misunderstood article titles or sections. This hatnote may use more than one link if necessary. These must be formatted as follows:\n\n```markdown\n*Not to be confused with {article}.*\n\n*Not to be confused with {article} or {article}.*\n```\n\n### For other uses\n\n*For other uses* hatnotes are similar to *not to be confused with* hatnotes, but links directly to the [disambiguation article](#disambiguation-articles). This hatnote must only link to the disambiguation article. These must be formatted as follows:\n\n```markdown\n*For other uses, see {disambiguation article}.*\n```\n\n## Notice\n\n*Not to be confused with [Hatnote](#hatnote).*\n\nA notice should be placed where appropriate in a section, but must start off the paragraph and use italics. Notices may contain bolding where appropriate, but should be kept to a minimum. Notices must be written as complete sentences. Thus, unlike most [hatnotes](#hatnotes), must use a full stop (`.`) or an exclamation mark (`!`) if appropriate. Anything within the same paragraph of a notice must also be italicised. These must be formatted as follows:\n\n```markdown\n*Note: {note}.*\n\n*Notice: {notice}.*\n\n*Caution: {caution}.*\n\n*Warning: {warning}.*\n```\n\n- `Note` should be used for factual or trivial details.\n- `Notice` should be used for reminders or to draw attention to something that the reader should be made aware of.\n- `Caution` should be used to warn the reader to avoid unintended consequences.\n- `Warning` should be used to warn the reader that action may be taken against them.\n\n## Emphasising\n\n### Bold\n\nBold must use double asterisks (`**`).\n\nLead paragraphs may bold the first occurrence of the article's title.\n\n### Italics\n\nItalics must use single asterisks (`*`).\n\nNames of work or video games should be italicised. osu!—the game—is exempt from this.\n\nThe first occurrence of an abbreviation, acronym, or initialism may be italicised.\n\nItalics may also be used to provide emphasis or help with readability.\n\n## Headings\n\nAll headings must use sentence case.\n\nHeadings must use the [ATX (hash) style](https://github.github.com/gfm/#atx-headings \"GitHub\") and must have an empty line before and after the heading. The title heading is an exception when it is on the first line. If this is the case, there only needs to be an empty line after the title heading.\n\nHeadings must not exceed a heading level of 5 and must not be used to style or format text.\n\n### Titles\n\n*See also: [Article naming](#article-naming)*\n\n*Caution: Titles are parsed as plain text; they must not be escaped.*\n\nThe first heading in all articles must be a level 1 heading, being the article's title. All headings afterwards must be [section headings](#sections). Titles must not contain formatting, links, or images.\n\nThe title heading must be on the first line, unless [front matter](#front-matter) is being used. If that is the case, the title heading must go after it and have an empty line before the title heading.\n\n### Sections\n\nSection headings must use levels 2 to 5. The section heading proceeding the [title heading](#titles) must be a level 2 heading. Unlike titles, section headings may have small image icons.\n\nSection headings must not skip a heading level (i.e. do not go from a level 2 heading to a level 4 heading) and must not contain formatting or links.\n\n*Notice: On the website, heading levels 4 and 5 will not appear in the table of contents. They cannot be linked to directly either.*\n\n## Lists\n\nLists should not go over 4 levels of indentation and should not have an empty line in between each item.\n\nFor nested lists, bullets or numbers must align with the item content of their parent lists.\n\nThe following example was done incorrectly (take note of the spacing before the bullet):\n\n```markdown\n1. Fly a kite\n - Don't fly a kite if it's raining\n```\n\nThe following example was done correctly:\n\n```markdown\n1. Fly a kite\n - Don't fly a kite if it's raining\n```\n\n### Bulleted\n\nBulleted lists must use a hyphen (`-`). These must then be followed by one space. (Example shown below.)\n\n```markdown\n- osu!\n - Hit circle\n - Combo number\n - Approach circle\n - Slider\n - Hit circles\n - Slider body\n - Slider ticks\n - Spinner\n- osu!taiko\n```\n\n### Numbered\n\nThe numbers in a numbered list must be incremented to represent their step.\n\n```markdown\n1. Download the osu! installer.\n2. Run the installer.\n 1. To change the installation location, click the text underneath the progression bar.\n 2. The installer will prompt for a new location, choose the installation folder.\n3. osu! will start up once installation is complete.\n4. Sign in.\n```\n\n### Mixed\n\nCombining both bulleted and numbered lists should be done sparingly.\n\n```markdown\n1. Download a skin from the forums.\n2. Load the skin file into osu!.\n - If the file is a `.zip`, unzip it and move the contents into the `Skins/` folder (found in your osu! installation folder).\n - If the file is a `.osk`, open it on your desktop or drag-and-drop it into the game client.\n3. Open osu!, if it is not opened, and select the skin in the options.\n - This may have been completed if you opened the `.osk` file or drag-and-dropped it into the game client.\n```\n\n## Code\n\nThe markup for code is a grave mark (`` ` ``). To put grave marks in code, use double grave marks instead. If the grave mark is at the start or end, pad it with one space. (Example shown below.)\n\n```markdown\n`` ` ``\n`` `Space` ``\n```\n\n### Keyboard keys\n\n*Notice: When denoting the letter itself, and not the keyboard key, use quotation marks instead.*\n\nWhen representing keyboard keys, use capital letters for single characters and title case for modifiers. Use the plus symbol (`+`) (without code) to represent key combinations. (Example shown below.)\n\n```markdown\npippi is spelt with a lowercase \"p\" like peppy.\n\nPress `Ctrl` + `O` to open the open dialog.\n```\n\nWhen representing a space or the spacebar, use `` `Space` ``.\n\n### Button and menu text\n\nWhen copying the text from a menu or button, the letter casing should be copied as it appears. (Example shown below.)\n\n```markdown\nThe `osu!direct` button is visible in the main menu on the right side, if you have an active osu!supporter tag.\n```\n\n### Folder and directory names\n\nWhen copying the name of a folder or directory, the letter casing should be copied as it appears, but prefer lowercased paths when possible. Directory paths must not be absolute (i.e. do not start the directory name from the drive letter or from the root folder). (Example shown below.)\n\n```markdown\nosu! is installed in the `AppData/Local` folder by default, unless specified otherwise during installation.\n```\n\n### Keywords and commands\n\nWhen copying a keyword or command, the letter casing should be copied as it appears or how someone normally would type it. If applicable, prefer lowercase letters. (Example shown below.)\n\n```markdown\nAs of now, the `Name` and `Author` commands in the skin configuration file (`skin.ini`) do nothing.\n```\n\n### File names\n\nWhen copying the name of a file, the letter casing should be copied as it appears. If applicable, prefer lowercase letters. (Example shown below.)\n\n```markdown\nTo play osu!, double click the `osu!.exe` icon.\n```\n\n### File extensions\n\n*Notice: File formats (not to be confused with file extensions) must be written in capital letters without the prefixed fullstop (`.`).*\n\nFile extensions must be prefixed with a fullstop (`.`) and be followed by the file extension in lowercase letters. (Example shown below.)\n\n```markdown\nThe JPG (or JPEG) file format has the `.jpg` (or `.jpeg`) extension.\n```\n\n### Chat channels\n\nWhen copying the name of a chat channel, start it with a hash (`#`), followed by the channel name in lowercase letters. (Example shown below.)\n\n```markdown\n`#lobby` is where you can advertise your multi room.\n```\n\n## Preformatted text (code blocks)\n\n*Notice: Syntax highlighting for preformatted text is not implemented on the website yet.*\n\nPreformatted text (also known as code blocks) must be fenced using three grave marks. They should set the language identifier for syntax highlighting.\n\n## Links\n\nThere are two types of links: inline and reference. Inline has two styles.\n\nThe following is an example of both inline styles:\n\n```markdown\n[Game Modifiers](/wiki/Game_Modifiers)\n\n\n```\n\nThe following is an example of the reference style:\n\n```markdown\n[Game Modifiers][game mods link]\n\n[game mods link]: /wiki/Game_Modifiers\n```\n\n---\n\nLinks must use the inline style if they are only referenced once. The inline angle brackets style should be avoided. References to reference links must be placed at the bottom of the article.\n\n### Internal links\n\n*Note: Internal links refer to links that stay inside the `https://osu.ppy.sh/` domain.*\n\n#### Wiki links\n\nAll links that point to an wiki article should start with `/wiki/` followed by the path to get to the article you are targeting. Relative links may also be used. Some examples include the following:\n\n```markdown\n[FAQ](/wiki/FAQ)\n[pippi](/wiki/Mascots#-pippi)\n[Beatmaps](../)\n[Pattern](./Pattern)\n```\n\nWiki links must not use redirects and must not have a trailing forward slash (`/`).\n\nBad examples include the following:\n\n```markdown\n[Article styling criteria](/wiki/ASC)\n[Developers](/wiki/Developers/)\n[Developers](/wiki/Developers/#game-client-developers)\n```\n\nGood examples include the following:\n\n```markdown\n[Article styling criteria](/wiki/Article_styling_criteria)\n[Developers](/wiki/Developers)\n[Developers](/wiki/Developers#game-client-developers)\n```\n\n##### Sub-article links\n\nWiki links that point to a sub-article should include the parent article's folder name in its link text. See the following example:\n\n```markdown\n*See also: [Beatmap Editor/Design](/wiki/Beatmap_Editor/Design)*\n```\n\n##### Section links\n\n*Notice: On the website, heading levels 4 and 5 are not given the id attribute. This means that they can not be linked to directly.*\n\nWiki links that point to a section of an article may use the section sign symbol (`§`). See the following example:\n\n```markdown\n*For timing rules, see: [Ranking Criteria § Timing](/wiki/Ranking_Criteria#timing)*\n```\n\n#### Other osu! links\n\nThe URL from the address bar of your web browser should be copied as it is when linking to other osu! web pages. The `https://osu.ppy.sh` part of the URL must be kept.\n\n##### User profiles\n\nAll usernames must be linked on first occurrence. Other occurrences are optional, but must be consistent throughout the entire article for all usernames. If it is difficult to determine the user's id, it may be skipped over.\n\nWhen linking to a user profile, the user's id number must be used. Use the new website (`https://osu.ppy.sh/users/{username})`) to get the user's id.\n\nThe link text of the user link should be the user's current name.\n\n##### Difficulties\n\nWhenever linking to a single difficulty, use this format as the link text:\n\n```\n{artist} - {title} ({creator}) [{difficuty_name}]\n```\n\nThe link must actually link to that difficulty. Beatmap difficulty URLs must be formatted as follows:\n\n```\nhttps://osu.ppy.sh/beatmapsets/{BeatmapSetID}#{mode}/{BeatmapID}\n```\n\nThe difficulty name may be left outside of the link text, but doing so must be consistent throughout the entire article.\n\n##### Beatmaps\n\nWhenever linking to a beatmap, use this format as the link text:\n\n```\n{artist} - {title} ({creator})\n```\n\nAll beatmap URLs must be formatted as follows:\n\n```\nhttps://osu.ppy.sh/beatmapsets/{BeatmapSetID}\n```\n\n### External links\n\n*Notice: External links refers to links that go outside the `https://osu.ppy.sh/` domain.*\n\nThe `https` protocol must be used, unless the site does not support it. External links must be a clean and direct link to a reputable source. The link text should be the title of the page it is linking to. The URL from the address bar of your web browser should be copied as it is when linking to other external pages.\n\nThere are no visual differences between external and osu! web links. Due to this, the website name should be included in the title text. See the following example:\n\n```markdown\n*For more information about music theory, see: [Music theory](https://en.wikipedia.org/wiki/Music_theory \"Wikipedia\")*\n```\n\n## Images\n\nThere are two types of image links: inline and reference. Examples:\n\n**Inline style:**\n\n```markdown\n![](/wiki/shared/flag/AU.gif)\n```\n\n**Reference style:**\n\n```markdown\n![][flag_AU]\n\n[flag_AU]: /wiki/shared/flag/AU.gif\n```\n\nImages should use the inline linking style. References to reference links must be placed at the bottom of the article.\n\nImages must be placed in a folder named `img`, located in the article's folder. Images that are used in multiple articles should be stored in the `/wiki/shared/` folder.\n\n### Image caching\n\nImages on the website are cached for up to 60 days. The cached image is matched with the image link's URL.\n\nWhen updating an image, either change the image's name or append a query string to the URL. In both cases, all translations linking to the updated image should also be updated.\n\n### Formats and quality\n\nImages should use the JPG format at quality 8 (80 or 80%, depending on the program). If the image contains transparency or has text that must be readable, use the PNG format instead. If the image contains an animation, the GIF format can be used; however, this should be used sparingly as these may take longer to load or can be bigger then the [max file size](#file-size).\n\n### File size\n\nImages must be under 1 megabyte, otherwise they will fail to load. Downscaling and using JPG at 80% is almost always under the size limit.\n\nAll images should be optimised as much as possible. Use [jpeg-archive](https://github.com/danielgtaylor/jpeg-archive \"GitHub\") to compress JPEG images. For consistency, use the following command for jpeg-archive:\n\n```sh\njpeg-recompress -am smallfry \n```\n\nWhere `` is the file name to be compressed and `` is the compressed file name.\n\n### File names\n\n*Notice: File extensions must use lowercase letters, otherwise they will fail to load!*\n\nUse hyphens (`-`) when spacing words. When naming an image, the file name should be meaningful or descriptive but short.\n\n### Formatting and positioning\n\n*Note: It is currently not possible to float an image or have text wrap around it.*\n\nImages on the website will be centred when it is on a single line, by themself. Otherwise, they will be positioned inline with the paragraph. The following example will place the image in the center:\n\n```markdown\nInstalling osu! is easy. First, download the installer from the download page.\n\n![](img/download-page.jpg)\n\nThen locate the installer and run it.\n```\n\n### Alt text\n\nImages should have alt text unless it is for decorative purposes.\n\n### Captions\n\nImages are given captions on the website if they fulfill these conditions:\n\n1. The image is by itself.\n2. The image is not inside a heading.\n3. The image has title text.\n\nCaptions are assumed via the title text, which must be in plain text. Images with captions are also centred with the image on the website.\n\n### Max image width\n\nThe website's max image width is the width of the article body. Images should be no wider than 800 pixels.\n\n### Annotating images\n\nWhen annotating images, use *Torus Regular*. For Chinese, Korean, Japanese characters, use *Microsoft YaHei*.\n\nAnnotating images should be avoided, as it is difficult for translators (and other editors) to edit them.\n\n#### Translating annotated images\n\nWhen translating annotated images, the localised image version must be placed in the same directory as the original version (i.e. the English version). The filename of a localised image version must start with the original version's name, followed by a hyphen, followed by the locale name (in capital letters). See the following examples:\n\n- `hardrock-mod-vs-easy-mod.jpg` for English\n- `hardrock-mod-vs-easy-mod-DE.jpg` for German\n- `hardrock-mod-vs-easy-mod-ZH-TW.jpg` for Traditional Chinese\n\n### Screenshots of gameplay\n\nAll screenshots of gameplay must be done in the stable build, unless it is for a specific feature that is unavailable in the stable build. You should use the in-game screenshot feature (`F12`).\n\n#### Game client settings\n\n*Note: If you do not want to change your current settings for the wiki, you can move your `osu!..cfg` out of the osu! folder and move it back later.*\n\nYou must set these settings before taking a screenshot of the game client (settings not stated below are assumed to be at their defaults):\n\n- Select language: `English`\n- Prefer metadata in original language: `Enabled`\n- Resolution: `1280x720`\n- Fullscreen mode: `Disabled`\n- Parallax: `Disabled`\n- Menu tips: `Disabled`\n- Seasonal backgrounds: `Never`\n- Always show key overlay: `Enabled`\n- Current skin: `Default` (first option)\n\n*Notice to translators: If you are translating an article containing screenshots of the game, you may set the game client's language to the language you are translating in.*\n\n### Image links\n\nImages must not be part of a link text.\n\nFlag icons next to user links must be separate from the link text. See the following example:\n\n```markdown\n![][flag_AU] [peppy](https://osu.ppy.sh/users/2)\n```\n\n### Flag icons\n\n*For a list of flag icons, see: [issue \\#328](https://github.com/ppy/osu-wiki/issues/328 \"GitHub\")*\n\nThe flag icons use the two letter code (in all capital letters) and end with `.gif`. When adding a flag inline, use this format:\n\n```markdown\n![](/wiki/shared/flag/xx.gif)\n```\n\nWhere `xx` is the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 \"Wikipedia\") two-lettered country code for the flag.\n\nThe full country name should be added in the title text. The country code in the alternate text is optional, but must be applied to all flag icons in the article.\n\n## Tables\n\nTables on the website only support headings along the first row.\n\nTables must not be beautified (do not pad cells with extra spaces to make their widths uniform). They must have a vertical bar (`|`) on the left and right sides and the text of each cell must be padded with one space on both sides. Empty cells must use a vertical bar (`|`) followed by two spaces then another vertical bar (`|`).\n\nThe delimiter row (the next line after the table heading) must use only three characters per column (and be padded with a space on both sides), which must look like one of the following:\n\n- `:--` (for left align)\n- `:-:` (for centre align)\n- `--:` (for right align)\n\n---\n\nThe following is an example of what a table should look like:\n\n```markdown\n| Team \"Picturesque\" Red | Score | Team \"Statuesque\" Blue | Average Beatmap Stars |\n| :-- | :-: | --: | :-- |\n| **peppy** | 5 - 2 | pippi | 9.3 stars |\n| Aiko | 1 - 6 | **Alisa** | 4.2 stars |\n| Ryūta | 3 - 4 | **Yuzu** | 5.1 stars |\n| **Taikonator** | 7 - 0 | Tama | 13.37 stars |\n| Maria | No Contest | Mocha | |\n```\n\n## Blockquotes\n\nThe blockquote is limited to quoting text from someone. It must not be used to format text otherwise.\n\n## Thematic breaks\n\nThe thematic break (also known as the horizontal rule or line) should be used sparingly. A few uses of the thematic break may include (but is not limited to):\n\n- separating images from text\n- separating multiple images that follow one another\n- shifting the topic within a section\n\nThese must have an empty line before and after the markup. Thematic breaks must use only three hyphens, as depicted below:\n\n```markdown\n---\n```\n" }; + + // From https://osu.ppy.sh/api/v2/wiki/en/Article_styling_criteria + private APIWikiPage responseArticleParentPage => new APIWikiPage + { + Title = "Article styling criteria", + Layout = "markdown_page", + Path = "Article_styling_criteria", + Locale = "en", + Subtitle = null, + Markdown = + "---\ntags:\n - wiki standards\n---\n\n# Article styling criteria\n\n*For news posts, see: [News Styling Criteria](/wiki/News_styling_criteria)*\n\nThe article styling criteria (ASC) serve as the osu! wiki's enforced styling standards to keep consistency in clarity, formatting, and layout in all articles, and to help them strive for proper grammar, correct spelling, and correct information.\n\nThese articles are primarily tools to aid in reviewing and represent the consensus of osu! wiki contributors formed over the years. Since the wiki is a collaborative effort through the review process, it is not necessary to read or memorise all of the ASC at once. If you are looking to contribute, read the [contribution guide](/wiki/osu!_wiki/Contribution_guide).\n\nTo suggest changes regarding the article styling criteria, [open an issue on GitHub](https://github.com/ppy/osu-wiki/issues/new).\n\n## Standards\n\n*Notice: The articles below use [RFC 2119](https://tools.ietf.org/html/rfc2119) to describe requirement levels.*\n\nThe article styling criteria are split up into two articles:\n\n- [Formatting](Formatting): includes Markdown and other formatting rules\n- [Writing](Writing): includes writing practices and other grammar rules\n" + }; } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs index 862b3667b1..33e3ee7023 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Parsers; using Markdig.Syntax; using Markdig.Syntax.Inlines; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs index 9ba0da1911..8ca37a241b 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsLoungeSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs index 666e32d1d0..e6882081dd 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs index 1288b9e765..5961ed74ad 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs index c532e8bc05..8a04cd96fe 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -185,8 +187,8 @@ namespace osu.Game.Tests.Visual.Playlists // pre-check for requests we should be handling (as they are scheduled below). switch (request) { - case ShowPlaylistUserScoreRequest _: - case IndexPlaylistScoresRequest _: + case ShowPlaylistUserScoreRequest: + case IndexPlaylistScoresRequest: break; default: diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs index 14f8c1d6d4..c0cd2d9157 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs index 63bd7c8068..af3d2d9d9a 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; namespace osu.Game.Tests.Visual.Playlists diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index ac736086fd..3e2043cea5 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs index 85306b9354..83242fe363 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs index 2a31728f87..62e9adcf25 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using JetBrains.Annotations; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs index a2fa142896..94f6fa8839 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs b/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs index 7471b6acf2..44cb438a6b 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneHitEventTimingDistributionGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs index 2a5fc050d3..89d6206fd7 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs index 5dbeefd390..77fcd04fbd 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs index c65587d433..871224f3e4 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs b/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs index 07a0bcc8d8..57a3907b6e 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneSimpleStatisticTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Humanizer; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs index 1efe6d7380..8214c52edc 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Threading; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs b/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs index 227bce0c60..4f05194e08 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs b/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs index 84a0fc6e4c..6f25012bfa 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs index 1effe52608..d7d073e908 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs b/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs new file mode 100644 index 0000000000..caffc54d47 --- /dev/null +++ b/osu.Game.Tests/Visual/Settings/TestSceneLatencyCertifierScreen.cs @@ -0,0 +1,94 @@ +// 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; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Utility; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Settings +{ + public class TestSceneLatencyCertifierScreen : ScreenTestScene + { + private LatencyCertifierScreen latencyCertifier = null!; + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("Load screen", () => LoadScreen(latencyCertifier = new LatencyCertifierScreen())); + AddUntilStep("wait for load", () => latencyCertifier.IsLoaded); + } + + [Test] + public void TestSimple() + { + AddStep("set visual mode to simple", () => latencyCertifier.VisualMode.Value = LatencyVisualMode.Simple); + } + + [Test] + public void TestCircleGameplay() + { + AddStep("set visual mode to circles", () => latencyCertifier.VisualMode.Value = LatencyVisualMode.CircleGameplay); + } + + [Test] + public void TestScrollingGameplay() + { + AddStep("set visual mode to scrolling", () => latencyCertifier.VisualMode.Value = LatencyVisualMode.ScrollingGameplay); + } + + [Test] + public void TestCycleVisualModes() + { + AddRepeatStep("cycle mode", () => InputManager.Key(Key.Space), 6); + } + + [Test] + public void TestCertification() + { + checkDifficulty(1); + clickUntilResults(true); + continueFromResults(); + checkDifficulty(2); + + clickUntilResults(false); + continueFromResults(); + checkDifficulty(1); + + clickUntilResults(true); + AddAssert("check at results", () => !latencyCertifier.ChildrenOfType().Any()); + checkDifficulty(1); + } + + private void continueFromResults() + { + AddAssert("check at results", () => !latencyCertifier.ChildrenOfType().Any()); + AddStep("hit enter to continue", () => InputManager.Key(Key.Enter)); + } + + private void checkDifficulty(int difficulty) + { + AddAssert($"difficulty is {difficulty}", () => latencyCertifier.DifficultyLevel == difficulty); + } + + private void clickUntilResults(bool clickCorrect) + { + AddUntilStep("click correct button until results", () => + { + var latencyArea = latencyCertifier + .ChildrenOfType() + .SingleOrDefault(a => clickCorrect ? a.TargetFrameRate == null : a.TargetFrameRate != null); + + // reached results + if (latencyArea == null) + return true; + + latencyArea.ChildrenOfType().Single().TriggerClick(); + return false; + }); + } + } +} diff --git a/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs b/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs index ac0956502e..e32757c6f6 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Threading; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs b/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs index 0c46fa439a..289969af3e 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneRestoreDefaultValueButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs index 3e679a7905..b3d1966511 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs index 334a814688..53e1f0e0bf 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsNumberBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs index 97463b7466..9791bb6248 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -74,7 +76,7 @@ namespace osu.Game.Tests.Visual.Settings public void ToggleVisibility() { AddWaitStep("wait some", 5); - AddToggleStep("toggle visibility", visible => settings.ToggleVisibility()); + AddToggleStep("toggle visibility", _ => settings.ToggleVisibility()); } [Test] diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs index ffaa038930..98de712703 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs index dc5b0e0d77..d1d3748c26 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneTabletSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs index 8af70df48a..4510fda11d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; @@ -68,7 +70,7 @@ namespace osu.Game.Tests.Visual.SongSelect { AddStep("set beatmap", () => advancedStats.BeatmapInfo = new BeatmapInfo { - Ruleset = rulesets.GetRuleset(3) ?? throw new InvalidOperationException(), + Ruleset = rulesets.GetRuleset(3) ?? throw new InvalidOperationException("osu!mania ruleset not found"), Difficulty = new BeatmapDifficulty { CircleSize = 5, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 540b820250..e574ee30fb 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -823,7 +825,8 @@ namespace osu.Game.Tests.Visual.SongSelect checkVisibleItemCount(true, 15); } - private void loadBeatmaps(List beatmapSets = null, Func initialCriteria = null, Action carouselAdjust = null, int? count = null, bool randomDifficulties = false) + private void loadBeatmaps(List beatmapSets = null, Func initialCriteria = null, Action carouselAdjust = null, int? count = null, + bool randomDifficulties = false) { bool changed = false; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index bd15c40271..e33cfe280e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index ef04baefa2..a144111fd3 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -51,13 +53,8 @@ namespace osu.Game.Tests.Visual.SongSelect Margin = new MarginPadding { Top = 20 } }); - AddStep("show", () => - { - infoWedge.Show(); - infoWedge.Beatmap = Beatmap.Value; - }); + AddStep("show", () => infoWedge.Show()); - // select part is redundant, but wait for load isn't selectBeatmap(Beatmap.Value.Beatmap); AddWaitStep("wait for select", 3); @@ -89,19 +86,19 @@ namespace osu.Game.Tests.Visual.SongSelect switch (instance) { - case OsuRuleset _: + case OsuRuleset: testInfoLabels(5); break; - case TaikoRuleset _: + case TaikoRuleset: testInfoLabels(5); break; - case CatchRuleset _: + case CatchRuleset: testInfoLabels(5); break; - case ManiaRuleset _: + case ManiaRuleset: testInfoLabels(4); break; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 3b15ee9c45..abcb888cd4 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -45,7 +47,7 @@ namespace osu.Game.Tests.Visual.SongSelect dependencies.Cache(rulesetStore = new RealmRulesetStore(Realm)); dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, Realm, rulesetStore, null, dependencies.Get(), Resources, dependencies.Get(), Beatmap.Default)); - dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, Realm, Scheduler)); + dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, Realm, Scheduler, API)); Dependencies.Cache(Realm); return dependencies; @@ -138,11 +140,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 6602580, Username = @"waaiiru", - Country = new Country - { - FullName = @"Spain", - FlagName = @"ES", - }, + CountryCode = CountryCode.ES, }, }); } @@ -162,12 +160,8 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 6602580, Username = @"waaiiru", - Country = new Country - { - FullName = @"Spain", - FlagName = @"ES", - }, - }, + CountryCode = CountryCode.ES, + } }); } @@ -223,11 +217,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 6602580, Username = @"waaiiru", - Country = new Country - { - FullName = @"Spain", - FlagName = @"ES", - }, + CountryCode = CountryCode.ES, }, }, new ScoreInfo @@ -244,11 +234,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 4608074, Username = @"Skycries", - Country = new Country - { - FullName = @"Brazil", - FlagName = @"BR", - }, + CountryCode = CountryCode.BR, }, }, new ScoreInfo @@ -266,11 +252,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 1014222, Username = @"eLy", - Country = new Country - { - FullName = @"Japan", - FlagName = @"JP", - }, + CountryCode = CountryCode.JP, }, }, new ScoreInfo @@ -288,11 +270,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 1541390, Username = @"Toukai", - Country = new Country - { - FullName = @"Canada", - FlagName = @"CA", - }, + CountryCode = CountryCode.CA, }, }, new ScoreInfo @@ -310,11 +288,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 2243452, Username = @"Satoruu", - Country = new Country - { - FullName = @"Venezuela", - FlagName = @"VE", - }, + CountryCode = CountryCode.VE, }, }, new ScoreInfo @@ -332,11 +306,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 2705430, Username = @"Mooha", - Country = new Country - { - FullName = @"France", - FlagName = @"FR", - }, + CountryCode = CountryCode.FR, }, }, new ScoreInfo @@ -354,11 +324,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 7151382, Username = @"Mayuri Hana", - Country = new Country - { - FullName = @"Thailand", - FlagName = @"TH", - }, + CountryCode = CountryCode.TH, }, }, new ScoreInfo @@ -376,11 +342,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 2051389, Username = @"FunOrange", - Country = new Country - { - FullName = @"Canada", - FlagName = @"CA", - }, + CountryCode = CountryCode.CA, }, }, new ScoreInfo @@ -398,11 +360,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 6169483, Username = @"-Hebel-", - Country = new Country - { - FullName = @"Mexico", - FlagName = @"MX", - }, + CountryCode = CountryCode.MX, }, }, new ScoreInfo @@ -420,11 +378,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 6702666, Username = @"prhtnsm", - Country = new Country - { - FullName = @"Germany", - FlagName = @"DE", - }, + CountryCode = CountryCode.DE, }, }, }; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index fb6d9a0b4b..27b485156c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs index e9742acdde..5ad82f1ffd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs index a78a8aa028..504ded5406 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -164,15 +167,22 @@ namespace osu.Game.Tests.Visual.SongSelect var beatmapSet = TestResources.CreateTestBeatmapSetInfo(rulesets.Length, rulesets); - for (int i = 0; i < rulesets.Length; i++) + var importedBeatmapSet = Game.BeatmapManager.Import(beatmapSet); + + Debug.Assert(importedBeatmapSet != null); + + importedBeatmapSet.PerformWrite(s => { - var beatmap = beatmapSet.Beatmaps[i]; + for (int i = 0; i < rulesets.Length; i++) + { + var beatmap = s.Beatmaps[i]; - beatmap.StarRating = i + 1; - beatmap.DifficultyName = $"SR{i + 1}"; - } + beatmap.StarRating = i + 1; + beatmap.DifficultyName = $"SR{i + 1}"; + } + }); - return Game.BeatmapManager.Import(beatmapSet)?.Value; + return importedBeatmapSet.Value; } private bool ensureAllBeatmapSetsImported(IEnumerable beatmapSets) => beatmapSets.All(set => set != null); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneDifficultyRangeFilterControl.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneDifficultyRangeFilterControl.cs new file mode 100644 index 0000000000..7ae2c6e5e2 --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneDifficultyRangeFilterControl.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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Screens.Select; +using osuTK; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public class TestSceneDifficultyRangeFilterControl : OsuTestScene + { + [Test] + public void TestBasic() + { + AddStep("create control", () => + { + Child = new DifficultyRangeFilterControl + { + Width = 200, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(3), + }; + }); + } + } +} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs index b7ec128596..6807180640 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -151,10 +153,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } })); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); - AddStep("add beatmap to collection", () => collectionManager.Collections[0].Beatmaps.Add(Beatmap.Value.BeatmapInfo)); + AddStep("add beatmap to collection", () => collectionManager.Collections[0].BeatmapHashes.Add(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare)); - AddStep("remove beatmap from collection", () => collectionManager.Collections[0].Beatmaps.Clear()); + AddStep("remove beatmap from collection", () => collectionManager.Collections[0].BeatmapHashes.Clear()); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); } @@ -169,11 +171,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); addClickAddOrRemoveButtonStep(1); - AddAssert("collection contains beatmap", () => collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo)); + AddAssert("collection contains beatmap", () => collectionManager.Collections[0].BeatmapHashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare)); addClickAddOrRemoveButtonStep(1); - AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo)); + AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].BeatmapHashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 77f5bd83d6..159a3b1923 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -95,15 +97,32 @@ namespace osu.Game.Tests.Visual.SongSelect AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Visible); } + [Test] + public void TestPlaceholderStarDifficulty() + { + addRulesetImportStep(0); + AddStep("change star filter", () => config.SetValue(OsuSetting.DisplayStarsMinimum, 10.0)); + + createSongSelect(); + + AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Visible); + + AddStep("click link in placeholder", () => getPlaceholder().ChildrenOfType().First().TriggerClick()); + + AddUntilStep("star filter reset", () => config.Get(OsuSetting.DisplayStarsMinimum) == 0.0); + AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Hidden); + } + [Test] public void TestPlaceholderConvertSetting() { - changeRuleset(2); addRulesetImportStep(0); AddStep("change convert setting", () => config.SetValue(OsuSetting.ShowConvertedBeatmaps, false)); createSongSelect(); + changeRuleset(2); + AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Visible); AddStep("click link in placeholder", () => getPlaceholder().ChildrenOfType().First().TriggerClick()); @@ -870,10 +889,10 @@ namespace osu.Game.Tests.Visual.SongSelect return set != null; }); - FilterableGroupedDifficultyIcon groupIcon = null; + GroupedDifficultyIcon groupIcon = null; AddUntilStep("Find group icon for different ruleset", () => { - return (groupIcon = set.ChildrenOfType() + return (groupIcon = set.ChildrenOfType() .FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.OnlineID == 3)) != null; }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs index f27615eea5..cb78fbfe35 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneSongSelectFooter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Select; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs index 7bef7c8fce..05b5c5c0cd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -30,7 +32,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Dependencies.Cache(rulesets = new RealmRulesetStore(Realm)); Dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, Realm, rulesets, null, audio, Resources, host, Beatmap.Default)); - Dependencies.Cache(scoreManager = new ScoreManager(rulesets, () => beatmapManager, LocalStorage, Realm, Scheduler)); + Dependencies.Cache(scoreManager = new ScoreManager(rulesets, () => beatmapManager, LocalStorage, Realm, Scheduler, API)); Dependencies.Cache(Realm); beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs new file mode 100644 index 0000000000..70786c93e7 --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUpdateBeatmapSetButton.cs @@ -0,0 +1,156 @@ +// Copyright (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.Graphics; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Screens.Select; +using osu.Game.Screens.Select.Carousel; +using osu.Game.Tests.Online; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Visual.SongSelect +{ + [TestFixture] + public class TestSceneUpdateBeatmapSetButton : OsuManualInputManagerTestScene + { + private BeatmapCarousel carousel = null!; + + private TestSceneOnlinePlayBeatmapAvailabilityTracker.TestBeatmapModelDownloader beatmapDownloader = null!; + + private BeatmapSetInfo testBeatmapSetInfo = null!; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + var importer = parent.Get(); + + dependencies.CacheAs(beatmapDownloader = new TestSceneOnlinePlayBeatmapAvailabilityTracker.TestBeatmapModelDownloader(importer, API)); + return dependencies; + } + + private UpdateBeatmapSetButton? getUpdateButton() => carousel.ChildrenOfType().SingleOrDefault(); + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create carousel", () => + { + Child = carousel = new BeatmapCarousel + { + RelativeSizeAxes = Axes.Both, + BeatmapSets = new List + { + (testBeatmapSetInfo = TestResources.CreateTestBeatmapSetInfo()), + } + }; + }); + + AddUntilStep("wait for load", () => carousel.BeatmapSetsLoaded); + + AddAssert("update button not visible", () => getUpdateButton() == null); + } + + [Test] + public void TestDownloadToCompletion() + { + ArchiveDownloadRequest? downloadRequest = null; + + AddStep("update online hash", () => + { + testBeatmapSetInfo.Beatmaps.First().OnlineMD5Hash = "different hash"; + testBeatmapSetInfo.Beatmaps.First().LastOnlineUpdate = DateTimeOffset.Now; + + carousel.UpdateBeatmapSet(testBeatmapSetInfo); + }); + + AddUntilStep("only one set visible", () => carousel.ChildrenOfType().Count() == 1); + AddUntilStep("update button visible", () => getUpdateButton() != null); + + AddStep("click button", () => getUpdateButton()?.TriggerClick()); + + AddUntilStep("wait for download started", () => + { + downloadRequest = beatmapDownloader.GetExistingDownload(testBeatmapSetInfo); + return downloadRequest != null; + }); + + AddUntilStep("wait for button disabled", () => getUpdateButton()?.Enabled.Value == false); + + AddUntilStep("progress download to completion", () => + { + if (downloadRequest is TestSceneOnlinePlayBeatmapAvailabilityTracker.TestDownloadRequest testRequest) + { + testRequest.SetProgress(testRequest.Progress + 0.1f); + + if (testRequest.Progress >= 1) + { + testRequest.TriggerSuccess(); + + // usually this would be done by the import process. + testBeatmapSetInfo.Beatmaps.First().MD5Hash = "different hash"; + testBeatmapSetInfo.Beatmaps.First().LastOnlineUpdate = DateTimeOffset.Now; + + // usually this would be done by a realm subscription. + carousel.UpdateBeatmapSet(testBeatmapSetInfo); + return true; + } + } + + return false; + }); + } + + [Test] + public void TestDownloadFailed() + { + ArchiveDownloadRequest? downloadRequest = null; + + AddStep("update online hash", () => + { + testBeatmapSetInfo.Beatmaps.First().OnlineMD5Hash = "different hash"; + testBeatmapSetInfo.Beatmaps.First().LastOnlineUpdate = DateTimeOffset.Now; + + carousel.UpdateBeatmapSet(testBeatmapSetInfo); + }); + + AddUntilStep("only one set visible", () => carousel.ChildrenOfType().Count() == 1); + AddUntilStep("update button visible", () => getUpdateButton() != null); + + AddStep("click button", () => getUpdateButton()?.TriggerClick()); + + AddUntilStep("wait for download started", () => + { + downloadRequest = beatmapDownloader.GetExistingDownload(testBeatmapSetInfo); + return downloadRequest != null; + }); + + AddUntilStep("wait for button disabled", () => getUpdateButton()?.Enabled.Value == false); + + AddUntilStep("progress download to failure", () => + { + if (downloadRequest is TestSceneOnlinePlayBeatmapAvailabilityTracker.TestDownloadRequest testRequest) + { + testRequest.SetProgress(testRequest.Progress + 0.1f); + + if (testRequest.Progress >= 0.5f) + { + testRequest.TriggerFailure(new Exception()); + return true; + } + } + + return false; + }); + + AddUntilStep("wait for button enabled", () => getUpdateButton()?.Enabled.Value == true); + } + } +} diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index c71e54e9a8..39fd9fda2b 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -67,11 +69,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 6602580, Username = @"waaiiru", - Country = new Country - { - FullName = @"Spain", - FlagName = @"ES", - }, + CountryCode = CountryCode.ES, }, }, new ScoreInfo @@ -86,11 +84,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 4608074, Username = @"Skycries", - Country = new Country - { - FullName = @"Brazil", - FlagName = @"BR", - }, + CountryCode = CountryCode.BR, }, }, new ScoreInfo @@ -105,11 +99,7 @@ namespace osu.Game.Tests.Visual.SongSelect { Id = 1541390, Username = @"Toukai", - Country = new Country - { - FullName = @"Canada", - FlagName = @"CA", - }, + CountryCode = CountryCode.CA, }, } }; diff --git a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs index 4ab201ef46..0458f41358 100644 --- a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs +++ b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index 7729ad0ff3..7588546f42 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 2440911c11..9b84cf2a9e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs index 3cbb7daf51..368babc9b5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatSyncedContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -68,7 +70,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Set time before zero", () => { - beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) => + beatContainer.NewBeat = (i, timingControlPoint, _, _) => { lastActuationTime = gameplayClockContainer.CurrentTime; lastTimingPoint = timingControlPoint; @@ -103,7 +105,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Set time before zero", () => { - beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) => + beatContainer.NewBeat = (i, timingControlPoint, _, _) => { lastBeatIndex = i; lastBpm = timingControlPoint.BPM; @@ -124,7 +126,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("bind event", () => { - beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) => lastBpm = timingControlPoint.BPM; + beatContainer.NewBeat = (_, timingControlPoint, _, _) => lastBpm = timingControlPoint.BPM; }); AddUntilStep("wait for trigger", () => lastBpm != null); @@ -155,7 +157,7 @@ namespace osu.Game.Tests.Visual.UserInterface actualEffectPoint = null; beatContainer.AllowMistimedEventFiring = false; - beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) => + beatContainer.NewBeat = (_, _, effectControlPoint, _) => { if (Precision.AlmostEquals(gameplayClockContainer.CurrentTime + earlyActivationMilliseconds, expectedEffectPoint.Time, BeatSyncedContainer.MISTIMED_ALLOWANCE)) actualEffectPoint = effectControlPoint; @@ -267,7 +269,7 @@ namespace osu.Game.Tests.Visual.UserInterface private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { - if (timingPoints[^1] == current) + if (ReferenceEquals(timingPoints[^1], current)) return current; int index = timingPoints.IndexOf(current); // -1 means that this is a "default beat" @@ -279,7 +281,7 @@ namespace osu.Game.Tests.Visual.UserInterface { if (timingPoints.Count == 0) return 0; - if (timingPoints[^1] == current) + if (ReferenceEquals(timingPoints[^1], current)) { Debug.Assert(BeatSyncSource.Clock != null); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs index e3d47f08c6..bc846d8bcb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingCardSizeTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs index f17de75f5c..e8454e8d0f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs @@ -1,14 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; -using Humanizer; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; @@ -75,13 +77,13 @@ namespace osu.Game.Tests.Visual.UserInterface }; control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true); - control.General.BindCollectionChanged((u, v) => general.Text = $"General: {(control.General.Any() ? string.Join('.', control.General.Select(i => i.ToString().Underscore())) : "")}", true); + control.General.BindCollectionChanged((_, _) => general.Text = $"General: {(control.General.Any() ? string.Join('.', control.General.Select(i => i.ToString().ToSnakeCase())) : "")}", true); control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true); control.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true); control.Genre.BindValueChanged(g => genre.Text = $"Genre: {g.NewValue}", true); control.Language.BindValueChanged(l => language.Text = $"Language: {l.NewValue}", true); - control.Extra.BindCollectionChanged((u, v) => extra.Text = $"Extra: {(control.Extra.Any() ? string.Join('.', control.Extra.Select(i => i.ToString().ToLowerInvariant())) : "")}", true); - control.Ranks.BindCollectionChanged((u, v) => ranks.Text = $"Ranks: {(control.Ranks.Any() ? string.Join('.', control.Ranks.Select(i => i.ToString())) : "")}", true); + control.Extra.BindCollectionChanged((_, _) => extra.Text = $"Extra: {(control.Extra.Any() ? string.Join('.', control.Extra.Select(i => i.ToString().ToLowerInvariant())) : "")}", true); + control.Ranks.BindCollectionChanged((_, _) => ranks.Text = $"Ranks: {(control.Ranks.Any() ? string.Join('.', control.Ranks.Select(i => i.ToString())) : "")}", true); control.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true); control.ExplicitContent.BindValueChanged(e => explicitMap.Text = $"Explicit Maps: {e.NewValue}", true); }); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs index 5364f0bef5..3247461fba 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs index 37b7b64615..ff1dce1a4e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs index 3967b62c95..a387148c2c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs index 7bc75f1c44..8e2502dad1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControlHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs index 1a879e2e70..cbd4c69180 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneButtonSystem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs index fa9179443d..eba0e8cfed 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index 920b437f57..fd4ec2f3dc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs index c2ac5179c9..115833b034 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays.Comments.Buttons; using osu.Framework.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs index 3b43f8485a..bd77c4725c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 5b74852259..0fa7c5303c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs index 17ac812eb0..2b6a93143f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Overlays.Dashboard.Home; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 1350052ae6..e59914f69a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -16,6 +18,7 @@ using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; +using osu.Game.Models; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Overlays; @@ -71,7 +74,7 @@ namespace osu.Game.Tests.Visual.UserInterface dependencies.Cache(rulesetStore = new RealmRulesetStore(Realm)); dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, Realm, rulesetStore, null, dependencies.Get(), Resources, dependencies.Get(), Beatmap.Default)); - dependencies.Cache(scoreManager = new ScoreManager(dependencies.Get(), () => beatmapManager, LocalStorage, Realm, Scheduler)); + dependencies.Cache(scoreManager = new ScoreManager(dependencies.Get(), () => beatmapManager, LocalStorage, Realm, Scheduler, API)); Dependencies.Cache(Realm); return dependencies; @@ -98,6 +101,7 @@ namespace osu.Game.Tests.Visual.UserInterface Rank = ScoreRank.XH, User = new APIUser { Username = "TestUser" }, Ruleset = new OsuRuleset().RulesetInfo, + Files = { new RealmNamedFileUsage(new RealmFile { Hash = $"{i}" }, string.Empty) } }; importedScores.Add(scoreManager.Import(score).Value); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs index 54cdeaf956..a8e6142bab 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs index cd84f8b380..984276b27e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDifficultyMultiplierDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs index 19097f33bb..59e85ae085 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs index f2f475e063..ee07acef52 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs index f92aae43d2..2d97513206 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs index 2bb6e58448..704185b117 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.cs new file mode 100644 index 0000000000..d78707045b --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFPSCounter.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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneFPSCounter : OsuTestScene + { + [SetUpSteps] + public void SetUpSteps() + { + AddStep("create display", () => + { + Children = new Drawable[] + { + new Box + { + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new FPSCounter(), + new FPSCounter { Scale = new Vector2(2) }, + new FPSCounter { Scale = new Vector2(4) }, + } + }, + }; + }); + } + + [Test] + public void TestBasic() + { + } + } +} diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs index 9747b5cc53..8fa4f7ec0e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs index 51065939f0..6cc4ac709b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs index 081b240795..3c3d5933e4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using System.Threading.Tasks; using Moq; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs index 64ad4ff119..98ad77fbae 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index d09efdc925..b845b85e1f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -52,7 +54,7 @@ namespace osu.Game.Tests.Visual.UserInterface notificationOverlay.Reset(); performer.Setup(g => g.PerformFromScreen(It.IsAny>(), It.IsAny>())) - .Callback((Action action, IEnumerable types) => action(null)); + .Callback((Action action, IEnumerable _) => action(null)); notificationOverlay.Setup(n => n.Post(It.IsAny())) .Callback((Notification n) => lastNotification = n); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index 0631059d1a..a4b5faae26 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs index ea3cfbd497..ad5e498c8b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFriendsOnlineStatusControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index cea91d422e..235dbc1fcb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs index c80b3e6297..35d250c7ac 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs index e1ea02ba67..d7a69616f3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledColourPalette.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs index d5dda6f6cd..7ce0fceff9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDrawable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; @@ -76,7 +78,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.Centre, Width = 500, AutoSizeAxes = Axes.Y, - Child = component = padded ? (LabelledDrawable)new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(), + Child = component = padded ? new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(), }; component.Label = "a sample component"; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs index a9aaefdf6c..cd14d6bde3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs index 1b7f65f9a0..8ccfe2ee9c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs index 903f1242b4..03434ff0a1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index c11ba0aa59..3f93e60773 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs index d426723f0b..2fc6405b88 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs index 47f5bdfe17..8c9b9186b1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs index 155d043bf9..b565cb359b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs index b46d35a84d..558ea01a49 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoTrackingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 331509e10f..72cddc0ad2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using NUnit.Framework; @@ -11,9 +9,11 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osu.Game.Overlays.Mods; +using osu.Game.Overlays.Mods.Input; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Utils; @@ -27,6 +27,9 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + [Resolved] + private OsuConfigManager configManager { get; set; } = null!; + [TestCase(ModType.DifficultyReduction)] [TestCase(ModType.DifficultyIncrease)] [TestCase(ModType.Conversion)] @@ -134,14 +137,16 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestKeyboardSelection() + public void TestSequentialKeyboardSelection() { + AddStep("set sequential hotkey mode", () => configManager.SetValue(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Sequential)); + ModColumn column = null!; AddStep("create content", () => Child = new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(30), - Child = column = new ModColumn(ModType.DifficultyReduction, true, new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }) + Child = column = new ModColumn(ModType.DifficultyReduction, true) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -160,9 +165,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set filter to NF", () => setFilter(mod => mod.Acronym == "NF")); AddStep("press W", () => InputManager.Key(Key.W)); + AddAssert("NF panel not selected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NF").Active.Value); + + AddStep("press Q", () => InputManager.Key(Key.Q)); AddAssert("NF panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NF").Active.Value); - AddStep("press W again", () => InputManager.Key(Key.W)); + AddStep("press Q again", () => InputManager.Key(Key.Q)); AddAssert("NF panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NF").Active.Value); AddStep("filter out everything", () => setFilter(_ => false)); @@ -173,6 +181,113 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("clear filter", () => setFilter(null)); } + [Test] + public void TestClassicKeyboardExclusiveSelection() + { + AddStep("set classic hotkey mode", () => configManager.SetValue(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Classic)); + + ModColumn column = null!; + AddStep("create content", () => Child = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(30), + Child = column = new ModColumn(ModType.DifficultyIncrease, false) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AvailableMods = getExampleModsFor(ModType.DifficultyIncrease) + } + }); + + AddUntilStep("wait for panel load", () => column.IsLoaded && column.ItemsLoaded); + + AddStep("press A", () => InputManager.Key(Key.A)); + AddAssert("HR panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "HR").Active.Value); + + AddStep("press A again", () => InputManager.Key(Key.A)); + AddAssert("HR panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "HR").Active.Value); + + AddStep("press D", () => InputManager.Key(Key.D)); + AddAssert("DT panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + + AddStep("press D again", () => InputManager.Key(Key.D)); + AddAssert("DT panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + AddAssert("NC panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NC").Active.Value); + + AddStep("press D again", () => InputManager.Key(Key.D)); + AddAssert("DT panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + AddAssert("NC panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NC").Active.Value); + + AddStep("press Shift-D", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.D); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + AddAssert("DT panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + AddAssert("NC panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NC").Active.Value); + + AddStep("press J", () => InputManager.Key(Key.J)); + AddAssert("no change", () => this.ChildrenOfType().Single(panel => panel.Active.Value).Mod.Acronym == "NC"); + + AddStep("filter everything but NC", () => setFilter(mod => mod.Acronym == "NC")); + + AddStep("press A", () => InputManager.Key(Key.A)); + AddAssert("no change", () => this.ChildrenOfType().Single(panel => panel.Active.Value).Mod.Acronym == "NC"); + } + + [Test] + public void TestClassicKeyboardIncompatibleSelection() + { + AddStep("set classic hotkey mode", () => configManager.SetValue(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Classic)); + + ModColumn column = null!; + AddStep("create content", () => Child = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(30), + Child = column = new ModColumn(ModType.DifficultyIncrease, true) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AvailableMods = getExampleModsFor(ModType.DifficultyIncrease) + } + }); + + AddUntilStep("wait for panel load", () => column.IsLoaded && column.ItemsLoaded); + + AddStep("press A", () => InputManager.Key(Key.A)); + AddAssert("HR panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "HR").Active.Value); + + AddStep("press A again", () => InputManager.Key(Key.A)); + AddAssert("HR panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "HR").Active.Value); + + AddStep("press D", () => InputManager.Key(Key.D)); + AddAssert("DT panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + AddAssert("NC panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NC").Active.Value); + + AddStep("press D again", () => InputManager.Key(Key.D)); + AddAssert("DT panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + AddAssert("NC panel deselected", () => !this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NC").Active.Value); + + AddStep("press Shift-D", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.D); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + AddAssert("DT panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "DT").Active.Value); + AddAssert("NC panel selected", () => this.ChildrenOfType().Single(panel => panel.Mod.Acronym == "NC").Active.Value); + + AddStep("press J", () => InputManager.Key(Key.J)); + AddAssert("no change", () => this.ChildrenOfType().Count(panel => panel.Active.Value) == 2); + + AddStep("filter everything but NC", () => setFilter(mod => mod.Acronym == "NC")); + + AddStep("press A", () => InputManager.Key(Key.A)); + AddAssert("no change", () => this.ChildrenOfType().Count(panel => panel.Active.Value) == 2); + } + private void setFilter(Func? filter) { foreach (var modState in this.ChildrenOfType().Single().AvailableMods) @@ -183,8 +298,8 @@ namespace osu.Game.Tests.Visual.UserInterface { public new bool SelectionAnimationRunning => base.SelectionAnimationRunning; - public TestModColumn(ModType modType, bool allowBulkSelection) - : base(modType, allowBulkSelection) + public TestModColumn(ModType modType, bool allowIncompatibleSelection) + : base(modType, allowIncompatibleSelection) { } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs index 8e1f426f7b..181f46a996 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDifficultyAdjustSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -11,7 +13,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Overlays.Settings; +using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osuTK; @@ -244,7 +246,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep($"Set {name} slider to {value}", () => this.ChildrenOfType().First(c => c.LabelText == name) - .ChildrenOfType>().First().Current.Value = value); + .ChildrenOfType>().First().Current.Value = value); } private void checkBindableAtValue(string name, float? expectedValue) @@ -258,7 +260,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddAssert($"Slider {name} at {expectedValue}", () => this.ChildrenOfType().First(c => c.LabelText == name) - .ChildrenOfType>().First().Current.Value == expectedValue); + .ChildrenOfType>().First().Current.Value == expectedValue); } private void setBeatmapWithDifficultyParameters(float value) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs index b8f5ee5e86..c65d1f8c5e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs index 10eab148de..c45ea3a40c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModFlowDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs index 513eb2fafc..ce9aa682d1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModIcon.cs @@ -3,6 +3,8 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.UI; @@ -11,10 +13,24 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneModIcon : OsuTestScene { + [Test] + public void TestShowAllMods() + { + AddStep("create mod icons", () => + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Full, + ChildrenEnumerable = Ruleset.Value.CreateInstance().CreateAllMods().Select(m => new ModIcon(m)), + }; + }); + } + [Test] public void TestChangeModType() { - ModIcon icon = null; + ModIcon icon = null!; AddStep("create mod icon", () => Child = icon = new ModIcon(new OsuModDoubleTime())); AddStep("change mod", () => icon.Mod = new OsuModEasy()); @@ -23,7 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestInterfaceModType() { - ModIcon icon = null; + ModIcon icon = null!; var ruleset = new OsuRuleset(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs index f56d9c8a91..9c0b36073b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 9bb02c3e75..4de70f6f9e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -228,7 +230,7 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); AddStep("select diff adjust", () => SelectedMods.Value = new Mod[] { new OsuModDifficultyAdjust() }); - AddStep("set setting", () => modSelectOverlay.ChildrenOfType>().First().Current.Value = 8); + AddStep("set setting", () => modSelectOverlay.ChildrenOfType>().First().Current.Value = 8); AddAssert("ensure setting is propagated", () => SelectedMods.Value.OfType().Single().CircleSize.Value == 8); @@ -385,7 +387,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => panel.Filtered.Value)); AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => !panel.Filtered.Value)); - AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = m => true); + AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = _ => true); AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => !panel.Filtered.Value)); AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => !panel.Filtered.Value)); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs index ddc1c8c128..a9c3872643 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettingsArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs index 447352b7a6..ff9cc09806 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs index dbde7ce425..ddb5845df8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index a2aa0499d2..cf069a9e34 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs index 475ab0c414..f7f35b8361 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNowPlayingOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index 544581082e..2d8d7a5de3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs index 2eb5a8014e..bab2121d70 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuAnimatedButton.cs @@ -1,7 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; @@ -87,7 +88,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddToggleStep("toggle enabled", toggle => { for (int i = 0; i < 6; i++) - button.Action = toggle ? () => { } : (Action)null; + button.Action = toggle ? () => { } : null; }); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs index 9d086cce5c..d4c2bfd422 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuButton.cs @@ -1,7 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -27,7 +28,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddToggleStep("toggle enabled", toggle => { for (int i = 0; i < 6; i++) - button.Action = toggle ? () => { } : (Action)null; + button.Action = toggle ? () => { } : null; }); } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs index cce0295413..2cda95bda4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs index eedafce271..f534fc0fac 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuFont.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs index 396bec51b6..d4b15c06c5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuHoverContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs index 0bc4ac12d6..1e1c3b3282 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Reflection; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs index 8b91339479..e23a960a7e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs index 82e26cb87d..cdccb817b9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMarkdownContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs index 387deea76c..5349a1b8a0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuMenu.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs index 1848cf6a5e..6cc89a6df8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs index 353f84c546..cc510f007b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs index 2a76b8e265..a5493559d6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs index db414d23a0..11507e561f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index f4fa41a3b7..5a1ce9e791 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs index 7fa730e02b..7b3e82ff6d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index c99ac52cb1..1907a56735 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs index 588b25c02d..6ab69f32ef 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs index 84a06d97df..ee5ef2f364 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePlaylistOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; @@ -25,6 +27,8 @@ namespace osu.Game.Tests.Visual.UserInterface private Live first; + private const int item_count = 100; + [SetUp] public void Setup() => Schedule(() => { @@ -44,7 +48,7 @@ namespace osu.Game.Tests.Visual.UserInterface beatmapSets.Clear(); - for (int i = 0; i < 100; i++) + for (int i = 0; i < item_count; i++) { beatmapSets.Add(TestResources.CreateTestBeatmapSetInfo().ToLiveUnmanaged()); } @@ -57,6 +61,13 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestRearrangeItems() { + AddUntilStep("wait for load complete", () => + { + return this + .ChildrenOfType() + .Count(i => i.ChildrenOfType().First().DelayedLoadCompleted) > 6; + }); + AddUntilStep("wait for animations to complete", () => !playlistOverlay.Transforms.Any()); AddStep("hold 1st item handle", () => diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index b5f2544071..218677fd03 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs index 4ce684d5af..9738ff33c3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneProfileSubsectionHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Overlays.Profile.Sections; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs index 24bc0dbc97..a95ae190dd 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs index 454a71e6d2..2587960275 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs index 8b4e3f6d3a..2ba0fa36c3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSafeAreaHandling.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs index 5d554719a5..67c47492b0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScalingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs index 77a7d819a9..b3ee0af78b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs index 1f3736bd9b..f71d797363 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs index fb04c5bad0..466c83b1ac 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs index 8ef24e58a0..50e506f82b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsToolboxGroup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs index 5a4eeef4d9..ba9e1c6366 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedButtons.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs index 4dd64c6536..c0fb315e03 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs index ef2b25cd92..09292ee92b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs index e1dbf04133..78e06f7e32 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs index 2806e6d347..1f65b6ec7f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStarRatingDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs index 18ec631f37..11acb31fef 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneStatefulMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs index 37fab75aee..4d90a11405 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSwitchButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs index a884741ff8..b868abcc45 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs index 9fb8e747f3..92cfeef369 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs index cdfbb14cba..de67b85c7d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToolbarRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Toolbar; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs index 849577186d..a11efb69bd 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index 7109a55e7e..32f47d77e1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs index 7b6774a6b2..8176871481 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs index 8f7140ed7c..5e2e2ccff6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs index 64708c4858..b5b4542eac 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumeOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Overlays; using osu.Game.Overlays.Volume; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs index c8478c8eca..9ce71a5347 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Overlays.Volume; using osuTK; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs index 5b130b9224..6a4934cf47 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs index 7986f14d1d..8fb0fd84a1 100644 --- a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs +++ b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index ab7bf7fb73..5e41392560 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index a1eef4ce47..7615b3e8be 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -1,14 +1,13 @@  - - + WinExe diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs index 33165d385a..0e6e8f54bd 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDateTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs index f98f55dfbc..66093b80a1 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs index bb47683be1..4ea7e8008a 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs @@ -1,9 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; @@ -24,13 +25,13 @@ namespace osu.Game.Tournament.Tests.Components FullName = { Value = "Australia" }, Players = { - new APIUser { Username = "ASecretBox" }, - new APIUser { Username = "Dereban" }, - new APIUser { Username = "mReKk" }, - new APIUser { Username = "uyghti" }, - new APIUser { Username = "Parkes" }, - new APIUser { Username = "Shiroha" }, - new APIUser { Username = "Jordan The Bear" }, + new TournamentUser { Username = "ASecretBox" }, + new TournamentUser { Username = "Dereban" }, + new TournamentUser { Username = "mReKk" }, + new TournamentUser { Username = "uyghti" }, + new TournamentUser { Username = "Parkes" }, + new TournamentUser { Username = "Shiroha" }, + new TournamentUser { Username = "Jordan The Bear" }, } }; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs index b29e4964b6..55d58fef6e 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs index 11b5cc7556..53301c34d4 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Utils; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs index 13bca7bea1..514a797068 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs b/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs index b6004c651b..992baa48a3 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneSongBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -40,7 +42,7 @@ namespace osu.Game.Tournament.Tests.Components beatmap.Length = 123456; beatmap.BPM = 133; - songBar.Beatmap = beatmap; + songBar.Beatmap = new TournamentBeatmap(beatmap); }); AddStep("set mods to HR", () => songBar.Mods = LegacyMods.HardRock); AddStep("set mods to DT", () => songBar.Mods = LegacyMods.DoubleTime); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs index b678f69b8f..adfe048ce4 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Online.API; @@ -8,6 +10,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Tests.Components { @@ -30,7 +33,7 @@ namespace osu.Game.Tournament.Tests.Components private void success(APIBeatmap beatmap) { - Add(new TournamentBeatmapPanel(beatmap) + Add(new TournamentBeatmapPanel(new TournamentBeatmap(beatmap)) { Anchor = Anchor.Centre, Origin = Anchor.Centre diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index 05989566c3..eb8b0dfbe6 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -25,16 +27,16 @@ namespace osu.Game.Tournament.Tests.Components Colour = "f2ca34" }; - private readonly APIUser redUser = new APIUser + private readonly TournamentUser redUser = new TournamentUser { Username = "BanchoBot", - Id = 3, + OnlineID = 3, }; - private readonly APIUser blueUser = new APIUser + private readonly TournamentUser blueUser = new TournamentUser { Username = "Zallius", - Id = 4, + OnlineID = 4, }; [Cached] @@ -57,11 +59,11 @@ namespace osu.Game.Tournament.Tests.Components { Team1 = { - Value = new TournamentTeam { Players = new BindableList { redUser } } + Value = new TournamentTeam { Players = new BindableList { redUser } } }, Team2 = { - Value = new TournamentTeam { Players = new BindableList { blueUser } } + Value = new TournamentTeam { Players = new BindableList { blueUser } } } }; @@ -80,19 +82,19 @@ namespace osu.Game.Tournament.Tests.Components AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { - Sender = redUser, + Sender = redUser.ToAPIUser(), Content = "I am team red." })); AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { - Sender = redUser, + Sender = redUser.ToAPIUser(), Content = "I plan to win!" })); AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(nextMessageId()) { - Sender = blueUser, + Sender = blueUser.ToAPIUser(), Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand." })); diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 9feef36a02..263617ddf7 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,6 +11,7 @@ using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tournament.Components; +using osu.Game.Tournament.Models; using osuTK; namespace osu.Game.Tournament.Tests.Components @@ -51,7 +54,7 @@ namespace osu.Game.Tournament.Tests.Components foreach (var mod in mods) { - fillFlow.Add(new TournamentBeatmapPanel(beatmap, mod.Acronym) + fillFlow.Add(new TournamentBeatmapPanel(new TournamentBeatmap(beatmap), mod.Acronym) { Anchor = Anchor.Centre, Origin = Anchor.Centre diff --git a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs index 26fb03bed4..d314f40c30 100644 --- a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs index e5c539bbf1..ad776622be 100644 --- a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Threading.Tasks; diff --git a/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs b/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs index 80cc9be5c1..1bbbcc3661 100644 --- a/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/IPCLocationTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs index 8bdf909af3..f1e0966293 100644 --- a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using NUnit.Framework; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs b/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs index bf99f69b2a..8dc0946432 100644 --- a/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/TournamentHostTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using System.Threading.Tasks; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs index 0e38c777ba..e0c6aaf834 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs index 6879a71f1d..842324d03d 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index bceb3e6b74..7aade4fb82 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs index c4c100d506..1f817a1b22 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index f732c5582b..e0f91cc359 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs index 5c2b59df3a..656663ece7 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs index bd1bacd549..6061314796 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs index 2722021216..94321e708f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Editors; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs index a18e73e38f..2581ed4b7e 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs index 70b260c84c..9070590b15 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Tournament.Screens.Setup; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs index 8c43e25416..44e7c48887 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Tournament.Screens.Showcase; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs index b422227788..27e5c59600 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tournament.Screens.Setup; namespace osu.Game.Tournament.Tests.Screens diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs index fc6574ec8a..b38430ece5 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index e89aac73fa..fccc09c14e 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index d07cc4c431..3b48c2eee5 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs index 53591da07b..e961a3c670 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs index 50bdcd86c5..1adbe07709 100644 --- a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; diff --git a/osu.Game.Tournament.Tests/TournamentTestRunner.cs b/osu.Game.Tournament.Tests/TournamentTestRunner.cs index 229ab41a1e..f95fcbf487 100644 --- a/osu.Game.Tournament.Tests/TournamentTestRunner.cs +++ b/osu.Game.Tournament.Tests/TournamentTestRunner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Platform; diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 8c05b4e915..b440034f34 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -1,20 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.IO; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; -using osu.Game.Users; -using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tournament.Tests { @@ -121,11 +121,11 @@ namespace osu.Game.Tournament.Tests }, Players = { - new APIUser { Username = "Hello", Statistics = new UserStatistics { GlobalRank = 12 } }, - new APIUser { Username = "Hello", Statistics = new UserStatistics { GlobalRank = 16 } }, - new APIUser { Username = "Hello", Statistics = new UserStatistics { GlobalRank = 20 } }, - new APIUser { Username = "Hello", Statistics = new UserStatistics { GlobalRank = 24 } }, - new APIUser { Username = "Hello", Statistics = new UserStatistics { GlobalRank = 30 } }, + new TournamentUser { Username = "Hello", Rank = 12 }, + new TournamentUser { Username = "Hello", Rank = 16 }, + new TournamentUser { Username = "Hello", Rank = 20 }, + new TournamentUser { Username = "Hello", Rank = 24 }, + new TournamentUser { Username = "Hello", Rank = 30 }, } } }, @@ -138,11 +138,11 @@ namespace osu.Game.Tournament.Tests FullName = { Value = "United States" }, Players = { - new APIUser { Username = "Hello" }, - new APIUser { Username = "Hello" }, - new APIUser { Username = "Hello" }, - new APIUser { Username = "Hello" }, - new APIUser { Username = "Hello" }, + new TournamentUser { Username = "Hello" }, + new TournamentUser { Username = "Hello" }, + new TournamentUser { Username = "Hello" }, + new TournamentUser { Username = "Hello" }, + new TournamentUser { Username = "Hello" }, } } }, @@ -152,10 +152,10 @@ namespace osu.Game.Tournament.Tests } }; - public static APIBeatmap CreateSampleBeatmap() => - new APIBeatmap + public static TournamentBeatmap CreateSampleBeatmap() => + new TournamentBeatmap { - BeatmapSet = new APIBeatmapSet + Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist", diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 6fd53d923b..5512b26863 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -4,7 +4,6 @@ osu.Game.Tournament.Tests.TournamentTestRunner - diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs index ef8c8767e0..f43d494d5a 100644 --- a/osu.Game.Tournament/Components/ControlPanel.cs +++ b/osu.Game.Tournament/Components/ControlPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index 2237e389d7..76d12a6b03 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; @@ -28,7 +30,7 @@ namespace osu.Game.Tournament.Components { base.Current = new Bindable(string.Empty); - ((OsuTextBox)Control).OnCommit += (sender, newText) => + ((OsuTextBox)Control).OnCommit += (sender, _) => { try { diff --git a/osu.Game.Tournament/Components/DrawableTeamFlag.cs b/osu.Game.Tournament/Components/DrawableTeamFlag.cs index 75991a1ab8..348fd8cd76 100644 --- a/osu.Game.Tournament/Components/DrawableTeamFlag.cs +++ b/osu.Game.Tournament/Components/DrawableTeamFlag.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -32,7 +34,7 @@ namespace osu.Game.Tournament.Components { if (team == null) return; - Size = new Vector2(75, 50); + Size = new Vector2(75, 54); Masking = true; CornerRadius = 5; Child = flagSprite = new Sprite @@ -43,7 +45,7 @@ namespace osu.Game.Tournament.Components FillMode = FillMode.Fill }; - (flag = team.FlagName.GetBoundCopy()).BindValueChanged(acronym => flagSprite.Texture = textures.Get($@"Flags/{team.FlagName}"), true); + (flag = team.FlagName.GetBoundCopy()).BindValueChanged(_ => flagSprite.Texture = textures.Get($@"Flags/{team.FlagName}"), true); } } } diff --git a/osu.Game.Tournament/Components/DrawableTeamHeader.cs b/osu.Game.Tournament/Components/DrawableTeamHeader.cs index 3d9e8a6e00..ceaf8d5e6e 100644 --- a/osu.Game.Tournament/Components/DrawableTeamHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tournament.Models; using osuTK; diff --git a/osu.Game.Tournament/Components/DrawableTeamTitle.cs b/osu.Game.Tournament/Components/DrawableTeamTitle.cs index 6732eb152f..e64e08a921 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitle.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -25,7 +27,7 @@ namespace osu.Game.Tournament.Components { if (team == null) return; - (acronym = team.Acronym.GetBoundCopy()).BindValueChanged(acronym => Text.Text = team?.FullName.Value ?? string.Empty, true); + (acronym = team.Acronym.GetBoundCopy()).BindValueChanged(_ => Text.Text = team?.FullName.Value ?? string.Empty, true); } } } diff --git a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs index ceffe3d315..dbc9fa7f16 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs index 4d9afc23ac..0bb35d534c 100644 --- a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs +++ b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; @@ -54,7 +55,7 @@ namespace osu.Game.Tournament.Components }, }; - TournamentSpriteText createPlayerText(APIUser p) => + TournamentSpriteText createPlayerText(TournamentUser p) => new TournamentSpriteText { Text = p.Username, diff --git a/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs b/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs index 3f5ab42fd7..9f5b825e30 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs b/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs index 99d914fed4..67eeee7de4 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs index 367e447947..eb1dde21e7 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -36,7 +38,7 @@ namespace osu.Game.Tournament.Components { if (Team == null) return; - (acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true); + (acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(_ => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true); } } } diff --git a/osu.Game.Tournament/Components/IPCErrorDialog.cs b/osu.Game.Tournament/Components/IPCErrorDialog.cs index dc039cd3bc..a32e01fb48 100644 --- a/osu.Game.Tournament/Components/IPCErrorDialog.cs +++ b/osu.Game.Tournament/Components/IPCErrorDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game.Tournament/Components/RoundDisplay.cs b/osu.Game.Tournament/Components/RoundDisplay.cs index c0002e6804..98ef09aa58 100644 --- a/osu.Game.Tournament/Components/RoundDisplay.cs +++ b/osu.Game.Tournament/Components/RoundDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs index a45582a7c0..a9056166be 100644 --- a/osu.Game.Tournament/Components/SongBar.cs +++ b/osu.Game.Tournament/Components/SongBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -12,9 +14,9 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Extensions; using osu.Game.Graphics; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Screens.Menu; +using osu.Game.Tournament.Models; using osuTK; using osuTK.Graphics; @@ -22,14 +24,14 @@ namespace osu.Game.Tournament.Components { public class SongBar : CompositeDrawable { - private APIBeatmap beatmap; + private TournamentBeatmap beatmap; public const float HEIGHT = 145 / 2f; [Resolved] private IBindable ruleset { get; set; } - public APIBeatmap Beatmap + public TournamentBeatmap Beatmap { set { diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index b064d3dd79..462743cc3d 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Specialized; using System.Linq; @@ -12,7 +14,6 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Models; using osuTK.Graphics; @@ -20,7 +21,7 @@ namespace osu.Game.Tournament.Components { public class TournamentBeatmapPanel : CompositeDrawable { - public readonly APIBeatmap Beatmap; + public readonly TournamentBeatmap Beatmap; private readonly string mod; @@ -29,7 +30,7 @@ namespace osu.Game.Tournament.Components private readonly Bindable currentMatch = new Bindable(); private Box flash; - public TournamentBeatmapPanel(APIBeatmap beatmap, string mod = null) + public TournamentBeatmapPanel(TournamentBeatmap beatmap, string mod = null) { if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); @@ -59,7 +60,7 @@ namespace osu.Game.Tournament.Components { RelativeSizeAxes = Axes.Both, Colour = OsuColour.Gray(0.5f), - OnlineInfo = Beatmap.BeatmapSet, + OnlineInfo = Beatmap, }, new FillFlowContainer { diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index c30250c86a..6a8e4aa951 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Components/TournamentModIcon.cs b/osu.Game.Tournament/Components/TournamentModIcon.cs index 57a0390ac2..6697a993c3 100644 --- a/osu.Game.Tournament/Components/TournamentModIcon.cs +++ b/osu.Game.Tournament/Components/TournamentModIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs b/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs index d92b9eb605..b088670caa 100644 --- a/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs +++ b/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -10,7 +12,8 @@ namespace osu.Game.Tournament.Components { public class TournamentSpriteTextWithBackground : CompositeDrawable { - protected readonly TournamentSpriteText Text; + public readonly TournamentSpriteText Text; + protected readonly Box Background; public TournamentSpriteTextWithBackground(string text = "") diff --git a/osu.Game.Tournament/Components/TourneyVideo.cs b/osu.Game.Tournament/Components/TourneyVideo.cs index 2709580385..2e79998e66 100644 --- a/osu.Game.Tournament/Components/TourneyVideo.cs +++ b/osu.Game.Tournament/Components/TourneyVideo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -20,6 +22,8 @@ namespace osu.Game.Tournament.Components private Video video; private ManualClock manualClock; + public bool VideoAvailable => video != null; + public TourneyVideo(string filename, bool drawFallbackGradient = false) { this.filename = filename; diff --git a/osu.Game.Tournament/Configuration/TournamentStorageManager.cs b/osu.Game.Tournament/Configuration/TournamentStorageManager.cs index e3d0a9e75c..0b9a556296 100644 --- a/osu.Game.Tournament/Configuration/TournamentStorageManager.cs +++ b/osu.Game.Tournament/Configuration/TournamentStorageManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/CountryExtensions.cs b/osu.Game.Tournament/CountryExtensions.cs new file mode 100644 index 0000000000..f2a583c8a5 --- /dev/null +++ b/osu.Game.Tournament/CountryExtensions.cs @@ -0,0 +1,770 @@ +// Copyright (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; + +namespace osu.Game.Tournament +{ + public static class CountryExtensions + { + public static string GetAcronym(this CountryCode country) + { + switch (country) + { + case CountryCode.BD: + return "BGD"; + + case CountryCode.BE: + return "BEL"; + + case CountryCode.BF: + return "BFA"; + + case CountryCode.BG: + return "BGR"; + + case CountryCode.BA: + return "BIH"; + + case CountryCode.BB: + return "BRB"; + + case CountryCode.WF: + return "WLF"; + + case CountryCode.BL: + return "BLM"; + + case CountryCode.BM: + return "BMU"; + + case CountryCode.BN: + return "BRN"; + + case CountryCode.BO: + return "BOL"; + + case CountryCode.BH: + return "BHR"; + + case CountryCode.BI: + return "BDI"; + + case CountryCode.BJ: + return "BEN"; + + case CountryCode.BT: + return "BTN"; + + case CountryCode.JM: + return "JAM"; + + case CountryCode.BV: + return "BVT"; + + case CountryCode.BW: + return "BWA"; + + case CountryCode.WS: + return "WSM"; + + case CountryCode.BQ: + return "BES"; + + case CountryCode.BR: + return "BRA"; + + case CountryCode.BS: + return "BHS"; + + case CountryCode.JE: + return "JEY"; + + case CountryCode.BY: + return "BLR"; + + case CountryCode.BZ: + return "BLZ"; + + case CountryCode.RU: + return "RUS"; + + case CountryCode.RW: + return "RWA"; + + case CountryCode.RS: + return "SRB"; + + case CountryCode.TL: + return "TLS"; + + case CountryCode.RE: + return "REU"; + + case CountryCode.TM: + return "TKM"; + + case CountryCode.TJ: + return "TJK"; + + case CountryCode.RO: + return "ROU"; + + case CountryCode.TK: + return "TKL"; + + case CountryCode.GW: + return "GNB"; + + case CountryCode.GU: + return "GUM"; + + case CountryCode.GT: + return "GTM"; + + case CountryCode.GS: + return "SGS"; + + case CountryCode.GR: + return "GRC"; + + case CountryCode.GQ: + return "GNQ"; + + case CountryCode.GP: + return "GLP"; + + case CountryCode.JP: + return "JPN"; + + case CountryCode.GY: + return "GUY"; + + case CountryCode.GG: + return "GGY"; + + case CountryCode.GF: + return "GUF"; + + case CountryCode.GE: + return "GEO"; + + case CountryCode.GD: + return "GRD"; + + case CountryCode.GB: + return "GBR"; + + case CountryCode.GA: + return "GAB"; + + case CountryCode.SV: + return "SLV"; + + case CountryCode.GN: + return "GIN"; + + case CountryCode.GM: + return "GMB"; + + case CountryCode.GL: + return "GRL"; + + case CountryCode.GI: + return "GIB"; + + case CountryCode.GH: + return "GHA"; + + case CountryCode.OM: + return "OMN"; + + case CountryCode.TN: + return "TUN"; + + case CountryCode.JO: + return "JOR"; + + case CountryCode.HR: + return "HRV"; + + case CountryCode.HT: + return "HTI"; + + case CountryCode.HU: + return "HUN"; + + case CountryCode.HK: + return "HKG"; + + case CountryCode.HN: + return "HND"; + + case CountryCode.HM: + return "HMD"; + + case CountryCode.VE: + return "VEN"; + + case CountryCode.PR: + return "PRI"; + + case CountryCode.PS: + return "PSE"; + + case CountryCode.PW: + return "PLW"; + + case CountryCode.PT: + return "PRT"; + + case CountryCode.SJ: + return "SJM"; + + case CountryCode.PY: + return "PRY"; + + case CountryCode.IQ: + return "IRQ"; + + case CountryCode.PA: + return "PAN"; + + case CountryCode.PF: + return "PYF"; + + case CountryCode.PG: + return "PNG"; + + case CountryCode.PE: + return "PER"; + + case CountryCode.PK: + return "PAK"; + + case CountryCode.PH: + return "PHL"; + + case CountryCode.PN: + return "PCN"; + + case CountryCode.PL: + return "POL"; + + case CountryCode.PM: + return "SPM"; + + case CountryCode.ZM: + return "ZMB"; + + case CountryCode.EH: + return "ESH"; + + case CountryCode.EE: + return "EST"; + + case CountryCode.EG: + return "EGY"; + + case CountryCode.ZA: + return "ZAF"; + + case CountryCode.EC: + return "ECU"; + + case CountryCode.IT: + return "ITA"; + + case CountryCode.VN: + return "VNM"; + + case CountryCode.SB: + return "SLB"; + + case CountryCode.ET: + return "ETH"; + + case CountryCode.SO: + return "SOM"; + + case CountryCode.ZW: + return "ZWE"; + + case CountryCode.SA: + return "SAU"; + + case CountryCode.ES: + return "ESP"; + + case CountryCode.ER: + return "ERI"; + + case CountryCode.ME: + return "MNE"; + + case CountryCode.MD: + return "MDA"; + + case CountryCode.MG: + return "MDG"; + + case CountryCode.MF: + return "MAF"; + + case CountryCode.MA: + return "MAR"; + + case CountryCode.MC: + return "MCO"; + + case CountryCode.UZ: + return "UZB"; + + case CountryCode.MM: + return "MMR"; + + case CountryCode.ML: + return "MLI"; + + case CountryCode.MO: + return "MAC"; + + case CountryCode.MN: + return "MNG"; + + case CountryCode.MH: + return "MHL"; + + case CountryCode.MK: + return "MKD"; + + case CountryCode.MU: + return "MUS"; + + case CountryCode.MT: + return "MLT"; + + case CountryCode.MW: + return "MWI"; + + case CountryCode.MV: + return "MDV"; + + case CountryCode.MQ: + return "MTQ"; + + case CountryCode.MP: + return "MNP"; + + case CountryCode.MS: + return "MSR"; + + case CountryCode.MR: + return "MRT"; + + case CountryCode.IM: + return "IMN"; + + case CountryCode.UG: + return "UGA"; + + case CountryCode.TZ: + return "TZA"; + + case CountryCode.MY: + return "MYS"; + + case CountryCode.MX: + return "MEX"; + + case CountryCode.IL: + return "ISR"; + + case CountryCode.FR: + return "FRA"; + + case CountryCode.IO: + return "IOT"; + + case CountryCode.SH: + return "SHN"; + + case CountryCode.FI: + return "FIN"; + + case CountryCode.FJ: + return "FJI"; + + case CountryCode.FK: + return "FLK"; + + case CountryCode.FM: + return "FSM"; + + case CountryCode.FO: + return "FRO"; + + case CountryCode.NI: + return "NIC"; + + case CountryCode.NL: + return "NLD"; + + case CountryCode.NO: + return "NOR"; + + case CountryCode.NA: + return "NAM"; + + case CountryCode.VU: + return "VUT"; + + case CountryCode.NC: + return "NCL"; + + case CountryCode.NE: + return "NER"; + + case CountryCode.NF: + return "NFK"; + + case CountryCode.NG: + return "NGA"; + + case CountryCode.NZ: + return "NZL"; + + case CountryCode.NP: + return "NPL"; + + case CountryCode.NR: + return "NRU"; + + case CountryCode.NU: + return "NIU"; + + case CountryCode.CK: + return "COK"; + + case CountryCode.XK: + return "XKX"; + + case CountryCode.CI: + return "CIV"; + + case CountryCode.CH: + return "CHE"; + + case CountryCode.CO: + return "COL"; + + case CountryCode.CN: + return "CHN"; + + case CountryCode.CM: + return "CMR"; + + case CountryCode.CL: + return "CHL"; + + case CountryCode.CC: + return "CCK"; + + case CountryCode.CA: + return "CAN"; + + case CountryCode.CG: + return "COG"; + + case CountryCode.CF: + return "CAF"; + + case CountryCode.CD: + return "COD"; + + case CountryCode.CZ: + return "CZE"; + + case CountryCode.CY: + return "CYP"; + + case CountryCode.CX: + return "CXR"; + + case CountryCode.CR: + return "CRI"; + + case CountryCode.CW: + return "CUW"; + + case CountryCode.CV: + return "CPV"; + + case CountryCode.CU: + return "CUB"; + + case CountryCode.SZ: + return "SWZ"; + + case CountryCode.SY: + return "SYR"; + + case CountryCode.SX: + return "SXM"; + + case CountryCode.KG: + return "KGZ"; + + case CountryCode.KE: + return "KEN"; + + case CountryCode.SS: + return "SSD"; + + case CountryCode.SR: + return "SUR"; + + case CountryCode.KI: + return "KIR"; + + case CountryCode.KH: + return "KHM"; + + case CountryCode.KN: + return "KNA"; + + case CountryCode.KM: + return "COM"; + + case CountryCode.ST: + return "STP"; + + case CountryCode.SK: + return "SVK"; + + case CountryCode.KR: + return "KOR"; + + case CountryCode.SI: + return "SVN"; + + case CountryCode.KP: + return "PRK"; + + case CountryCode.KW: + return "KWT"; + + case CountryCode.SN: + return "SEN"; + + case CountryCode.SM: + return "SMR"; + + case CountryCode.SL: + return "SLE"; + + case CountryCode.SC: + return "SYC"; + + case CountryCode.KZ: + return "KAZ"; + + case CountryCode.KY: + return "CYM"; + + case CountryCode.SG: + return "SGP"; + + case CountryCode.SE: + return "SWE"; + + case CountryCode.SD: + return "SDN"; + + case CountryCode.DO: + return "DOM"; + + case CountryCode.DM: + return "DMA"; + + case CountryCode.DJ: + return "DJI"; + + case CountryCode.DK: + return "DNK"; + + case CountryCode.VG: + return "VGB"; + + case CountryCode.DE: + return "DEU"; + + case CountryCode.YE: + return "YEM"; + + case CountryCode.DZ: + return "DZA"; + + case CountryCode.US: + return "USA"; + + case CountryCode.UY: + return "URY"; + + case CountryCode.YT: + return "MYT"; + + case CountryCode.UM: + return "UMI"; + + case CountryCode.LB: + return "LBN"; + + case CountryCode.LC: + return "LCA"; + + case CountryCode.LA: + return "LAO"; + + case CountryCode.TV: + return "TUV"; + + case CountryCode.TW: + return "TWN"; + + case CountryCode.TT: + return "TTO"; + + case CountryCode.TR: + return "TUR"; + + case CountryCode.LK: + return "LKA"; + + case CountryCode.LI: + return "LIE"; + + case CountryCode.LV: + return "LVA"; + + case CountryCode.TO: + return "TON"; + + case CountryCode.LT: + return "LTU"; + + case CountryCode.LU: + return "LUX"; + + case CountryCode.LR: + return "LBR"; + + case CountryCode.LS: + return "LSO"; + + case CountryCode.TH: + return "THA"; + + case CountryCode.TF: + return "ATF"; + + case CountryCode.TG: + return "TGO"; + + case CountryCode.TD: + return "TCD"; + + case CountryCode.TC: + return "TCA"; + + case CountryCode.LY: + return "LBY"; + + case CountryCode.VA: + return "VAT"; + + case CountryCode.VC: + return "VCT"; + + case CountryCode.AE: + return "ARE"; + + case CountryCode.AD: + return "AND"; + + case CountryCode.AG: + return "ATG"; + + case CountryCode.AF: + return "AFG"; + + case CountryCode.AI: + return "AIA"; + + case CountryCode.VI: + return "VIR"; + + case CountryCode.IS: + return "ISL"; + + case CountryCode.IR: + return "IRN"; + + case CountryCode.AM: + return "ARM"; + + case CountryCode.AL: + return "ALB"; + + case CountryCode.AO: + return "AGO"; + + case CountryCode.AQ: + return "ATA"; + + case CountryCode.AS: + return "ASM"; + + case CountryCode.AR: + return "ARG"; + + case CountryCode.AU: + return "AUS"; + + case CountryCode.AT: + return "AUT"; + + case CountryCode.AW: + return "ABW"; + + case CountryCode.IN: + return "IND"; + + case CountryCode.AX: + return "ALA"; + + case CountryCode.AZ: + return "AZE"; + + case CountryCode.IE: + return "IRL"; + + case CountryCode.ID: + return "IDN"; + + case CountryCode.UA: + return "UKR"; + + case CountryCode.QA: + return "QAT"; + + case CountryCode.MZ: + return "MOZ"; + + default: + throw new ArgumentOutOfRangeException(nameof(country)); + } + } + } +} diff --git a/osu.Game.Tournament/IO/TournamentStorage.cs b/osu.Game.Tournament/IO/TournamentStorage.cs index b4859d0c91..bd52b6dfed 100644 --- a/osu.Game.Tournament/IO/TournamentStorage.cs +++ b/osu.Game.Tournament/IO/TournamentStorage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs b/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs index 964d03220d..ba584f1d3e 100644 --- a/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs +++ b/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Stores; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 5278d538d2..ad564c58c3 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -94,7 +96,7 @@ namespace osu.Game.Tournament.IPC else { beatmapLookupRequest = new GetBeatmapRequest(new APIBeatmap { OnlineID = beatmapId }); - beatmapLookupRequest.Success += b => Beatmap.Value = b; + beatmapLookupRequest.Success += b => Beatmap.Value = new TournamentBeatmap(b); API.Queue(beatmapLookupRequest); } } diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index fa7079b824..f438923803 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -1,16 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps.Legacy; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.IPC { public class MatchIPCInfo : Component { - public Bindable Beatmap { get; } = new Bindable(); + public Bindable Beatmap { get; } = new Bindable(); public Bindable Mods { get; } = new Bindable(); public Bindable State { get; } = new Bindable(); public Bindable ChatChannel { get; } = new Bindable(); diff --git a/osu.Game.Tournament/IPC/TourneyState.cs b/osu.Game.Tournament/IPC/TourneyState.cs index ef1c612a53..2c7253dc10 100644 --- a/osu.Game.Tournament/IPC/TourneyState.cs +++ b/osu.Game.Tournament/IPC/TourneyState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Tournament.IPC { public enum TourneyState diff --git a/osu.Game.Tournament/JsonPointConverter.cs b/osu.Game.Tournament/JsonPointConverter.cs index 32bbe2dc18..db48c36c99 100644 --- a/osu.Game.Tournament/JsonPointConverter.cs +++ b/osu.Game.Tournament/JsonPointConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Drawing; diff --git a/osu.Game.Tournament/Models/BeatmapChoice.cs b/osu.Game.Tournament/Models/BeatmapChoice.cs index 384b349b24..ddd4597722 100644 --- a/osu.Game.Tournament/Models/BeatmapChoice.cs +++ b/osu.Game.Tournament/Models/BeatmapChoice.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; using Newtonsoft.Json.Converters; diff --git a/osu.Game.Tournament/Models/LadderEditorInfo.cs b/osu.Game.Tournament/Models/LadderEditorInfo.cs index 70fd115e25..84ebeff3db 100644 --- a/osu.Game.Tournament/Models/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Models/LadderEditorInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; namespace osu.Game.Tournament.Models diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 7794019437..0f73b60774 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Tournament/Models/RoundBeatmap.cs b/osu.Game.Tournament/Models/RoundBeatmap.cs index 2fd79546f1..65ef77e53d 100644 --- a/osu.Game.Tournament/Models/RoundBeatmap.cs +++ b/osu.Game.Tournament/Models/RoundBeatmap.cs @@ -1,8 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; -using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.Models { @@ -12,6 +13,6 @@ namespace osu.Game.Tournament.Models public string Mods; [JsonProperty("BeatmapInfo")] - public APIBeatmap Beatmap; + public TournamentBeatmap Beatmap; } } diff --git a/osu.Game.Tournament/Models/SeedingBeatmap.cs b/osu.Game.Tournament/Models/SeedingBeatmap.cs index 26f3016ac8..fb0e20556c 100644 --- a/osu.Game.Tournament/Models/SeedingBeatmap.cs +++ b/osu.Game.Tournament/Models/SeedingBeatmap.cs @@ -3,7 +3,6 @@ using Newtonsoft.Json; using osu.Framework.Bindables; -using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.Models { @@ -12,7 +11,7 @@ namespace osu.Game.Tournament.Models public int ID; [JsonProperty("BeatmapInfo")] - public APIBeatmap Beatmap; + public TournamentBeatmap? Beatmap; public long Score; diff --git a/osu.Game.Tournament/Models/SeedingResult.cs b/osu.Game.Tournament/Models/SeedingResult.cs index d37c967762..71e52b3324 100644 --- a/osu.Game.Tournament/Models/SeedingResult.cs +++ b/osu.Game.Tournament/Models/SeedingResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Models/StableInfo.cs b/osu.Game.Tournament/Models/StableInfo.cs index c835b11a4d..1ae80d4596 100644 --- a/osu.Game.Tournament/Models/StableInfo.cs +++ b/osu.Game.Tournament/Models/StableInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using Newtonsoft.Json; diff --git a/osu.Game.Tournament/Models/TournamentBeatmap.cs b/osu.Game.Tournament/Models/TournamentBeatmap.cs new file mode 100644 index 0000000000..274fddc490 --- /dev/null +++ b/osu.Game.Tournament/Models/TournamentBeatmap.cs @@ -0,0 +1,99 @@ +// Copyright (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.ObjectExtensions; +using osu.Game.Beatmaps; +using osu.Game.Extensions; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; + +namespace osu.Game.Tournament.Models +{ + public class TournamentBeatmap : IBeatmapInfo, IBeatmapSetOnlineInfo + { + public int OnlineID { get; set; } + + public string DifficultyName { get; set; } = string.Empty; + + public double BPM { get; set; } + + public double Length { get; set; } + + public double StarRating { get; set; } + + public IBeatmapMetadataInfo Metadata { get; set; } = new BeatmapMetadata(); + + public IBeatmapDifficultyInfo Difficulty { get; set; } = new BeatmapDifficulty(); + + public BeatmapSetOnlineCovers Covers { get; set; } + + public TournamentBeatmap() + { + } + + public TournamentBeatmap(APIBeatmap beatmap) + { + OnlineID = beatmap.OnlineID; + DifficultyName = beatmap.DifficultyName; + BPM = beatmap.BPM; + Length = beatmap.Length; + StarRating = beatmap.StarRating; + Metadata = beatmap.Metadata; + Difficulty = beatmap.Difficulty; + Covers = beatmap.BeatmapSet.AsNonNull().Covers; + } + + public bool Equals(IBeatmapInfo? other) => other is TournamentBeatmap b && this.MatchesOnlineID(b); + + #region IBeatmapInfo/IBeatmapSetOnlineInfo explicit implementation + + IBeatmapSetInfo IBeatmapInfo.BeatmapSet => throw new NotImplementedException(); + + string IBeatmapSetOnlineInfo.Preview => throw new NotImplementedException(); + + double IBeatmapSetOnlineInfo.BPM => throw new NotImplementedException(); + + int IBeatmapSetOnlineInfo.PlayCount => throw new NotImplementedException(); + + int IBeatmapSetOnlineInfo.FavouriteCount => throw new NotImplementedException(); + + bool IBeatmapSetOnlineInfo.HasFavourited => throw new NotImplementedException(); + + BeatmapSetOnlineAvailability IBeatmapSetOnlineInfo.Availability => throw new NotImplementedException(); + + BeatmapSetOnlineGenre IBeatmapSetOnlineInfo.Genre => throw new NotImplementedException(); + + BeatmapSetOnlineLanguage IBeatmapSetOnlineInfo.Language => throw new NotImplementedException(); + + int? IBeatmapSetOnlineInfo.TrackId => throw new NotImplementedException(); + + int[] IBeatmapSetOnlineInfo.Ratings => throw new NotImplementedException(); + + BeatmapSetHypeStatus IBeatmapSetOnlineInfo.HypeStatus => throw new NotImplementedException(); + + BeatmapSetNominationStatus IBeatmapSetOnlineInfo.NominationStatus => throw new NotImplementedException(); + + string IBeatmapInfo.Hash => throw new NotImplementedException(); + + string IBeatmapInfo.MD5Hash => throw new NotImplementedException(); + + IRulesetInfo IBeatmapInfo.Ruleset => throw new NotImplementedException(); + + DateTimeOffset IBeatmapSetOnlineInfo.Submitted => throw new NotImplementedException(); + + DateTimeOffset? IBeatmapSetOnlineInfo.Ranked => throw new NotImplementedException(); + + DateTimeOffset? IBeatmapSetOnlineInfo.LastUpdated => throw new NotImplementedException(); + + BeatmapOnlineStatus IBeatmapSetOnlineInfo.Status => throw new NotImplementedException(); + + bool IBeatmapSetOnlineInfo.HasExplicitContent => throw new NotImplementedException(); + + bool IBeatmapSetOnlineInfo.HasVideo => throw new NotImplementedException(); + + bool IBeatmapSetOnlineInfo.HasStoryboard => throw new NotImplementedException(); + + #endregion + } +} diff --git a/osu.Game.Tournament/Models/TournamentMatch.cs b/osu.Game.Tournament/Models/TournamentMatch.cs index bdfb1728f3..2f72dc9257 100644 --- a/osu.Game.Tournament/Models/TournamentMatch.cs +++ b/osu.Game.Tournament/Models/TournamentMatch.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.ObjectModel; diff --git a/osu.Game.Tournament/Models/TournamentProgression.cs b/osu.Game.Tournament/Models/TournamentProgression.cs index 5575b4c29e..6c3ba1922a 100644 --- a/osu.Game.Tournament/Models/TournamentProgression.cs +++ b/osu.Game.Tournament/Models/TournamentProgression.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Tournament.Models diff --git a/osu.Game.Tournament/Models/TournamentRound.cs b/osu.Game.Tournament/Models/TournamentRound.cs index ab39605d07..480d6c37c3 100644 --- a/osu.Game.Tournament/Models/TournamentRound.cs +++ b/osu.Game.Tournament/Models/TournamentRound.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs index 24dee3b372..ac57f748da 100644 --- a/osu.Game.Tournament/Models/TournamentTeam.cs +++ b/osu.Game.Tournament/Models/TournamentTeam.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using Newtonsoft.Json; using osu.Framework.Bindables; -using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Tournament.Models { @@ -36,7 +37,7 @@ namespace osu.Game.Tournament.Models { get { - int[] ranks = Players.Select(p => p.Statistics?.GlobalRank) + int[] ranks = Players.Select(p => p.Rank) .Where(i => i.HasValue) .Select(i => i.Value) .ToArray(); @@ -57,7 +58,7 @@ namespace osu.Game.Tournament.Models }; [JsonProperty] - public BindableList Players { get; set; } = new BindableList(); + public BindableList Players { get; set; } = new BindableList(); public TournamentTeam() { @@ -65,14 +66,14 @@ namespace osu.Game.Tournament.Models { // use a sane default flag name based on acronym. if (val.OldValue.StartsWith(FlagName.Value, StringComparison.InvariantCultureIgnoreCase)) - FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpper() : string.Empty; + FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpperInvariant() : string.Empty; }; FullName.ValueChanged += val => { // use a sane acronym based on full name. if (val.OldValue.StartsWith(Acronym.Value, StringComparison.InvariantCultureIgnoreCase)) - Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpper() : string.Empty; + Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpperInvariant() : string.Empty; }; } diff --git a/osu.Game.Tournament/Models/TournamentUser.cs b/osu.Game.Tournament/Models/TournamentUser.cs new file mode 100644 index 0000000000..78ca014860 --- /dev/null +++ b/osu.Game.Tournament/Models/TournamentUser.cs @@ -0,0 +1,59 @@ +// Copyright (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.Game.Online.API.Requests.Responses; +using osu.Game.Users; + +namespace osu.Game.Tournament.Models +{ + /// + /// A tournament player user, containing simple information about the player. + /// + [Serializable] + public class TournamentUser : IUser + { + [JsonProperty(@"id")] + public int OnlineID { get; set; } + + public string Username { get; set; } = string.Empty; + + /// + /// The player's country. + /// + [JsonProperty("country_code")] + public CountryCode CountryCode { get; set; } + + /// + /// The player's global rank, or null if not available. + /// + public int? Rank { get; set; } + + /// + /// A URL to the player's profile cover. + /// + public string CoverUrl { get; set; } = string.Empty; + + public APIUser ToAPIUser() + { + var user = new APIUser + { + Id = OnlineID, + Username = Username, + CountryCode = CountryCode, + CoverUrl = CoverUrl, + }; + + user.Statistics = new UserStatistics + { + User = user, + GlobalRank = Rank + }; + + return user; + } + + bool IUser.IsBot => false; + } +} diff --git a/osu.Game.Tournament/Properties/AssemblyInfo.cs b/osu.Game.Tournament/Properties/AssemblyInfo.cs index 70e42bcafb..2eb8c3e1d6 100644 --- a/osu.Game.Tournament/Properties/AssemblyInfo.cs +++ b/osu.Game.Tournament/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Tournament/Resources/countries.json b/osu.Game.Tournament/Resources/countries.json deleted file mode 100644 index 7306a8bec5..0000000000 --- a/osu.Game.Tournament/Resources/countries.json +++ /dev/null @@ -1,1252 +0,0 @@ -[ - { - "FlagName": "BD", - "FullName": "Bangladesh", - "Acronym": "BGD" - }, - { - "FlagName": "BE", - "FullName": "Belgium", - "Acronym": "BEL" - }, - { - "FlagName": "BF", - "FullName": "Burkina Faso", - "Acronym": "BFA" - }, - { - "FlagName": "BG", - "FullName": "Bulgaria", - "Acronym": "BGR" - }, - { - "FlagName": "BA", - "FullName": "Bosnia and Herzegovina", - "Acronym": "BIH" - }, - { - "FlagName": "BB", - "FullName": "Barbados", - "Acronym": "BRB" - }, - { - "FlagName": "WF", - "FullName": "Wallis and Futuna", - "Acronym": "WLF" - }, - { - "FlagName": "BL", - "FullName": "Saint Barthelemy", - "Acronym": "BLM" - }, - { - "FlagName": "BM", - "FullName": "Bermuda", - "Acronym": "BMU" - }, - { - "FlagName": "BN", - "FullName": "Brunei", - "Acronym": "BRN" - }, - { - "FlagName": "BO", - "FullName": "Bolivia", - "Acronym": "BOL" - }, - { - "FlagName": "BH", - "FullName": "Bahrain", - "Acronym": "BHR" - }, - { - "FlagName": "BI", - "FullName": "Burundi", - "Acronym": "BDI" - }, - { - "FlagName": "BJ", - "FullName": "Benin", - "Acronym": "BEN" - }, - { - "FlagName": "BT", - "FullName": "Bhutan", - "Acronym": "BTN" - }, - { - "FlagName": "JM", - "FullName": "Jamaica", - "Acronym": "JAM" - }, - { - "FlagName": "BV", - "FullName": "Bouvet Island", - "Acronym": "BVT" - }, - { - "FlagName": "BW", - "FullName": "Botswana", - "Acronym": "BWA" - }, - { - "FlagName": "WS", - "FullName": "Samoa", - "Acronym": "WSM" - }, - { - "FlagName": "BQ", - "FullName": "Bonaire, Saint Eustatius and Saba", - "Acronym": "BES" - }, - { - "FlagName": "BR", - "FullName": "Brazil", - "Acronym": "BRA" - }, - { - "FlagName": "BS", - "FullName": "Bahamas", - "Acronym": "BHS" - }, - { - "FlagName": "JE", - "FullName": "Jersey", - "Acronym": "JEY" - }, - { - "FlagName": "BY", - "FullName": "Belarus", - "Acronym": "BLR" - }, - { - "FlagName": "BZ", - "FullName": "Belize", - "Acronym": "BLZ" - }, - { - "FlagName": "RU", - "FullName": "Russia", - "Acronym": "RUS" - }, - { - "FlagName": "RW", - "FullName": "Rwanda", - "Acronym": "RWA" - }, - { - "FlagName": "RS", - "FullName": "Serbia", - "Acronym": "SRB" - }, - { - "FlagName": "TL", - "FullName": "East Timor", - "Acronym": "TLS" - }, - { - "FlagName": "RE", - "FullName": "Reunion", - "Acronym": "REU" - }, - { - "FlagName": "TM", - "FullName": "Turkmenistan", - "Acronym": "TKM" - }, - { - "FlagName": "TJ", - "FullName": "Tajikistan", - "Acronym": "TJK" - }, - { - "FlagName": "RO", - "FullName": "Romania", - "Acronym": "ROU" - }, - { - "FlagName": "TK", - "FullName": "Tokelau", - "Acronym": "TKL" - }, - { - "FlagName": "GW", - "FullName": "Guinea-Bissau", - "Acronym": "GNB" - }, - { - "FlagName": "GU", - "FullName": "Guam", - "Acronym": "GUM" - }, - { - "FlagName": "GT", - "FullName": "Guatemala", - "Acronym": "GTM" - }, - { - "FlagName": "GS", - "FullName": "South Georgia and the South Sandwich Islands", - "Acronym": "SGS" - }, - { - "FlagName": "GR", - "FullName": "Greece", - "Acronym": "GRC" - }, - { - "FlagName": "GQ", - "FullName": "Equatorial Guinea", - "Acronym": "GNQ" - }, - { - "FlagName": "GP", - "FullName": "Guadeloupe", - "Acronym": "GLP" - }, - { - "FlagName": "JP", - "FullName": "Japan", - "Acronym": "JPN" - }, - { - "FlagName": "GY", - "FullName": "Guyana", - "Acronym": "GUY" - }, - { - "FlagName": "GG", - "FullName": "Guernsey", - "Acronym": "GGY" - }, - { - "FlagName": "GF", - "FullName": "French Guiana", - "Acronym": "GUF" - }, - { - "FlagName": "GE", - "FullName": "Georgia", - "Acronym": "GEO" - }, - { - "FlagName": "GD", - "FullName": "Grenada", - "Acronym": "GRD" - }, - { - "FlagName": "GB", - "FullName": "United Kingdom", - "Acronym": "GBR" - }, - { - "FlagName": "GA", - "FullName": "Gabon", - "Acronym": "GAB" - }, - { - "FlagName": "SV", - "FullName": "El Salvador", - "Acronym": "SLV" - }, - { - "FlagName": "GN", - "FullName": "Guinea", - "Acronym": "GIN" - }, - { - "FlagName": "GM", - "FullName": "Gambia", - "Acronym": "GMB" - }, - { - "FlagName": "GL", - "FullName": "Greenland", - "Acronym": "GRL" - }, - { - "FlagName": "GI", - "FullName": "Gibraltar", - "Acronym": "GIB" - }, - { - "FlagName": "GH", - "FullName": "Ghana", - "Acronym": "GHA" - }, - { - "FlagName": "OM", - "FullName": "Oman", - "Acronym": "OMN" - }, - { - "FlagName": "TN", - "FullName": "Tunisia", - "Acronym": "TUN" - }, - { - "FlagName": "JO", - "FullName": "Jordan", - "Acronym": "JOR" - }, - { - "FlagName": "HR", - "FullName": "Croatia", - "Acronym": "HRV" - }, - { - "FlagName": "HT", - "FullName": "Haiti", - "Acronym": "HTI" - }, - { - "FlagName": "HU", - "FullName": "Hungary", - "Acronym": "HUN" - }, - { - "FlagName": "HK", - "FullName": "Hong Kong", - "Acronym": "HKG" - }, - { - "FlagName": "HN", - "FullName": "Honduras", - "Acronym": "HND" - }, - { - "FlagName": "HM", - "FullName": "Heard Island and McDonald Islands", - "Acronym": "HMD" - }, - { - "FlagName": "VE", - "FullName": "Venezuela", - "Acronym": "VEN" - }, - { - "FlagName": "PR", - "FullName": "Puerto Rico", - "Acronym": "PRI" - }, - { - "FlagName": "PS", - "FullName": "Palestinian Territory", - "Acronym": "PSE" - }, - { - "FlagName": "PW", - "FullName": "Palau", - "Acronym": "PLW" - }, - { - "FlagName": "PT", - "FullName": "Portugal", - "Acronym": "PRT" - }, - { - "FlagName": "SJ", - "FullName": "Svalbard and Jan Mayen", - "Acronym": "SJM" - }, - { - "FlagName": "PY", - "FullName": "Paraguay", - "Acronym": "PRY" - }, - { - "FlagName": "IQ", - "FullName": "Iraq", - "Acronym": "IRQ" - }, - { - "FlagName": "PA", - "FullName": "Panama", - "Acronym": "PAN" - }, - { - "FlagName": "PF", - "FullName": "French Polynesia", - "Acronym": "PYF" - }, - { - "FlagName": "PG", - "FullName": "Papua New Guinea", - "Acronym": "PNG" - }, - { - "FlagName": "PE", - "FullName": "Peru", - "Acronym": "PER" - }, - { - "FlagName": "PK", - "FullName": "Pakistan", - "Acronym": "PAK" - }, - { - "FlagName": "PH", - "FullName": "Philippines", - "Acronym": "PHL" - }, - { - "FlagName": "PN", - "FullName": "Pitcairn", - "Acronym": "PCN" - }, - { - "FlagName": "PL", - "FullName": "Poland", - "Acronym": "POL" - }, - { - "FlagName": "PM", - "FullName": "Saint Pierre and Miquelon", - "Acronym": "SPM" - }, - { - "FlagName": "ZM", - "FullName": "Zambia", - "Acronym": "ZMB" - }, - { - "FlagName": "EH", - "FullName": "Western Sahara", - "Acronym": "ESH" - }, - { - "FlagName": "EE", - "FullName": "Estonia", - "Acronym": "EST" - }, - { - "FlagName": "EG", - "FullName": "Egypt", - "Acronym": "EGY" - }, - { - "FlagName": "ZA", - "FullName": "South Africa", - "Acronym": "ZAF" - }, - { - "FlagName": "EC", - "FullName": "Ecuador", - "Acronym": "ECU" - }, - { - "FlagName": "IT", - "FullName": "Italy", - "Acronym": "ITA" - }, - { - "FlagName": "VN", - "FullName": "Vietnam", - "Acronym": "VNM" - }, - { - "FlagName": "SB", - "FullName": "Solomon Islands", - "Acronym": "SLB" - }, - { - "FlagName": "ET", - "FullName": "Ethiopia", - "Acronym": "ETH" - }, - { - "FlagName": "SO", - "FullName": "Somalia", - "Acronym": "SOM" - }, - { - "FlagName": "ZW", - "FullName": "Zimbabwe", - "Acronym": "ZWE" - }, - { - "FlagName": "SA", - "FullName": "Saudi Arabia", - "Acronym": "SAU" - }, - { - "FlagName": "ES", - "FullName": "Spain", - "Acronym": "ESP" - }, - { - "FlagName": "ER", - "FullName": "Eritrea", - "Acronym": "ERI" - }, - { - "FlagName": "ME", - "FullName": "Montenegro", - "Acronym": "MNE" - }, - { - "FlagName": "MD", - "FullName": "Moldova", - "Acronym": "MDA" - }, - { - "FlagName": "MG", - "FullName": "Madagascar", - "Acronym": "MDG" - }, - { - "FlagName": "MF", - "FullName": "Saint Martin", - "Acronym": "MAF" - }, - { - "FlagName": "MA", - "FullName": "Morocco", - "Acronym": "MAR" - }, - { - "FlagName": "MC", - "FullName": "Monaco", - "Acronym": "MCO" - }, - { - "FlagName": "UZ", - "FullName": "Uzbekistan", - "Acronym": "UZB" - }, - { - "FlagName": "MM", - "FullName": "Myanmar", - "Acronym": "MMR" - }, - { - "FlagName": "ML", - "FullName": "Mali", - "Acronym": "MLI" - }, - { - "FlagName": "MO", - "FullName": "Macao", - "Acronym": "MAC" - }, - { - "FlagName": "MN", - "FullName": "Mongolia", - "Acronym": "MNG" - }, - { - "FlagName": "MH", - "FullName": "Marshall Islands", - "Acronym": "MHL" - }, - { - "FlagName": "MK", - "FullName": "North Macedonia", - "Acronym": "MKD" - }, - { - "FlagName": "MU", - "FullName": "Mauritius", - "Acronym": "MUS" - }, - { - "FlagName": "MT", - "FullName": "Malta", - "Acronym": "MLT" - }, - { - "FlagName": "MW", - "FullName": "Malawi", - "Acronym": "MWI" - }, - { - "FlagName": "MV", - "FullName": "Maldives", - "Acronym": "MDV" - }, - { - "FlagName": "MQ", - "FullName": "Martinique", - "Acronym": "MTQ" - }, - { - "FlagName": "MP", - "FullName": "Northern Mariana Islands", - "Acronym": "MNP" - }, - { - "FlagName": "MS", - "FullName": "Montserrat", - "Acronym": "MSR" - }, - { - "FlagName": "MR", - "FullName": "Mauritania", - "Acronym": "MRT" - }, - { - "FlagName": "IM", - "FullName": "Isle of Man", - "Acronym": "IMN" - }, - { - "FlagName": "UG", - "FullName": "Uganda", - "Acronym": "UGA" - }, - { - "FlagName": "TZ", - "FullName": "Tanzania", - "Acronym": "TZA" - }, - { - "FlagName": "MY", - "FullName": "Malaysia", - "Acronym": "MYS" - }, - { - "FlagName": "MX", - "FullName": "Mexico", - "Acronym": "MEX" - }, - { - "FlagName": "IL", - "FullName": "Israel", - "Acronym": "ISR" - }, - { - "FlagName": "FR", - "FullName": "France", - "Acronym": "FRA" - }, - { - "FlagName": "IO", - "FullName": "British Indian Ocean Territory", - "Acronym": "IOT" - }, - { - "FlagName": "SH", - "FullName": "Saint Helena", - "Acronym": "SHN" - }, - { - "FlagName": "FI", - "FullName": "Finland", - "Acronym": "FIN" - }, - { - "FlagName": "FJ", - "FullName": "Fiji", - "Acronym": "FJI" - }, - { - "FlagName": "FK", - "FullName": "Falkland Islands", - "Acronym": "FLK" - }, - { - "FlagName": "FM", - "FullName": "Micronesia", - "Acronym": "FSM" - }, - { - "FlagName": "FO", - "FullName": "Faroe Islands", - "Acronym": "FRO" - }, - { - "FlagName": "NI", - "FullName": "Nicaragua", - "Acronym": "NIC" - }, - { - "FlagName": "NL", - "FullName": "Netherlands", - "Acronym": "NLD" - }, - { - "FlagName": "NO", - "FullName": "Norway", - "Acronym": "NOR" - }, - { - "FlagName": "NA", - "FullName": "Namibia", - "Acronym": "NAM" - }, - { - "FlagName": "VU", - "FullName": "Vanuatu", - "Acronym": "VUT" - }, - { - "FlagName": "NC", - "FullName": "New Caledonia", - "Acronym": "NCL" - }, - { - "FlagName": "NE", - "FullName": "Niger", - "Acronym": "NER" - }, - { - "FlagName": "NF", - "FullName": "Norfolk Island", - "Acronym": "NFK" - }, - { - "FlagName": "NG", - "FullName": "Nigeria", - "Acronym": "NGA" - }, - { - "FlagName": "NZ", - "FullName": "New Zealand", - "Acronym": "NZL" - }, - { - "FlagName": "NP", - "FullName": "Nepal", - "Acronym": "NPL" - }, - { - "FlagName": "NR", - "FullName": "Nauru", - "Acronym": "NRU" - }, - { - "FlagName": "NU", - "FullName": "Niue", - "Acronym": "NIU" - }, - { - "FlagName": "CK", - "FullName": "Cook Islands", - "Acronym": "COK" - }, - { - "FlagName": "XK", - "FullName": "Kosovo", - "Acronym": "XKX" - }, - { - "FlagName": "CI", - "FullName": "Ivory Coast", - "Acronym": "CIV" - }, - { - "FlagName": "CH", - "FullName": "Switzerland", - "Acronym": "CHE" - }, - { - "FlagName": "CO", - "FullName": "Colombia", - "Acronym": "COL" - }, - { - "FlagName": "CN", - "FullName": "China", - "Acronym": "CHN" - }, - { - "FlagName": "CM", - "FullName": "Cameroon", - "Acronym": "CMR" - }, - { - "FlagName": "CL", - "FullName": "Chile", - "Acronym": "CHL" - }, - { - "FlagName": "CC", - "FullName": "Cocos Islands", - "Acronym": "CCK" - }, - { - "FlagName": "CA", - "FullName": "Canada", - "Acronym": "CAN" - }, - { - "FlagName": "CG", - "FullName": "Republic of the Congo", - "Acronym": "COG" - }, - { - "FlagName": "CF", - "FullName": "Central African Republic", - "Acronym": "CAF" - }, - { - "FlagName": "CD", - "FullName": "Democratic Republic of the Congo", - "Acronym": "COD" - }, - { - "FlagName": "CZ", - "FullName": "Czech Republic", - "Acronym": "CZE" - }, - { - "FlagName": "CY", - "FullName": "Cyprus", - "Acronym": "CYP" - }, - { - "FlagName": "CX", - "FullName": "Christmas Island", - "Acronym": "CXR" - }, - { - "FlagName": "CR", - "FullName": "Costa Rica", - "Acronym": "CRI" - }, - { - "FlagName": "CW", - "FullName": "Curacao", - "Acronym": "CUW" - }, - { - "FlagName": "CV", - "FullName": "Cabo Verde", - "Acronym": "CPV" - }, - { - "FlagName": "CU", - "FullName": "Cuba", - "Acronym": "CUB" - }, - { - "FlagName": "SZ", - "FullName": "Eswatini", - "Acronym": "SWZ" - }, - { - "FlagName": "SY", - "FullName": "Syria", - "Acronym": "SYR" - }, - { - "FlagName": "SX", - "FullName": "Sint Maarten", - "Acronym": "SXM" - }, - { - "FlagName": "KG", - "FullName": "Kyrgyzstan", - "Acronym": "KGZ" - }, - { - "FlagName": "KE", - "FullName": "Kenya", - "Acronym": "KEN" - }, - { - "FlagName": "SS", - "FullName": "South Sudan", - "Acronym": "SSD" - }, - { - "FlagName": "SR", - "FullName": "Suriname", - "Acronym": "SUR" - }, - { - "FlagName": "KI", - "FullName": "Kiribati", - "Acronym": "KIR" - }, - { - "FlagName": "KH", - "FullName": "Cambodia", - "Acronym": "KHM" - }, - { - "FlagName": "KN", - "FullName": "Saint Kitts and Nevis", - "Acronym": "KNA" - }, - { - "FlagName": "KM", - "FullName": "Comoros", - "Acronym": "COM" - }, - { - "FlagName": "ST", - "FullName": "Sao Tome and Principe", - "Acronym": "STP" - }, - { - "FlagName": "SK", - "FullName": "Slovakia", - "Acronym": "SVK" - }, - { - "FlagName": "KR", - "FullName": "South Korea", - "Acronym": "KOR" - }, - { - "FlagName": "SI", - "FullName": "Slovenia", - "Acronym": "SVN" - }, - { - "FlagName": "KP", - "FullName": "North Korea", - "Acronym": "PRK" - }, - { - "FlagName": "KW", - "FullName": "Kuwait", - "Acronym": "KWT" - }, - { - "FlagName": "SN", - "FullName": "Senegal", - "Acronym": "SEN" - }, - { - "FlagName": "SM", - "FullName": "San Marino", - "Acronym": "SMR" - }, - { - "FlagName": "SL", - "FullName": "Sierra Leone", - "Acronym": "SLE" - }, - { - "FlagName": "SC", - "FullName": "Seychelles", - "Acronym": "SYC" - }, - { - "FlagName": "KZ", - "FullName": "Kazakhstan", - "Acronym": "KAZ" - }, - { - "FlagName": "KY", - "FullName": "Cayman Islands", - "Acronym": "CYM" - }, - { - "FlagName": "SG", - "FullName": "Singapore", - "Acronym": "SGP" - }, - { - "FlagName": "SE", - "FullName": "Sweden", - "Acronym": "SWE" - }, - { - "FlagName": "SD", - "FullName": "Sudan", - "Acronym": "SDN" - }, - { - "FlagName": "DO", - "FullName": "Dominican Republic", - "Acronym": "DOM" - }, - { - "FlagName": "DM", - "FullName": "Dominica", - "Acronym": "DMA" - }, - { - "FlagName": "DJ", - "FullName": "Djibouti", - "Acronym": "DJI" - }, - { - "FlagName": "DK", - "FullName": "Denmark", - "Acronym": "DNK" - }, - { - "FlagName": "VG", - "FullName": "British Virgin Islands", - "Acronym": "VGB" - }, - { - "FlagName": "DE", - "FullName": "Germany", - "Acronym": "DEU" - }, - { - "FlagName": "YE", - "FullName": "Yemen", - "Acronym": "YEM" - }, - { - "FlagName": "DZ", - "FullName": "Algeria", - "Acronym": "DZA" - }, - { - "FlagName": "US", - "FullName": "United States", - "Acronym": "USA" - }, - { - "FlagName": "UY", - "FullName": "Uruguay", - "Acronym": "URY" - }, - { - "FlagName": "YT", - "FullName": "Mayotte", - "Acronym": "MYT" - }, - { - "FlagName": "UM", - "FullName": "United States Minor Outlying Islands", - "Acronym": "UMI" - }, - { - "FlagName": "LB", - "FullName": "Lebanon", - "Acronym": "LBN" - }, - { - "FlagName": "LC", - "FullName": "Saint Lucia", - "Acronym": "LCA" - }, - { - "FlagName": "LA", - "FullName": "Laos", - "Acronym": "LAO" - }, - { - "FlagName": "TV", - "FullName": "Tuvalu", - "Acronym": "TUV" - }, - { - "FlagName": "TW", - "FullName": "Taiwan", - "Acronym": "TWN" - }, - { - "FlagName": "TT", - "FullName": "Trinidad and Tobago", - "Acronym": "TTO" - }, - { - "FlagName": "TR", - "FullName": "Turkey", - "Acronym": "TUR" - }, - { - "FlagName": "LK", - "FullName": "Sri Lanka", - "Acronym": "LKA" - }, - { - "FlagName": "LI", - "FullName": "Liechtenstein", - "Acronym": "LIE" - }, - { - "FlagName": "LV", - "FullName": "Latvia", - "Acronym": "LVA" - }, - { - "FlagName": "TO", - "FullName": "Tonga", - "Acronym": "TON" - }, - { - "FlagName": "LT", - "FullName": "Lithuania", - "Acronym": "LTU" - }, - { - "FlagName": "LU", - "FullName": "Luxembourg", - "Acronym": "LUX" - }, - { - "FlagName": "LR", - "FullName": "Liberia", - "Acronym": "LBR" - }, - { - "FlagName": "LS", - "FullName": "Lesotho", - "Acronym": "LSO" - }, - { - "FlagName": "TH", - "FullName": "Thailand", - "Acronym": "THA" - }, - { - "FlagName": "TF", - "FullName": "French Southern Territories", - "Acronym": "ATF" - }, - { - "FlagName": "TG", - "FullName": "Togo", - "Acronym": "TGO" - }, - { - "FlagName": "TD", - "FullName": "Chad", - "Acronym": "TCD" - }, - { - "FlagName": "TC", - "FullName": "Turks and Caicos Islands", - "Acronym": "TCA" - }, - { - "FlagName": "LY", - "FullName": "Libya", - "Acronym": "LBY" - }, - { - "FlagName": "VA", - "FullName": "Vatican", - "Acronym": "VAT" - }, - { - "FlagName": "VC", - "FullName": "Saint Vincent and the Grenadines", - "Acronym": "VCT" - }, - { - "FlagName": "AE", - "FullName": "United Arab Emirates", - "Acronym": "ARE" - }, - { - "FlagName": "AD", - "FullName": "Andorra", - "Acronym": "AND" - }, - { - "FlagName": "AG", - "FullName": "Antigua and Barbuda", - "Acronym": "ATG" - }, - { - "FlagName": "AF", - "FullName": "Afghanistan", - "Acronym": "AFG" - }, - { - "FlagName": "AI", - "FullName": "Anguilla", - "Acronym": "AIA" - }, - { - "FlagName": "VI", - "FullName": "U.S. Virgin Islands", - "Acronym": "VIR" - }, - { - "FlagName": "IS", - "FullName": "Iceland", - "Acronym": "ISL" - }, - { - "FlagName": "IR", - "FullName": "Iran", - "Acronym": "IRN" - }, - { - "FlagName": "AM", - "FullName": "Armenia", - "Acronym": "ARM" - }, - { - "FlagName": "AL", - "FullName": "Albania", - "Acronym": "ALB" - }, - { - "FlagName": "AO", - "FullName": "Angola", - "Acronym": "AGO" - }, - { - "FlagName": "AQ", - "FullName": "Antarctica", - "Acronym": "ATA" - }, - { - "FlagName": "AS", - "FullName": "American Samoa", - "Acronym": "ASM" - }, - { - "FlagName": "AR", - "FullName": "Argentina", - "Acronym": "ARG" - }, - { - "FlagName": "AU", - "FullName": "Australia", - "Acronym": "AUS" - }, - { - "FlagName": "AT", - "FullName": "Austria", - "Acronym": "AUT" - }, - { - "FlagName": "AW", - "FullName": "Aruba", - "Acronym": "ABW" - }, - { - "FlagName": "IN", - "FullName": "India", - "Acronym": "IND" - }, - { - "FlagName": "AX", - "FullName": "Aland Islands", - "Acronym": "ALA" - }, - { - "FlagName": "AZ", - "FullName": "Azerbaijan", - "Acronym": "AZE" - }, - { - "FlagName": "IE", - "FullName": "Ireland", - "Acronym": "IRL" - }, - { - "FlagName": "ID", - "FullName": "Indonesia", - "Acronym": "IDN" - }, - { - "FlagName": "UA", - "FullName": "Ukraine", - "Acronym": "UKR" - }, - { - "FlagName": "QA", - "FullName": "Qatar", - "Acronym": "QAT" - }, - { - "FlagName": "MZ", - "FullName": "Mozambique", - "Acronym": "MOZ" - } -] \ No newline at end of file diff --git a/osu.Game.Tournament/SaveChangesOverlay.cs b/osu.Game.Tournament/SaveChangesOverlay.cs new file mode 100644 index 0000000000..b5e08fc005 --- /dev/null +++ b/osu.Game.Tournament/SaveChangesOverlay.cs @@ -0,0 +1,101 @@ +// 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.Tasks; +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.Game.Graphics; +using osu.Game.Online.Multiplayer; +using osuTK; + +namespace osu.Game.Tournament +{ + internal class SaveChangesOverlay : CompositeDrawable + { + [Resolved] + private TournamentGame tournamentGame { get; set; } = null!; + + private string? lastSerialisedLadder; + private readonly TourneyButton saveChangesButton; + + public SaveChangesOverlay() + { + RelativeSizeAxes = Axes.Both; + + InternalChild = new Container + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Position = new Vector2(5), + CornerRadius = 10, + Masking = true, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.2f), + RelativeSizeAxes = Axes.Both, + }, + saveChangesButton = new TourneyButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Padding = new MarginPadding + { + Top = 10, + Left = 10, + }, + Margin = new MarginPadding + { + Right = 10, + Bottom = 10, + }, + Action = saveChanges, + // Enabled = { Value = false }, + }, + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + scheduleNextCheck(); + } + + private async Task checkForChanges() + { + string serialisedLadder = await Task.Run(() => tournamentGame.GetSerialisedLadder()); + + // If a save hasn't been triggered by the user yet, populate the initial value + lastSerialisedLadder ??= serialisedLadder; + + if (lastSerialisedLadder != serialisedLadder && !saveChangesButton.Enabled.Value) + { + saveChangesButton.Enabled.Value = true; + saveChangesButton.Background + .FadeColour(saveChangesButton.BackgroundColour.Lighten(0.5f), 500, Easing.In).Then() + .FadeColour(saveChangesButton.BackgroundColour, 500, Easing.Out) + .Loop(); + } + + scheduleNextCheck(); + } + + private void scheduleNextCheck() => Scheduler.AddDelayed(() => checkForChanges().FireAndForget(), 1000); + + private void saveChanges() + { + tournamentGame.SaveChanges(); + lastSerialisedLadder = tournamentGame.GetSerialisedLadder(); + + saveChangesButton.Enabled.Value = false; + saveChangesButton.Background.FadeColour(saveChangesButton.BackgroundColour, 500); + } + } +} diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 77b816d24c..763f576afe 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -1,13 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps.Legacy; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; +using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens { @@ -37,7 +39,7 @@ namespace osu.Game.Tournament.Screens SongBar.Mods = mods.NewValue; } - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { SongBar.FadeInFromZero(300, Easing.OutQuint); SongBar.Beatmap = beatmap.NewValue; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs index 1a2f5a1ff4..ac1d599851 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index ece1c431e2..f50abd6e58 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index b9a19090df..62b3c4e8ff 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs index cd252392ba..80bdad8b7b 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs index 09208818a9..7e0ac89c83 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs index 6fec74f95b..52c611d323 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ScrollingTeamContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -310,7 +312,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components public class ScrollingTeam : DrawableTournamentTeam { public const float WIDTH = 58; - public const float HEIGHT = 41; + public const float HEIGHT = 44; private readonly Box outline; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs index 5d035a4028..c230607343 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/StorageBackedTeamList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs index f21f5c9460..15edbb76c1 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/VisualiserContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs index 53ac93afea..5ac25f97b5 100644 --- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs +++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -10,8 +12,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; @@ -43,7 +43,7 @@ namespace osu.Game.Tournament.Screens.Drawings public ITeamList TeamList; [BackgroundDependencyLoader] - private void load(TextureStore textures, Storage storage) + private void load(Storage storage) { RelativeSizeAxes = Axes.Both; @@ -89,11 +89,10 @@ namespace osu.Game.Tournament.Screens.Drawings RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Sprite + new TourneyVideo("drawings") { + Loop = true, RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fill, - Texture = textures.Get(@"Backgrounds/Drawings/background.png") }, // Visualiser new VisualiserContainer @@ -217,7 +216,7 @@ namespace osu.Game.Tournament.Screens.Drawings } } - writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run(writeAction); + writeOp = writeOp?.ContinueWith(_ => { writeAction(); }) ?? Task.Run(writeAction); } private void reloadTeams() diff --git a/osu.Game.Tournament/Screens/Editors/IModelBacked.cs b/osu.Game.Tournament/Screens/Editors/IModelBacked.cs index ed94bd7f45..ca59afa2cb 100644 --- a/osu.Game.Tournament/Screens/Editors/IModelBacked.cs +++ b/osu.Game.Tournament/Screens/Editors/IModelBacked.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Tournament.Screens.Editors { /// diff --git a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs index ca46c3b050..4261828df2 100644 --- a/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Drawing; using System.Linq; @@ -42,7 +44,7 @@ namespace osu.Game.Tournament.Screens.Editors AddInternal(rightClickMessage = new WarningBox("Right click to place and link matches")); - LadderInfo.Matches.CollectionChanged += (_, __) => updateMessage(); + LadderInfo.Matches.CollectionChanged += (_, _) => updateMessage(); updateMessage(); } diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 5c12d83d1c..1b670f4b69 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -237,7 +239,7 @@ namespace osu.Game.Tournament.Screens.Editors req.Success += res => { - Model.Beatmap = res; + Model.Beatmap = new TournamentBeatmap(res); updatePanel(); }; diff --git a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs index 5cdfe7dc08..1bc929604d 100644 --- a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -239,7 +241,7 @@ namespace osu.Game.Tournament.Screens.Editors req.Success += res => { - Model.Beatmap = res; + Model.Beatmap = new TournamentBeatmap(res); updatePanel(); }; diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index 6adddb5204..da27c09e01 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -1,19 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; @@ -24,9 +25,6 @@ namespace osu.Game.Tournament.Screens.Editors { public class TeamEditorScreen : TournamentEditorScreen { - [Resolved] - private TournamentGameBase game { get; set; } - protected override BindableList Storage => LadderInfo.Teams; [BackgroundDependencyLoader] @@ -44,11 +42,17 @@ namespace osu.Game.Tournament.Screens.Editors private void addAllCountries() { - List countries; + var countries = new List(); - using (Stream stream = game.Resources.GetStream("Resources/countries.json")) - using (var sr = new StreamReader(stream)) - countries = JsonConvert.DeserializeObject>(sr.ReadToEnd()); + foreach (var country in Enum.GetValues(typeof(CountryCode)).Cast().Skip(1)) + { + countries.Add(new TournamentTeam + { + FlagName = { Value = country.ToString() }, + FullName = { Value = country.GetDescription() }, + Acronym = { Value = country.GetAcronym() }, + }); + } Debug.Assert(countries != null); @@ -200,14 +204,14 @@ namespace osu.Game.Tournament.Screens.Editors public void CreateNew() { - var user = new APIUser(); - team.Players.Add(user); - flow.Add(new PlayerRow(team, user)); + var player = new TournamentUser(); + team.Players.Add(player); + flow.Add(new PlayerRow(team, player)); } public class PlayerRow : CompositeDrawable { - private readonly APIUser user; + private readonly TournamentUser user; [Resolved] protected IAPIProvider API { get; private set; } @@ -215,11 +219,11 @@ namespace osu.Game.Tournament.Screens.Editors [Resolved] private TournamentGameBase game { get; set; } - private readonly Bindable userId = new Bindable(); + private readonly Bindable playerId = new Bindable(); private readonly Container drawableContainer; - public PlayerRow(TournamentTeam team, APIUser user) + public PlayerRow(TournamentTeam team, TournamentUser user) { this.user = user; @@ -252,7 +256,7 @@ namespace osu.Game.Tournament.Screens.Editors LabelText = "User ID", RelativeSizeAxes = Axes.None, Width = 200, - Current = userId, + Current = playerId, }, drawableContainer = new Container { @@ -279,10 +283,10 @@ namespace osu.Game.Tournament.Screens.Editors [BackgroundDependencyLoader] private void load() { - userId.Value = user.Id; - userId.BindValueChanged(id => + playerId.Value = user.OnlineID; + playerId.BindValueChanged(id => { - user.Id = id.NewValue ?? 0; + user.OnlineID = id.NewValue ?? 0; if (id.NewValue != id.OldValue) user.Username = string.Empty; @@ -293,14 +297,14 @@ namespace osu.Game.Tournament.Screens.Editors return; } - game.PopulateUser(user, updatePanel, updatePanel); + game.PopulatePlayer(user, updatePanel, updatePanel); }, true); } - private void updatePanel() + private void updatePanel() => Scheduler.AddOnce(() => { - drawableContainer.Child = new UserGridPanel(user) { Width = 300 }; - } + drawableContainer.Child = new UserGridPanel(user.ToAPIUser()) { Width = 300 }; + }); } } } diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index a5a2c5c15f..0fefe6f780 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; @@ -18,7 +20,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public abstract class TournamentEditorScreen : TournamentScreen, IProvideVideo + public abstract class TournamentEditorScreen : TournamentScreen where TDrawable : Drawable, IModelBacked where TModel : class, new() { diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs index 8048425ce1..91a75bf86f 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs index 2f0e4b5e87..78206c6d47 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Tournament.Components; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs index 33658115cc..1eceddd871 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,6 +16,10 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { private readonly TeamScore score; + private readonly TournamentSpriteTextWithBackground teamText; + + private readonly Bindable teamName = new Bindable("???"); + private bool showScore; public bool ShowScore @@ -91,7 +97,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components } } }, - new TournamentSpriteTextWithBackground(team?.FullName.Value ?? "???") + teamText = new TournamentSpriteTextWithBackground { Scale = new Vector2(0.5f), Origin = anchor, @@ -111,6 +117,11 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components updateDisplay(); FinishTransforms(true); + + if (Team != null) + teamName.BindTo(Team.FullName); + + teamName.BindValueChanged(name => teamText.Text.Text = name.NewValue, true); } private void updateDisplay() diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs index 36c78c5ac1..3fa06c16b4 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs index da55ba53ea..5ee57e9271 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScoreDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -40,6 +42,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentMatch.BindTo(ladder.CurrentMatch); currentMatch.BindValueChanged(matchChanged); + currentTeam.BindValueChanged(teamChanged); + updateMatch(); } @@ -65,7 +69,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components // team may change to same team, which means score is not in a good state. // thus we handle this manually. - teamChanged(currentTeam.Value); + currentTeam.TriggerChange(); } protected override bool OnMouseDown(MouseDownEvent e) @@ -86,11 +90,11 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components return base.OnMouseDown(e); } - private void teamChanged(TournamentTeam team) + private void teamChanged(ValueChangedEvent team) { InternalChildren = new Drawable[] { - teamDisplay = new TeamDisplay(team, teamColour, currentTeamScore, currentMatch.Value?.PointsToWin ?? 0), + teamDisplay = new TeamDisplay(team.NewValue, teamColour, currentTeamScore, currentMatch.Value?.PointsToWin ?? 0), }; } } diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs index db15a46fc8..7454d22aa2 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TournamentMatchScoreDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs index f900dd7eac..54ae4c0366 100644 --- a/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs +++ b/osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -19,7 +21,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Gameplay { - public class GameplayScreen : BeatmapInfoScreen, IProvideVideo + public class GameplayScreen : BeatmapInfoScreen { private readonly BindableBool warmup = new BindableBool(); diff --git a/osu.Game.Tournament/Screens/IProvideVideo.cs b/osu.Game.Tournament/Screens/IProvideVideo.cs deleted file mode 100644 index 61989d8448..0000000000 --- a/osu.Game.Tournament/Screens/IProvideVideo.cs +++ /dev/null @@ -1,12 +0,0 @@ -// 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.Tournament.Screens -{ - /// - /// Marker interface for a screen which provides its own local video background. - /// - public interface IProvideVideo - { - } -} diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs index 16224a7fb4..04155fcb89 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs index ea453a53ca..c005e11efe 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs index 5729e779c4..5204edf3be 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentMatch.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Drawing; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs index cad0b827c0..466b9ed482 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -47,10 +49,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components }; name = round.Name.GetBoundCopy(); - name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpper(), true); + name.BindValueChanged(_ => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpperInvariant(), true); description = round.Description.GetBoundCopy(); - description.BindValueChanged(n => textDescription.Text = round.Description.Value?.ToUpper(), true); + description.BindValueChanged(_ => textDescription.Text = round.Description.Value?.ToUpperInvariant(), true); } } } diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs index cf4466a2e3..1fdf616e34 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; @@ -51,6 +53,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components editorInfo.Selected.ValueChanged += selection => { + // ensure any ongoing edits are committed out to the *current* selection before changing to a new one. + GetContainingInputManager().TriggerFocusContention(null); + roundDropdown.Current = selection.NewValue?.Round; losersCheckbox.Current = selection.NewValue?.Losers; dateTimeBox.Current = selection.NewValue?.Date; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index 960c4f41cc..c5f8c3bb51 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Lines; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs index 6604e3a313..74424783c6 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index f98bfd087d..6fae44de35 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs index ad6e304c80..7ad7e76a1f 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; @@ -17,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Ladder { - public class LadderScreen : TournamentScreen, IProvideVideo + public class LadderScreen : TournamentScreen { protected Container MatchesContainer; private Container paths; @@ -73,7 +75,7 @@ namespace osu.Game.Tournament.Screens.Ladder foreach (var match in LadderInfo.Matches) addMatch(match); - LadderInfo.Rounds.CollectionChanged += (_, __) => layout.Invalidate(); + LadderInfo.Rounds.CollectionChanged += (_, _) => layout.Invalidate(); LadderInfo.Matches.CollectionChanged += (_, args) => { switch (args.Action) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index 3ae007f955..5eb2142fae 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -9,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -105,7 +106,7 @@ namespace osu.Game.Tournament.Screens.MapPool ipc.Beatmap.BindValueChanged(beatmapChanged); } - private void beatmapChanged(ValueChangedEvent beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { if (CurrentMatch.Value == null || CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2) return; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 84f38170ea..0827cbae69 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -17,7 +19,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Schedule { - public class ScheduleScreen : TournamentScreen // IProvidesVideo + public class ScheduleScreen : TournamentScreen { private readonly Bindable currentMatch = new Bindable(); private Container mainContainer; diff --git a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs index cfdf9c99ae..a9ac21284e 100644 --- a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs +++ b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs index e53110651b..a387341d66 100644 --- a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs +++ b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs index f6d28c15e0..2b2dce3664 100644 --- a/osu.Game.Tournament/Screens/Setup/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs @@ -1,12 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Drawing; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Overlays; @@ -17,7 +21,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.Setup { - public class SetupScreen : TournamentScreen, IProvideVideo + public class SetupScreen : TournamentScreen { private FillFlowContainer fillFlow; @@ -46,13 +50,21 @@ namespace osu.Game.Tournament.Screens.Setup { windowSize = frameworkConfig.GetBindable(FrameworkSetting.WindowedSize); - InternalChild = fillFlow = new FillFlowContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Padding = new MarginPadding(10), - Spacing = new Vector2(10), + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f), + }, + fillFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(10), + Spacing = new Vector2(10), + } }; api.LocalUser.BindValueChanged(_ => Schedule(reload)); @@ -72,7 +84,8 @@ namespace osu.Game.Tournament.Screens.Setup Action = () => sceneManager?.SetScreen(new StablePathSelectScreen()), Value = fileBasedIpc?.IPCStorage?.GetFullPath(string.Empty) ?? "Not found", Failing = fileBasedIpc?.IPCStorage == null, - Description = "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation." + Description = + "The osu!stable installation which is currently being used as a data source. If a source is not found, make sure you have created an empty ipc.txt in your stable cutting-edge installation." }, new ActionableInfo { diff --git a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs index fb9ca46c2d..fac488fcf5 100644 --- a/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index f0aa857769..447d6f44ce 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -25,7 +27,7 @@ namespace osu.Game.Tournament.Screens.Setup dropdown.Items = storage.ListTournaments(); dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true); - Action = () => game.GracefullyExit(); + Action = () => game.AttemptExit(); folderButton.Action = () => storage.PresentExternally(); ButtonText = "Close osu!"; diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 32d458e191..a7a175ceba 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -12,7 +14,7 @@ using osuTK.Graphics; namespace osu.Game.Tournament.Screens.Showcase { - public class ShowcaseScreen : BeatmapInfoScreen // IProvideVideo + public class ShowcaseScreen : BeatmapInfoScreen { [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index bd5aa2f5d9..07a632ec72 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs index 0003e213e7..9262cab098 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -17,7 +20,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.TeamIntro { - public class SeedingScreen : TournamentMatchScreen, IProvideVideo + public class SeedingScreen : TournamentMatchScreen { private Container mainContainer; @@ -67,7 +70,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro currentTeam.BindValueChanged(teamChanged, true); } - private void teamChanged(ValueChangedEvent team) + private void teamChanged(ValueChangedEvent team) => Scheduler.AddOnce(() => { if (team.NewValue == null) { @@ -76,7 +79,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro } showTeam(team.NewValue); - } + }); protected override void CurrentMatchChanged(ValueChangedEvent match) { @@ -118,8 +121,14 @@ namespace osu.Game.Tournament.Screens.TeamIntro foreach (var seeding in team.SeedingResults) { fill.Add(new ModRow(seeding.Mod.Value, seeding.Seed.Value)); + foreach (var beatmap in seeding.Beatmaps) + { + if (beatmap.Beatmap == null) + continue; + fill.Add(new BeatmapScoreRow(beatmap)); + } } } @@ -127,6 +136,8 @@ namespace osu.Game.Tournament.Screens.TeamIntro { public BeatmapScoreRow(SeedingBeatmap beatmap) { + Debug.Assert(beatmap.Beatmap != null); + RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -155,7 +166,8 @@ namespace osu.Game.Tournament.Screens.TeamIntro Children = new Drawable[] { new TournamentSpriteText { Text = beatmap.Score.ToString("#,0"), Colour = TournamentGame.TEXT_COLOUR, Width = 80 }, - new TournamentSpriteText { Text = "#" + beatmap.Seed.Value.ToString("#,0"), Colour = TournamentGame.TEXT_COLOUR, Font = OsuFont.Torus.With(weight: FontWeight.Regular) }, + new TournamentSpriteText + { Text = "#" + beatmap.Seed.Value.ToString("#,0"), Colour = TournamentGame.TEXT_COLOUR, Font = OsuFont.Torus.With(weight: FontWeight.Regular) }, } }, }; @@ -196,7 +208,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro { row.Add(new Sprite { - Texture = textures.Get($"Mods/{mods.ToLower()}"), + Texture = textures.Get($"Mods/{mods.ToLowerInvariant()}"), Scale = new Vector2(0.5f) }); } @@ -255,7 +267,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro }; foreach (var p in team.Players) - fill.Add(new RowDisplay(p.Username, p.Statistics?.GlobalRank?.ToString("\\##,0") ?? "-")); + fill.Add(new RowDisplay(p.Username, p.Rank?.ToString("\\##,0") ?? "-")); } internal class RowDisplay : CompositeDrawable diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs index ef6f0b32ff..08c9a7a897 100644 --- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs +++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -11,7 +13,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.TeamIntro { - public class TeamIntroScreen : TournamentMatchScreen, IProvideVideo + public class TeamIntroScreen : TournamentMatchScreen { private Container mainContainer; diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs index 11db7bfad9..ac54ff58f5 100644 --- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs +++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -12,7 +14,7 @@ using osuTK; namespace osu.Game.Tournament.Screens.TeamWin { - public class TeamWinScreen : TournamentMatchScreen, IProvideVideo + public class TeamWinScreen : TournamentMatchScreen { private Container mainContainer; @@ -64,7 +66,7 @@ namespace osu.Game.Tournament.Screens.TeamWin private bool firstDisplay = true; - private void update() => Schedule(() => + private void update() => Scheduler.AddOnce(() => { var match = CurrentMatch.Value; diff --git a/osu.Game.Tournament/Screens/TournamentMatchScreen.cs b/osu.Game.Tournament/Screens/TournamentMatchScreen.cs index 5f00036653..585cdd09c1 100644 --- a/osu.Game.Tournament/Screens/TournamentMatchScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentMatchScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index 5da7c7a5d2..b4641fa45d 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 7967f54b49..7d67bfa759 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Drawing; using System.Linq; using osu.Framework.Allocation; @@ -9,8 +11,6 @@ using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Logging; using osu.Framework.Platform; @@ -18,11 +18,11 @@ using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Tournament.Models; -using osuTK; using osuTK.Graphics; namespace osu.Game.Tournament { + [Cached] public class TournamentGame : TournamentGameBase { public static ColourInfo GetTeamColour(TeamColour teamColour) => teamColour == TeamColour.Red ? COLOUR_RED : COLOUR_BLUE; @@ -76,40 +76,9 @@ namespace osu.Game.Tournament LoadComponentsAsync(new[] { - new Container + new SaveChangesOverlay { - CornerRadius = 10, Depth = float.MinValue, - Position = new Vector2(5), - Masking = true, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Children = new Drawable[] - { - new Box - { - Colour = OsuColour.Gray(0.2f), - RelativeSizeAxes = Axes.Both, - }, - new TourneyButton - { - Text = "Save Changes", - Width = 140, - Height = 50, - Padding = new MarginPadding - { - Top = 10, - Left = 10, - }, - Margin = new MarginPadding - { - Right = 10, - Bottom = 10, - }, - Action = SaveChanges, - }, - } }, heightWarning = new WarningBox("Please make the window wider") { @@ -135,7 +104,7 @@ namespace osu.Game.Tournament heightWarning.Alpha = size.NewValue.Width < minWidth ? 1 : 0; }), true); - windowMode.BindValueChanged(mode => ScheduleAfterChildren(() => + windowMode.BindValueChanged(_ => ScheduleAfterChildren(() => { windowMode.Value = WindowMode.Windowed; }), true); diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 6ae0312cce..063b62bf08 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -19,8 +21,8 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Tournament.IO; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; +using osu.Game.Users; using osuTK.Input; -using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tournament { @@ -61,7 +63,7 @@ namespace osu.Game.Tournament dependencies.Cache(new TournamentVideoResourceStore(storage)); - Textures.AddStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))); + Textures.AddTextureSource(new TextureLoaderStore(new StorageBackedResourceStore(storage))); dependencies.CacheAs(new StableInfo(storage)); } @@ -186,8 +188,8 @@ namespace osu.Game.Tournament var playersRequiringPopulation = ladder.Teams .SelectMany(t => t.Players) .Where(p => string.IsNullOrEmpty(p.Username) - || p.Statistics?.GlobalRank == null - || p.Statistics?.CountryRank == null).ToList(); + || p.CountryCode == CountryCode.Unknown + || p.Rank == null).ToList(); if (playersRequiringPopulation.Count == 0) return false; @@ -195,7 +197,7 @@ namespace osu.Game.Tournament for (int i = 0; i < playersRequiringPopulation.Count; i++) { var p = playersRequiringPopulation[i]; - PopulateUser(p, immediate: true); + PopulatePlayer(p, immediate: true); updateLoadProgressMessage($"Populating user stats ({i} / {playersRequiringPopulation.Count})"); } @@ -209,7 +211,7 @@ namespace osu.Game.Tournament { var beatmapsRequiringPopulation = ladder.Rounds .SelectMany(r => r.Beatmaps) - .Where(b => string.IsNullOrEmpty(b.Beatmap?.BeatmapSet?.Title) && b.ID > 0).ToList(); + .Where(b => b.Beatmap?.OnlineID == 0 && b.ID > 0).ToList(); if (beatmapsRequiringPopulation.Count == 0) return false; @@ -220,7 +222,7 @@ namespace osu.Game.Tournament var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); API.Perform(req); - b.Beatmap = req.Response ?? new APIBeatmap(); + b.Beatmap = new TournamentBeatmap(req.Response ?? new APIBeatmap()); updateLoadProgressMessage($"Populating round beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } @@ -236,7 +238,7 @@ namespace osu.Game.Tournament var beatmapsRequiringPopulation = ladder.Teams .SelectMany(r => r.SeedingResults) .SelectMany(r => r.Beatmaps) - .Where(b => string.IsNullOrEmpty(b.Beatmap?.BeatmapSet?.Title) && b.ID > 0).ToList(); + .Where(b => b.Beatmap?.OnlineID == 0 && b.ID > 0).ToList(); if (beatmapsRequiringPopulation.Count == 0) return false; @@ -247,7 +249,7 @@ namespace osu.Game.Tournament var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); API.Perform(req); - b.Beatmap = req.Response ?? new APIBeatmap(); + b.Beatmap = new TournamentBeatmap(req.Response ?? new APIBeatmap()); updateLoadProgressMessage($"Populating seeding beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } @@ -257,9 +259,9 @@ namespace osu.Game.Tournament private void updateLoadProgressMessage(string s) => Schedule(() => initialisationText.Text = s); - public void PopulateUser(APIUser user, Action success = null, Action failure = null, bool immediate = false) + public void PopulatePlayer(TournamentUser user, Action success = null, Action failure = null, bool immediate = false) { - var req = new GetUserRequest(user.Id, ladder.Ruleset.Value); + var req = new GetUserRequest(user.OnlineID, ladder.Ruleset.Value); if (immediate) { @@ -268,10 +270,10 @@ namespace osu.Game.Tournament } else { - req.Success += res => { populate(); }; + req.Success += _ => { populate(); }; req.Failure += _ => { - user.Id = 1; + user.OnlineID = 1; failure?.Invoke(); }; @@ -285,18 +287,18 @@ namespace osu.Game.Tournament if (res == null) return; - user.Id = res.Id; + user.OnlineID = res.Id; user.Username = res.Username; - user.Statistics = res.Statistics; - user.Country = res.Country; - user.Cover = res.Cover; + user.CoverUrl = res.CoverUrl; + user.CountryCode = res.CountryCode; + user.Rank = res.Statistics?.GlobalRank; success?.Invoke(); } } - protected virtual void SaveChanges() + public void SaveChanges() { if (!bracketLoadTaskCompletionSource.Task.IsCompletedSuccessfully) { @@ -312,7 +314,16 @@ namespace osu.Game.Tournament .ToList(); // Serialise before opening stream for writing, so if there's a failure it will leave the file in the previous state. - string serialisedLadder = JsonConvert.SerializeObject(ladder, + string serialisedLadder = GetSerialisedLadder(); + + using (var stream = storage.CreateFileSafely(BRACKET_FILENAME)) + using (var sw = new StreamWriter(stream)) + sw.Write(serialisedLadder); + } + + public string GetSerialisedLadder() + { + return JsonConvert.SerializeObject(ladder, new JsonSerializerSettings { Formatting = Formatting.Indented, @@ -320,10 +331,6 @@ namespace osu.Game.Tournament DefaultValueHandling = DefaultValueHandling.Ignore, Converters = new JsonConverter[] { new JsonPointConverter() } }); - - using (var stream = storage.CreateFileSafely(BRACKET_FILENAME)) - using (var sw = new StreamWriter(stream)) - sw.Write(serialisedLadder); } protected override UserInputManager CreateUserInputManager() => new TournamentInputManager(); diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 98338244e4..a12dbb4740 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -8,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Framework.Testing; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -184,7 +187,7 @@ namespace osu.Game.Tournament var lastScreen = currentScreen; currentScreen = target; - if (currentScreen is IProvideVideo) + if (currentScreen.ChildrenOfType().FirstOrDefault()?.VideoAvailable == true) { video.FadeOut(200); @@ -202,12 +205,12 @@ namespace osu.Game.Tournament switch (currentScreen) { - case MapPoolScreen _: + case MapPoolScreen: chatContainer.FadeIn(TournamentScreen.FADE_DELAY); chatContainer.ResizeWidthTo(1, 500, Easing.OutQuint); break; - case GameplayScreen _: + case GameplayScreen: chatContainer.FadeIn(TournamentScreen.FADE_DELAY); chatContainer.ResizeWidthTo(0.5f, 500, Easing.OutQuint); break; diff --git a/osu.Game.Tournament/TournamentSpriteText.cs b/osu.Game.Tournament/TournamentSpriteText.cs index e550dfbfae..166a8dfaf0 100644 --- a/osu.Game.Tournament/TournamentSpriteText.cs +++ b/osu.Game.Tournament/TournamentSpriteText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs index 12872d3197..f1b14df783 100644 --- a/osu.Game.Tournament/TourneyButton.cs +++ b/osu.Game.Tournament/TourneyButton.cs @@ -1,12 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; namespace osu.Game.Tournament { public class TourneyButton : OsuButton { + public new Box Background => base.Background; + public TourneyButton() : base(null) { diff --git a/osu.Game.Tournament/WarningBox.cs b/osu.Game.Tournament/WarningBox.cs index 814482aea4..123e78113a 100644 --- a/osu.Game.Tournament/WarningBox.cs +++ b/osu.Game.Tournament/WarningBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Audio/Effects/AudioFilter.cs b/osu.Game/Audio/Effects/AudioFilter.cs index 9446967173..5c318eb957 100644 --- a/osu.Game/Audio/Effects/AudioFilter.cs +++ b/osu.Game/Audio/Effects/AudioFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using ManagedBass.Fx; using osu.Framework.Audio.Mixing; diff --git a/osu.Game/Audio/Effects/ITransformableFilter.cs b/osu.Game/Audio/Effects/ITransformableFilter.cs index fb6a924f68..02149b362c 100644 --- a/osu.Game/Audio/Effects/ITransformableFilter.cs +++ b/osu.Game/Audio/Effects/ITransformableFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 3d90dd0189..efa5562cb8 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -16,15 +14,15 @@ namespace osu.Game.Audio [Serializable] public class HitSampleInfo : ISampleInfo, IEquatable { + public const string HIT_NORMAL = @"hitnormal"; public const string HIT_WHISTLE = @"hitwhistle"; public const string HIT_FINISH = @"hitfinish"; - public const string HIT_NORMAL = @"hitnormal"; public const string HIT_CLAP = @"hitclap"; /// /// All valid sample addition constants. /// - public static IEnumerable AllAdditions => new[] { HIT_WHISTLE, HIT_CLAP, HIT_FINISH }; + public static IEnumerable AllAdditions => new[] { HIT_WHISTLE, HIT_FINISH, HIT_CLAP }; /// /// The name of the sample to load. diff --git a/osu.Game/Audio/IPreviewTrackOwner.cs b/osu.Game/Audio/IPreviewTrackOwner.cs index 8ab93257a5..6a3acc2059 100644 --- a/osu.Game/Audio/IPreviewTrackOwner.cs +++ b/osu.Game/Audio/IPreviewTrackOwner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Audio { /// diff --git a/osu.Game/Audio/ISampleInfo.cs b/osu.Game/Audio/ISampleInfo.cs index 4f81d37e78..8f58415587 100644 --- a/osu.Game/Audio/ISampleInfo.cs +++ b/osu.Game/Audio/ISampleInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; namespace osu.Game.Audio diff --git a/osu.Game/Audio/ISamplePlaybackDisabler.cs b/osu.Game/Audio/ISamplePlaybackDisabler.cs index 4167316780..250e004b05 100644 --- a/osu.Game/Audio/ISamplePlaybackDisabler.cs +++ b/osu.Game/Audio/ISamplePlaybackDisabler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Skinning; diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 5df656e1e0..8ff8cd5c54 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 6d56d152f1..d19fdbd94c 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 5d8240204e..54b380f23a 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/APIFailTimes.cs b/osu.Game/Beatmaps/APIFailTimes.cs index 7218906b38..441d30d06b 100644 --- a/osu.Game/Beatmaps/APIFailTimes.cs +++ b/osu.Game/Beatmaps/APIFailTimes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 2fa5a56042..c499bccb68 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; 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 627e54c803..4419791e43 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 7e0462f1e8..f4bc5e7b77 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -4,8 +4,6 @@ using osu.Framework.Testing; using Realms; -#nullable enable - namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index f102daeef5..bf7b980e75 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -7,14 +7,12 @@ using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Lists; using osu.Framework.Logging; using osu.Framework.Threading; -using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Rulesets; @@ -48,31 +46,31 @@ namespace osu.Game.Beatmaps /// private readonly object bindableUpdateLock = new object(); - private CancellationTokenSource trackedUpdateCancellationSource; + private CancellationTokenSource trackedUpdateCancellationSource = new CancellationTokenSource(); [Resolved] - private BeatmapManager beatmapManager { get; set; } + private BeatmapManager beatmapManager { get; set; } = null!; [Resolved] - private Bindable currentRuleset { get; set; } + private Bindable currentRuleset { get; set; } = null!; [Resolved] - private Bindable> currentMods { get; set; } + private Bindable> currentMods { get; set; } = null!; - private ModSettingChangeTracker modSettingChangeTracker; - private ScheduledDelegate debouncedModSettingsChange; + private ModSettingChangeTracker? modSettingChangeTracker; + private ScheduledDelegate? debouncedModSettingsChange; protected override void LoadComplete() { base.LoadComplete(); - currentRuleset.BindValueChanged(_ => updateTrackedBindables()); + currentRuleset.BindValueChanged(_ => Scheduler.AddOnce(updateTrackedBindables)); currentMods.BindValueChanged(mods => { modSettingChangeTracker?.Dispose(); - updateTrackedBindables(); + Scheduler.AddOnce(updateTrackedBindables); modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue); modSettingChangeTracker.SettingChanged += _ => @@ -83,15 +81,22 @@ namespace osu.Game.Beatmaps }, true); } + public void Invalidate(IBeatmapInfo beatmap) + { + base.Invalidate(lookup => lookup.BeatmapInfo.Equals(beatmap)); + } + /// /// Retrieves a bindable containing the star difficulty of a that follows the currently-selected ruleset and mods. /// /// The to get the difficulty of. /// An optional which stops updating the star difficulty for the given . /// A bindable that is updated to contain the star difficulty when it becomes available. Will be null while in an initial calculating state (but not during updates to ruleset and mods if a stale value is already propagated). - public IBindable GetBindableDifficulty([NotNull] IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default) + public IBindable GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default) { - var bindable = createBindable(beatmapInfo, currentRuleset.Value, currentMods.Value, cancellationToken); + var bindable = new BindableStarDifficulty(beatmapInfo, cancellationToken); + + updateBindable(bindable, currentRuleset.Value, currentMods.Value, cancellationToken); lock (bindableUpdateLock) trackedBindables.Add(bindable); @@ -99,21 +104,6 @@ namespace osu.Game.Beatmaps return bindable; } - /// - /// Retrieves a bindable containing the star difficulty of a with a given and combination. - /// - /// - /// The bindable will not update to follow the currently-selected ruleset and mods or its settings. - /// - /// The to get the difficulty of. - /// The to get the difficulty with. If null, the 's ruleset is used. - /// The s to get the difficulty with. If null, no mods will be assumed. - /// An optional which stops updating the star difficulty for the given . - /// A bindable that is updated to contain the star difficulty when it becomes available. Will be null while in an initial calculating state. - public IBindable GetBindableDifficulty([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo rulesetInfo, [CanBeNull] IEnumerable mods, - CancellationToken cancellationToken = default) - => createBindable(beatmapInfo, rulesetInfo, mods, cancellationToken); - /// /// Retrieves the difficulty of a . /// @@ -126,8 +116,8 @@ namespace osu.Game.Beatmaps /// A return value indicates that the difficulty process failed or was interrupted early, /// and as such there is no usable star difficulty value to be returned. /// - public virtual Task GetDifficultyAsync([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo rulesetInfo = null, - [CanBeNull] IEnumerable mods = null, CancellationToken cancellationToken = default) + public virtual Task GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null, + IEnumerable? mods = null, CancellationToken cancellationToken = default) { // In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset. rulesetInfo ??= beatmapInfo.Ruleset; @@ -166,34 +156,6 @@ namespace osu.Game.Beatmaps updateScheduler); } - /// - /// Retrieves the that describes a star rating. - /// - /// - /// For more information, see: https://osu.ppy.sh/help/wiki/Difficulties - /// - /// The star rating. - /// The that best describes . - public static DifficultyRating GetDifficultyRating(double starRating) - { - if (Precision.AlmostBigger(starRating, 6.5, 0.005)) - return DifficultyRating.ExpertPlus; - - if (Precision.AlmostBigger(starRating, 5.3, 0.005)) - return DifficultyRating.Expert; - - if (Precision.AlmostBigger(starRating, 4.0, 0.005)) - return DifficultyRating.Insane; - - if (Precision.AlmostBigger(starRating, 2.7, 0.005)) - return DifficultyRating.Hard; - - if (Precision.AlmostBigger(starRating, 2.0, 0.005)) - return DifficultyRating.Normal; - - return DifficultyRating.Easy; - } - /// /// Updates all tracked using the current ruleset and mods. /// @@ -202,7 +164,6 @@ namespace osu.Game.Beatmaps lock (bindableUpdateLock) { cancelTrackedBindableUpdate(); - trackedUpdateCancellationSource = new CancellationTokenSource(); foreach (var b in trackedBindables) { @@ -221,35 +182,16 @@ namespace osu.Game.Beatmaps { lock (bindableUpdateLock) { - trackedUpdateCancellationSource?.Cancel(); - trackedUpdateCancellationSource = null; + trackedUpdateCancellationSource.Cancel(); + trackedUpdateCancellationSource = new CancellationTokenSource(); - if (linkedCancellationSources != null) - { - foreach (var c in linkedCancellationSources) - c.Dispose(); + foreach (var c in linkedCancellationSources) + c.Dispose(); - linkedCancellationSources.Clear(); - } + linkedCancellationSources.Clear(); } } - /// - /// Creates a new and triggers an initial value update. - /// - /// The that star difficulty should correspond to. - /// The initial to get the difficulty with. - /// The initial s to get the difficulty with. - /// An optional which stops updating the star difficulty for the given . - /// The . - private BindableStarDifficulty createBindable([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo initialRulesetInfo, [CanBeNull] IEnumerable initialMods, - CancellationToken cancellationToken) - { - var bindable = new BindableStarDifficulty(beatmapInfo, cancellationToken); - updateBindable(bindable, initialRulesetInfo, initialMods, cancellationToken); - return bindable; - } - /// /// Updates the value of a with a given ruleset + mods. /// @@ -257,7 +199,7 @@ namespace osu.Game.Beatmaps /// The to update with. /// The s to update with. /// A token that may be used to cancel this update. - private void updateBindable([NotNull] BindableStarDifficulty bindable, [CanBeNull] IRulesetInfo rulesetInfo, [CanBeNull] IEnumerable mods, CancellationToken cancellationToken = default) + private void updateBindable(BindableStarDifficulty bindable, IRulesetInfo? rulesetInfo, IEnumerable? mods, CancellationToken cancellationToken = default) { // GetDifficultyAsync will fall back to existing data from IBeatmapInfo if not locally available // (contrary to GetAsync) @@ -270,7 +212,7 @@ namespace osu.Game.Beatmaps if (cancellationToken.IsCancellationRequested) return; - var starDifficulty = task.GetResultSafely(); + StarDifficulty? starDifficulty = task.GetResultSafely(); if (starDifficulty != null) bindable.Value = starDifficulty.Value; @@ -327,7 +269,7 @@ namespace osu.Game.Beatmaps modSettingChangeTracker?.Dispose(); cancelTrackedBindableUpdate(); - updateScheduler?.Dispose(); + updateScheduler.Dispose(); } public readonly struct DifficultyCacheLookup : IEquatable @@ -337,7 +279,7 @@ namespace osu.Game.Beatmaps public readonly Mod[] OrderedMods; - public DifficultyCacheLookup([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo ruleset, IEnumerable mods) + public DifficultyCacheLookup(BeatmapInfo beatmapInfo, RulesetInfo? ruleset, IEnumerable? mods) { BeatmapInfo = beatmapInfo; // In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset. diff --git a/osu.Game/Stores/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs similarity index 74% rename from osu.Game/Stores/BeatmapImporter.cs rename to osu.Game/Beatmaps/BeatmapImporter.cs index f04a0210ef..3e4d01a9a3 100644 --- a/osu.Game/Stores/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -6,48 +6,36 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; -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.Framework.Testing; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.IO.Archives; -using osu.Game.Models; using osu.Game.Rulesets; -using osu.Game.Rulesets.Objects; -using osu.Game.Skinning; using Realms; -#nullable enable - -namespace osu.Game.Stores +namespace osu.Game.Beatmaps { /// /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. /// [ExcludeFromDynamicCompile] - public abstract class BeatmapImporter : RealmArchiveModelManager, IDisposable + public class BeatmapImporter : RealmArchiveModelImporter { public override IEnumerable HandledExtensions => new[] { ".osz" }; protected override string[] HashableFileTypes => new[] { ".osu" }; - // protected override bool CheckLocalAvailability(RealmBeatmapSet model, System.Linq.IQueryable items) - // => base.CheckLocalAvailability(model, items) || (model.OnlineID > -1)); + public Action? ProcessBeatmap { private get; set; } - private readonly BeatmapOnlineLookupQueue? onlineLookupQueue; - - protected BeatmapImporter(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) + public BeatmapImporter(Storage storage, RealmAccess realm) : base(storage, realm) { - this.onlineLookupQueue = onlineLookupQueue; } protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path).ToLowerInvariant() == ".osz"; @@ -55,7 +43,7 @@ namespace osu.Game.Stores protected override void Populate(BeatmapSetInfo beatmapSet, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default) { if (archive != null) - beatmapSet.Beatmaps.AddRange(createBeatmapDifficulties(beatmapSet.Files, realm)); + beatmapSet.Beatmaps.AddRange(createBeatmapDifficulties(beatmapSet, realm)); foreach (BeatmapInfo b in beatmapSet.Beatmaps) { @@ -71,8 +59,7 @@ namespace osu.Game.Stores bool hadOnlineIDs = beatmapSet.Beatmaps.Any(b => b.OnlineID > 0); - onlineLookupQueue?.Update(beatmapSet); - + // TODO: this may no longer be valid as we aren't doing an online population at this point. // ensure at least one beatmap was able to retrieve or keep an online ID, else drop the set ID. if (hadOnlineIDs && !beatmapSet.Beatmaps.Any(b => b.OnlineID > 0)) { @@ -93,9 +80,8 @@ namespace osu.Game.Stores if (beatmapSet.OnlineID > 0) { - var existingSetWithSameOnlineID = realm.All().SingleOrDefault(b => b.OnlineID == beatmapSet.OnlineID); - - if (existingSetWithSameOnlineID != null) + // OnlineID should really be unique, but to avoid catastrophic failure let's iterate just to be sure. + foreach (var existingSetWithSameOnlineID in realm.All().Where(b => b.OnlineID == beatmapSet.OnlineID)) { existingSetWithSameOnlineID.DeletePending = true; existingSetWithSameOnlineID.OnlineID = -1; @@ -103,11 +89,18 @@ namespace osu.Game.Stores foreach (var b in existingSetWithSameOnlineID.Beatmaps) b.OnlineID = -1; - LogForModel(beatmapSet, $"Found existing beatmap set with same OnlineID ({beatmapSet.OnlineID}). It will be deleted."); + LogForModel(beatmapSet, $"Found existing beatmap set with same OnlineID ({beatmapSet.OnlineID}). It will be disassociated and marked for deletion."); } } } + protected override void PostImport(BeatmapSetInfo model, Realm realm) + { + base.PostImport(model, realm); + + ProcessBeatmap?.Invoke(model); + } + private void validateOnlineIds(BeatmapSetInfo beatmapSet, Realm realm) { var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineID > 0).Select(b => b.OnlineID).ToList(); @@ -169,11 +162,6 @@ namespace osu.Game.Stores existing.DateAdded = DateTimeOffset.UtcNow; } - public override bool IsAvailableLocally(BeatmapSetInfo model) - { - return Realm.Run(realm => realm.All().Any(s => s.OnlineID == model.OnlineID)); - } - public override string HumanisedModelName => "beatmap"; protected override BeatmapSetInfo? CreateModel(ArchiveReader reader) @@ -188,8 +176,17 @@ namespace osu.Game.Stores } Beatmap beatmap; + using (var stream = new LineBufferedReader(reader.GetStream(mapName))) + { + if (stream.PeekLine() == null) + { + Logger.Log($"No content found in first .osu file of beatmap archive ({reader.Name} / {mapName})", LoggingTarget.Database); + return null; + } + beatmap = Decoder.GetDecoder(stream).Decode(stream); + } return new BeatmapSetInfo { @@ -202,23 +199,32 @@ namespace osu.Game.Stores /// /// Create all required s for the provided archive. /// - private List createBeatmapDifficulties(IList files, Realm realm) + private List createBeatmapDifficulties(BeatmapSetInfo beatmapSet, Realm realm) { var beatmaps = new List(); - foreach (var file in files.Where(f => f.Filename.EndsWith(".osu", StringComparison.OrdinalIgnoreCase))) + foreach (var file in beatmapSet.Files.Where(f => f.Filename.EndsWith(".osu", StringComparison.OrdinalIgnoreCase))) { using (var memoryStream = new MemoryStream(Files.Store.Get(file.File.GetStoragePath()))) // we need a memory stream so we can seek { IBeatmap decoded; + using (var lineReader = new LineBufferedReader(memoryStream, true)) + { + if (lineReader.PeekLine() == null) + { + LogForModel(beatmapSet, $"No content found in beatmap file {file.Filename}."); + continue; + } + decoded = Decoder.GetDecoder(lineReader).Decode(lineReader); + } string hash = memoryStream.ComputeSHA2Hash(); if (beatmaps.Any(b => b.Hash == hash)) { - Logger.Log($"Skipping import of {file.Filename} due to duplicate file content.", LoggingTarget.Database); + LogForModel(beatmapSet, $"Skipping import of {file.Filename} due to duplicate file content."); continue; } @@ -229,7 +235,7 @@ namespace osu.Game.Stores if (ruleset?.Available != true) { - Logger.Log($"Skipping import of {file.Filename} due to missing local ruleset {decodedInfo.Ruleset.OnlineID}.", LoggingTarget.Database); + LogForModel(beatmapSet, $"Skipping import of {file.Filename} due to missing local ruleset {decodedInfo.Ruleset.OnlineID}."); continue; } @@ -280,64 +286,11 @@ namespace osu.Game.Stores MD5Hash = memoryStream.ComputeMD5Hash(), }; - updateBeatmapStatistics(beatmap, decoded); - beatmaps.Add(beatmap); } } return beatmaps; } - - private void updateBeatmapStatistics(BeatmapInfo beatmap, IBeatmap decoded) - { - var rulesetInstance = ((IRulesetInfo)beatmap.Ruleset).CreateInstance(); - - decoded.BeatmapInfo.Ruleset = rulesetInstance.RulesetInfo; - - // TODO: this should be done in a better place once we actually need to dynamically update it. - beatmap.StarRating = rulesetInstance.CreateDifficultyCalculator(new DummyConversionBeatmap(decoded)).Calculate().StarRating; - beatmap.Length = calculateLength(decoded); - beatmap.BPM = 60000 / decoded.GetMostCommonBeatLength(); - } - - private double calculateLength(IBeatmap b) - { - if (!b.HitObjects.Any()) - return 0; - - var lastObject = b.HitObjects.Last(); - - //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). - double endTime = lastObject.GetEndTime(); - double startTime = b.HitObjects.First().StartTime; - - return endTime - startTime; - } - - public void Dispose() - { - onlineLookupQueue?.Dispose(); - } - - /// - /// A dummy WorkingBeatmap for the purpose of retrieving a beatmap for star difficulty calculation. - /// - private class DummyConversionBeatmap : WorkingBeatmap - { - private readonly IBeatmap beatmap; - - public DummyConversionBeatmap(IBeatmap beatmap) - : base(beatmap.BeatmapInfo, null) - { - this.beatmap = beatmap; - } - - protected override IBeatmap GetBeatmap() => beatmap; - protected override Texture? GetBackground() => null; - protected override Track? GetBeatmapTrack() => null; - protected internal override ISkin? GetSkin() => null; - public override Stream? GetStream(string storagePath) => null; - } } } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index abc9020dc6..3ee306cc9a 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; +using System.Diagnostics; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; @@ -90,8 +89,19 @@ namespace osu.Game.Beatmaps public double StarRating { get; set; } + [Indexed] public string MD5Hash { get; set; } = string.Empty; + public string OnlineMD5Hash { get; set; } = string.Empty; + + public DateTimeOffset? LastOnlineUpdate { get; set; } + + /// + /// Whether this beatmap matches the online version, based on fetched online metadata. + /// Will return true if no online metadata is available. + /// + public bool MatchesOnlineVersion => LastOnlineUpdate == null || MD5Hash == OnlineMD5Hash; + [JsonIgnore] public bool Hidden { get; set; } @@ -111,6 +121,11 @@ namespace osu.Game.Beatmaps public bool SamplesMatchPlaybackRate { get; set; } = true; + /// + /// The time at which this beatmap was last played by the local user. + /// + public DateTimeOffset? LastPlayed { get; set; } + /// /// The ratio of distance travelled per time unit. /// Generally used to decouple the spacing between hit objects from the enforced "velocity" of the beatmap (see ). @@ -152,14 +167,23 @@ namespace osu.Game.Beatmaps public bool AudioEquals(BeatmapInfo? other) => other != null && BeatmapSet != null && other.BeatmapSet != null - && BeatmapSet.Hash == other.BeatmapSet.Hash - && Metadata.AudioFile == other.Metadata.AudioFile; + && compareFiles(this, other, m => m.AudioFile); public bool BackgroundEquals(BeatmapInfo? other) => other != null && BeatmapSet != null && other.BeatmapSet != null - && BeatmapSet.Hash == other.BeatmapSet.Hash - && Metadata.BackgroundFile == other.Metadata.BackgroundFile; + && compareFiles(this, other, m => m.BackgroundFile); + + private static bool compareFiles(BeatmapInfo x, BeatmapInfo y, Func getFilename) + { + Debug.Assert(x.BeatmapSet != null); + Debug.Assert(y.BeatmapSet != null); + + string? fileHashX = x.BeatmapSet.Files.FirstOrDefault(f => f.Filename == getFilename(x.Metadata))?.File.Hash; + string? fileHashY = y.BeatmapSet.Files.FirstOrDefault(f => f.Filename == getFilename(y.Metadata))?.File.Hash; + + return fileHashX == fileHashY; + } IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata; IBeatmapSetInfo? IBeatmapInfo.BeatmapSet => BeatmapSet; diff --git a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs index eab66b9857..e7ff07fa5d 100644 --- a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Localisation; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index dba457c81c..30456afd2f 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -3,17 +3,22 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; +using System.Text; using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Extensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; +using osu.Game.Beatmaps.Formats; using osu.Game.Database; +using osu.Game.Extensions; using osu.Game.IO.Archives; using osu.Game.Models; using osu.Game.Online.API; @@ -21,57 +26,55 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Skinning; -using osu.Game.Stores; using osu.Game.Utils; -#nullable enable - namespace osu.Game.Beatmaps { /// /// Handles general operations related to global beatmap management. /// [ExcludeFromDynamicCompile] - public class BeatmapManager : IModelManager, IModelFileManager, IModelImporter, IWorkingBeatmapCache, IDisposable + public class BeatmapManager : ModelManager, IModelImporter, IWorkingBeatmapCache { public ITrackStore BeatmapTrackStore { get; } - private readonly BeatmapModelManager beatmapModelManager; + private readonly BeatmapImporter beatmapImporter; private readonly WorkingBeatmapCache workingBeatmapCache; - private readonly BeatmapOnlineLookupQueue? onlineBeatmapLookupQueue; - private readonly RealmAccess realm; + public Action? ProcessBeatmap { private get; set; } - public BeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider? api, AudioManager audioManager, IResourceStore gameResources, GameHost? host = null, WorkingBeatmap? defaultBeatmap = null, bool performOnlineLookups = false) + public BeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider? api, AudioManager audioManager, IResourceStore gameResources, GameHost? host = null, + WorkingBeatmap? defaultBeatmap = null, BeatmapDifficultyCache? difficultyCache = null, bool performOnlineLookups = false) + : base(storage, realm) { - this.realm = realm; - if (performOnlineLookups) { if (api == null) throw new ArgumentNullException(nameof(api), "API must be provided if online lookups are required."); - onlineBeatmapLookupQueue = new BeatmapOnlineLookupQueue(api, storage); + if (difficultyCache == null) + throw new ArgumentNullException(nameof(difficultyCache), "Difficulty cache must be provided if online lookups are required."); } var userResources = new RealmFileStore(realm, storage).Store; BeatmapTrackStore = audioManager.GetTrackStore(userResources); - beatmapModelManager = CreateBeatmapModelManager(storage, realm, rulesets, onlineBeatmapLookupQueue); - workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); + beatmapImporter = CreateBeatmapImporter(storage, realm); + beatmapImporter.ProcessBeatmap = obj => ProcessBeatmap?.Invoke(obj); + beatmapImporter.PostNotification = obj => PostNotification?.Invoke(obj); - beatmapModelManager.WorkingBeatmapCache = workingBeatmapCache; + workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); } - protected virtual WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap? defaultBeatmap, GameHost? host) + protected virtual WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap? defaultBeatmap, + GameHost? host) { return new WorkingBeatmapCache(BeatmapTrackStore, audioManager, resources, storage, defaultBeatmap, host); } - protected virtual BeatmapModelManager CreateBeatmapModelManager(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue? onlineLookupQueue) => - new BeatmapModelManager(realm, storage, onlineLookupQueue); + protected virtual BeatmapImporter CreateBeatmapImporter(Storage storage, RealmAccess realm) => new BeatmapImporter(storage, realm); /// /// Create a new beatmap set, backed by a model, @@ -100,7 +103,7 @@ namespace osu.Game.Beatmaps foreach (BeatmapInfo b in beatmapSet.Beatmaps) b.BeatmapSet = beatmapSet; - var imported = beatmapModelManager.Import(beatmapSet); + var imported = beatmapImporter.ImportModel(beatmapSet); if (imported == null) throw new InvalidOperationException("Failed to import new beatmap"); @@ -170,12 +173,12 @@ namespace osu.Game.Beatmaps private WorkingBeatmap addDifficultyToSet(BeatmapSetInfo targetBeatmapSet, IBeatmap newBeatmap, ISkin beatmapSkin) { // populate circular beatmap set info <-> beatmap info references manually. - // several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()` + // several places like `Save()` or `GetWorkingBeatmap()` // rely on them being freely traversable in both directions for correct operation. targetBeatmapSet.Beatmaps.Add(newBeatmap.BeatmapInfo); newBeatmap.BeatmapInfo.BeatmapSet = targetBeatmapSet; - beatmapModelManager.Save(newBeatmap.BeatmapInfo, newBeatmap, beatmapSkin); + Save(newBeatmap.BeatmapInfo, newBeatmap, beatmapSkin); workingBeatmapCache.Invalidate(targetBeatmapSet); return GetWorkingBeatmap(newBeatmap.BeatmapInfo); @@ -187,7 +190,7 @@ namespace osu.Game.Beatmaps /// The beatmap difficulty to hide. public void Hide(BeatmapInfo beatmapInfo) { - realm.Run(r => + Realm.Run(r => { using (var transaction = r.BeginWrite()) { @@ -206,7 +209,7 @@ namespace osu.Game.Beatmaps /// The beatmap difficulty to restore. public void Restore(BeatmapInfo beatmapInfo) { - realm.Run(r => + Realm.Run(r => { using (var transaction = r.BeginWrite()) { @@ -221,7 +224,7 @@ namespace osu.Game.Beatmaps public void RestoreAll() { - realm.Run(r => + Realm.Run(r => { using (var transaction = r.BeginWrite()) { @@ -239,7 +242,7 @@ namespace osu.Game.Beatmaps /// A list of available . public List GetAllUsableBeatmapSets() { - return realm.Run(r => + return Realm.Run(r => { r.Refresh(); return r.All().Where(b => !b.DeletePending).Detach(); @@ -253,26 +256,15 @@ namespace osu.Game.Beatmaps /// The first result for the provided query, or null if no results were found. public Live? QueryBeatmapSet(Expression> query) { - return realm.Run(r => r.All().FirstOrDefault(query)?.ToLive(realm)); + return Realm.Run(r => r.All().FirstOrDefault(query)?.ToLive(Realm)); } - #region Delegation to BeatmapModelManager (methods which previously existed locally). - /// /// Perform a lookup query on available s. /// /// The query. /// The first result for the provided query, or null if no results were found. - public BeatmapInfo? QueryBeatmap(Expression> query) => beatmapModelManager.QueryBeatmap(query)?.Detach(); - - /// - /// Saves an file against a given . - /// - /// The to save the content against. The file referenced by will be replaced. - /// The content to write. - /// The beatmap content to write, null if to be omitted. - public virtual void Save(BeatmapInfo info, IBeatmap beatmapContent, ISkin? beatmapSkin = null) => - beatmapModelManager.Save(info, beatmapContent, beatmapSkin); + public BeatmapInfo? QueryBeatmap(Expression> query) => Realm.Run(r => r.All().FirstOrDefault(query)?.Detach()); /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. @@ -280,176 +272,212 @@ namespace osu.Game.Beatmaps public IWorkingBeatmap DefaultBeatmap => workingBeatmapCache.DefaultBeatmap; /// - /// Fired when a notification should be presented to the user. + /// Saves an file against a given . /// - public Action PostNotification + /// The to save the content against. The file referenced by will be replaced. + /// The content to write. + /// The beatmap content to write, null if to be omitted. + public virtual void Save(BeatmapInfo beatmapInfo, IBeatmap beatmapContent, ISkin? beatmapSkin = null) { - set => beatmapModelManager.PostNotification = value; + var setInfo = beatmapInfo.BeatmapSet; + Debug.Assert(setInfo != null); + + // Difficulty settings must be copied first due to the clone in `Beatmap<>.BeatmapInfo_Set`. + // This should hopefully be temporary, assuming said clone is eventually removed. + + // Warning: The directionality here is important. Changes have to be copied *from* beatmapContent (which comes from editor and is being saved) + // *to* the beatmapInfo (which is a database model and needs to receive values without the taiko slider velocity multiplier for correct operation). + // CopyTo() will undo such adjustments, while CopyFrom() will not. + beatmapContent.Difficulty.CopyTo(beatmapInfo.Difficulty); + + // All changes to metadata are made in the provided beatmapInfo, so this should be copied to the `IBeatmap` before encoding. + beatmapContent.BeatmapInfo = beatmapInfo; + + using (var stream = new MemoryStream()) + { + using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) + new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); + + stream.Seek(0, SeekOrigin.Begin); + + // AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity. + var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase)); + string targetFilename = createBeatmapFilenameFromMetadata(beatmapInfo); + + // ensure that two difficulties from the set don't point at the same beatmap file. + if (setInfo.Beatmaps.Any(b => b.ID != beatmapInfo.ID && string.Equals(b.Path, targetFilename, StringComparison.OrdinalIgnoreCase))) + throw new InvalidOperationException($"{setInfo.GetDisplayString()} already has a difficulty with the name of '{beatmapInfo.DifficultyName}'."); + + if (existingFileInfo != null) + DeleteFile(setInfo, existingFileInfo); + + beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); + beatmapInfo.Hash = stream.ComputeSHA2Hash(); + + AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo)); + + setInfo.Hash = beatmapImporter.ComputeHash(setInfo); + + Realm.Write(r => + { + var liveBeatmapSet = r.Find(setInfo.ID); + + setInfo.CopyChangesToRealm(liveBeatmapSet); + + ProcessBeatmap?.Invoke(liveBeatmapSet); + }); + } + + Debug.Assert(beatmapInfo.BeatmapSet != null); + + static string createBeatmapFilenameFromMetadata(BeatmapInfo beatmapInfo) + { + var metadata = beatmapInfo.Metadata; + return $"{metadata.Artist} - {metadata.Title} ({metadata.Author.Username}) [{beatmapInfo.DifficultyName}].osu".GetValidArchiveContentFilename(); + } } - #endregion - - #region Implementation of IModelManager - - public bool IsAvailableLocally(BeatmapSetInfo model) + public void DeleteAllVideos() { - return beatmapModelManager.IsAvailableLocally(model); - } - - public bool Delete(BeatmapSetInfo item) - { - return beatmapModelManager.Delete(item); - } - - public void Delete(List items, bool silent = false) - { - beatmapModelManager.Delete(items, silent); + Realm.Write(r => + { + var items = r.All().Where(s => !s.DeletePending && !s.Protected); + DeleteVideos(items.ToList()); + }); } public void Delete(Expression>? filter = null, bool silent = false) { - realm.Run(r => + Realm.Run(r => { var items = r.All().Where(s => !s.DeletePending && !s.Protected); if (filter != null) items = items.Where(filter); - beatmapModelManager.Delete(items.ToList(), silent); + Delete(items.ToList(), silent); }); } - public void DeleteAllVideos() + /// + /// Delete videos from a list of beatmaps. + /// This will post notifications tracking progress. + /// + public void DeleteVideos(List items, bool silent = false) { - realm.Write(r => + if (items.Count == 0) return; + + var notification = new ProgressNotification { - var items = r.All().Where(s => !s.DeletePending && !s.Protected); - beatmapModelManager.DeleteVideos(items.ToList()); - }); + Progress = 0, + Text = $"Preparing to delete all {HumanisedModelName} videos...", + CompletionText = "No videos found to delete!", + State = ProgressNotificationState.Active, + }; + + if (!silent) + PostNotification?.Invoke(notification); + + int i = 0; + int deleted = 0; + + foreach (var b in items) + { + if (notification.State == ProgressNotificationState.Cancelled) + // user requested abort + return; + + var video = b.Files.FirstOrDefault(f => OsuGameBase.VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); + + if (video != null) + { + DeleteFile(b, video); + deleted++; + notification.CompletionText = $"Deleted {deleted} {HumanisedModelName} video(s)!"; + } + + notification.Text = $"Deleting videos from {HumanisedModelName}s ({deleted} deleted)"; + + notification.Progress = (float)++i / items.Count; + } + + notification.State = ProgressNotificationState.Completed; } public void UndeleteAll() { - realm.Run(r => beatmapModelManager.Undelete(r.All().Where(s => s.DeletePending).ToList())); + Realm.Run(r => Undelete(r.All().Where(s => s.DeletePending).ToList())); } - public void Undelete(List items, bool silent = false) - { - beatmapModelManager.Undelete(items, silent); - } - - public void Undelete(BeatmapSetInfo item) - { - beatmapModelManager.Undelete(item); - } - - #endregion - #region Implementation of ICanAcceptFiles - public Task Import(params string[] paths) - { - return beatmapModelManager.Import(paths); - } + public Task Import(params string[] paths) => beatmapImporter.Import(paths); - public Task Import(params ImportTask[] tasks) - { - return beatmapModelManager.Import(tasks); - } + public Task Import(params ImportTask[] tasks) => beatmapImporter.Import(tasks); - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) - { - return beatmapModelManager.Import(notification, tasks); - } + public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => beatmapImporter.Import(notification, tasks); - public Task?> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return beatmapModelManager.Import(task, lowPriority, cancellationToken); - } + public Task?> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => + beatmapImporter.Import(task, batchImport, cancellationToken); - public Task?> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return beatmapModelManager.Import(archive, lowPriority, cancellationToken); - } + public Live? Import(BeatmapSetInfo item, ArchiveReader? archive = null, CancellationToken cancellationToken = default) => + beatmapImporter.ImportModel(item, archive, false, cancellationToken); - public Live? Import(BeatmapSetInfo item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return beatmapModelManager.Import(item, archive, lowPriority, cancellationToken); - } - - public IEnumerable HandledExtensions => beatmapModelManager.HandledExtensions; + public IEnumerable HandledExtensions => beatmapImporter.HandledExtensions; #endregion #region Implementation of IWorkingBeatmapCache - public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo? importedBeatmap) + /// + /// Retrieve a instance for the provided + /// + /// The beatmap to lookup. + /// Whether to force a refetch from the database to ensure is up-to-date. + /// A instance correlating to the provided . + public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo? beatmapInfo, bool refetch = false) { - // Detached sets don't come with files. - // If we seem to be missing files, now is a good time to re-fetch. - if (importedBeatmap?.BeatmapSet?.Files.Count == 0) + if (beatmapInfo != null) { - realm.Run(r => + // Detached sets don't come with files. + // If we seem to be missing files, now is a good time to re-fetch. + if (refetch || beatmapInfo.IsManaged || beatmapInfo.BeatmapSet?.Files.Count == 0) { - var refetch = r.Find(importedBeatmap.ID)?.Detach(); + workingBeatmapCache.Invalidate(beatmapInfo); - if (refetch != null) - importedBeatmap = refetch; - }); + Guid id = beatmapInfo.ID; + beatmapInfo = Realm.Run(r => r.Find(id)?.Detach()) ?? beatmapInfo; + } + + Debug.Assert(beatmapInfo.IsManaged != true); } - return workingBeatmapCache.GetWorkingBeatmap(importedBeatmap); - } - - public WorkingBeatmap GetWorkingBeatmap(Live? importedBeatmap) - { - WorkingBeatmap working = workingBeatmapCache.GetWorkingBeatmap(null); - - importedBeatmap?.PerformRead(b => working = workingBeatmapCache.GetWorkingBeatmap(b)); - - return working; + return workingBeatmapCache.GetWorkingBeatmap(beatmapInfo); } + WorkingBeatmap IWorkingBeatmapCache.GetWorkingBeatmap(BeatmapInfo beatmapInfo) => GetWorkingBeatmap(beatmapInfo); void IWorkingBeatmapCache.Invalidate(BeatmapSetInfo beatmapSetInfo) => workingBeatmapCache.Invalidate(beatmapSetInfo); void IWorkingBeatmapCache.Invalidate(BeatmapInfo beatmapInfo) => workingBeatmapCache.Invalidate(beatmapInfo); - #endregion - - #region Implementation of IModelFileManager - - public void ReplaceFile(BeatmapSetInfo model, RealmNamedFileUsage file, Stream contents) + public event Action? OnInvalidated { - beatmapModelManager.ReplaceFile(model, file, contents); + add => workingBeatmapCache.OnInvalidated += value; + remove => workingBeatmapCache.OnInvalidated -= value; } - public void DeleteFile(BeatmapSetInfo model, RealmNamedFileUsage file) - { - beatmapModelManager.DeleteFile(model, file); - } - - public void AddFile(BeatmapSetInfo model, Stream contents, string filename) - { - beatmapModelManager.AddFile(model, contents, filename); - } - - #endregion - - #region Implementation of IDisposable - - public void Dispose() - { - onlineBeatmapLookupQueue?.Dispose(); - } + public override bool IsAvailableLocally(BeatmapSetInfo model) => Realm.Run(realm => realm.All().Any(s => s.OnlineID == model.OnlineID)); #endregion #region Implementation of IPostImports - public Action>>? PostImport + public Action>>? PresentImport { - set => beatmapModelManager.PostImport = value; + set => beatmapImporter.PresentImport = value; } #endregion + + public override string HumanisedModelName => "beatmap"; } } diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 3a24c4808f..feb9d34f44 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -10,8 +10,6 @@ using osu.Game.Users; using osu.Game.Utils; using Realms; -#nullable enable - namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] diff --git a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs index 7e7d1babf0..738bdb0839 100644 --- a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Localisation; diff --git a/osu.Game/Beatmaps/BeatmapModelDownloader.cs b/osu.Game/Beatmaps/BeatmapModelDownloader.cs index d31730ca15..4295def5c3 100644 --- a/osu.Game/Beatmaps/BeatmapModelDownloader.cs +++ b/osu.Game/Beatmaps/BeatmapModelDownloader.cs @@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps protected override ArchiveDownloadRequest CreateDownloadRequest(IBeatmapSetInfo set, bool minimiseDownloadSize) => new DownloadBeatmapSetRequest(set, minimiseDownloadSize); - public override ArchiveDownloadRequest GetExistingDownload(IBeatmapSetInfo model) + public override ArchiveDownloadRequest? GetExistingDownload(IBeatmapSetInfo model) => CurrentDownloads.Find(r => r.Model.OnlineID == model.OnlineID); public BeatmapModelDownloader(IModelImporter beatmapImporter, IAPIProvider api) diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs deleted file mode 100644 index 277047348e..0000000000 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (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.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using osu.Framework.Extensions; -using osu.Framework.Platform; -using osu.Framework.Testing; -using osu.Game.Beatmaps.Formats; -using osu.Game.Database; -using osu.Game.Extensions; -using osu.Game.Skinning; -using osu.Game.Stores; -using osu.Game.Overlays.Notifications; - -#nullable enable - -namespace osu.Game.Beatmaps -{ - [ExcludeFromDynamicCompile] - public class BeatmapModelManager : BeatmapImporter - { - /// - /// The game working beatmap cache, used to invalidate entries on changes. - /// - public IWorkingBeatmapCache? WorkingBeatmapCache { private get; set; } - - public override IEnumerable HandledExtensions => new[] { ".osz" }; - - protected override string[] HashableFileTypes => new[] { ".osu" }; - - public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; - - public BeatmapModelManager(RealmAccess realm, Storage storage, BeatmapOnlineLookupQueue? onlineLookupQueue = null) - : base(realm, storage, onlineLookupQueue) - { - } - - protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osz"; - - /// - /// Saves an file against a given . - /// - /// The to save the content against. The file referenced by will be replaced. - /// The content to write. - /// The beatmap content to write, null if to be omitted. - public void Save(BeatmapInfo beatmapInfo, IBeatmap beatmapContent, ISkin? beatmapSkin = null) - { - var setInfo = beatmapInfo.BeatmapSet; - Debug.Assert(setInfo != null); - - // Difficulty settings must be copied first due to the clone in `Beatmap<>.BeatmapInfo_Set`. - // This should hopefully be temporary, assuming said clone is eventually removed. - - // Warning: The directionality here is important. Changes have to be copied *from* beatmapContent (which comes from editor and is being saved) - // *to* the beatmapInfo (which is a database model and needs to receive values without the taiko slider velocity multiplier for correct operation). - // CopyTo() will undo such adjustments, while CopyFrom() will not. - beatmapContent.Difficulty.CopyTo(beatmapInfo.Difficulty); - - // All changes to metadata are made in the provided beatmapInfo, so this should be copied to the `IBeatmap` before encoding. - beatmapContent.BeatmapInfo = beatmapInfo; - - using (var stream = new MemoryStream()) - { - using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) - new LegacyBeatmapEncoder(beatmapContent, beatmapSkin).Encode(sw); - - stream.Seek(0, SeekOrigin.Begin); - - // AddFile generally handles updating/replacing files, but this is a case where the filename may have also changed so let's delete for simplicity. - var existingFileInfo = setInfo.Files.SingleOrDefault(f => string.Equals(f.Filename, beatmapInfo.Path, StringComparison.OrdinalIgnoreCase)); - string targetFilename = getFilename(beatmapInfo); - - // ensure that two difficulties from the set don't point at the same beatmap file. - if (setInfo.Beatmaps.Any(b => b.ID != beatmapInfo.ID && string.Equals(b.Path, targetFilename, StringComparison.OrdinalIgnoreCase))) - throw new InvalidOperationException($"{setInfo.GetDisplayString()} already has a difficulty with the name of '{beatmapInfo.DifficultyName}'."); - - if (existingFileInfo != null) - DeleteFile(setInfo, existingFileInfo); - - beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); - beatmapInfo.Hash = stream.ComputeSHA2Hash(); - - AddFile(setInfo, stream, getFilename(beatmapInfo)); - Update(setInfo); - } - - WorkingBeatmapCache?.Invalidate(beatmapInfo); - } - - private static string getFilename(BeatmapInfo beatmapInfo) - { - var metadata = beatmapInfo.Metadata; - return $"{metadata.Artist} - {metadata.Title} ({metadata.Author.Username}) [{beatmapInfo.DifficultyName}].osu".GetValidArchiveContentFilename(); - } - - /// - /// Perform a lookup query on available s. - /// - /// The query. - /// The first result for the provided query, or null if no results were found. - public BeatmapInfo? QueryBeatmap(Expression> query) - { - return Realm.Run(realm => realm.All().FirstOrDefault(query)?.Detach()); - } - - public void Update(BeatmapSetInfo item) - { - Realm.Write(r => - { - var existing = r.Find(item.ID); - item.CopyChangesToRealm(existing); - }); - } - - /// - /// Delete videos from a list of beatmaps. - /// This will post notifications tracking progress. - /// - public void DeleteVideos(List items, bool silent = false) - { - if (items.Count == 0) return; - - var notification = new ProgressNotification - { - Progress = 0, - Text = $"Preparing to delete all {HumanisedModelName} videos...", - CompletionText = "No videos found to delete!", - State = ProgressNotificationState.Active, - }; - - if (!silent) - PostNotification?.Invoke(notification); - - int i = 0; - int deleted = 0; - - foreach (var b in items) - { - if (notification.State == ProgressNotificationState.Cancelled) - // user requested abort - return; - - var video = b.Files.FirstOrDefault(f => VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); - - if (video != null) - { - DeleteFile(b, video); - deleted++; - notification.CompletionText = $"Deleted {deleted} {HumanisedModelName} video(s)!"; - } - - notification.Text = $"Deleting videos from {HumanisedModelName}s ({deleted} deleted)"; - - notification.Progress = (float)++i / items.Count; - } - - notification.State = ProgressNotificationState.Completed; - } - } -} diff --git a/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs b/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs new file mode 100644 index 0000000000..b6968f4e06 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.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 System.Linq; +using osu.Framework.Graphics; +using osu.Game.Database; +using osu.Game.Online.Metadata; + +namespace osu.Game.Beatmaps +{ + /// + /// Ingests any changes that happen externally to the client, reprocessing as required. + /// + public class BeatmapOnlineChangeIngest : Component + { + private readonly BeatmapUpdater beatmapUpdater; + private readonly RealmAccess realm; + private readonly MetadataClient metadataClient; + + public BeatmapOnlineChangeIngest(BeatmapUpdater beatmapUpdater, RealmAccess realm, MetadataClient metadataClient) + { + this.beatmapUpdater = beatmapUpdater; + this.realm = realm; + this.metadataClient = metadataClient; + + metadataClient.ChangedBeatmapSetsArrived += changesDetected; + } + + private void changesDetected(int[] beatmapSetIds) + { + // May want to batch incoming updates further if the background realm operations ever becomes a concern. + realm.Run(r => + { + foreach (int id in beatmapSetIds) + { + var matchingSet = r.All().FirstOrDefault(s => s.OnlineID == id); + + if (matchingSet != null) + beatmapUpdater.Queue(matchingSet.ToLive(realm)); + } + }); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + metadataClient.ChangedBeatmapSetsArrived -= changesDetected; + } + } +} diff --git a/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs b/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs index fc39887e79..d3be240d4c 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.IO; @@ -17,7 +19,6 @@ using osu.Framework.Threading; using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.API.Requests; -using osu.Game.Stores; using SharpCompress.Compressors; using SharpCompress.Compressors.BZip2; @@ -101,6 +102,12 @@ namespace osu.Game.Beatmaps beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None; beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID; + beatmapInfo.BeatmapSet.DateRanked = res.BeatmapSet?.Ranked; + beatmapInfo.BeatmapSet.DateSubmitted = res.BeatmapSet?.Submitted; + + beatmapInfo.OnlineMD5Hash = res.MD5Hash; + beatmapInfo.LastOnlineUpdate = res.LastUpdated; + beatmapInfo.OnlineID = res.OnlineID; beatmapInfo.Metadata.Author.OnlineID = res.AuthorID; @@ -189,7 +196,8 @@ namespace osu.Game.Beatmaps using (var cmd = db.CreateCommand()) { - cmd.CommandText = "SELECT beatmapset_id, beatmap_id, approved, user_id FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineID OR filename = @Path"; + cmd.CommandText = + "SELECT beatmapset_id, beatmap_id, approved, user_id, checksum, last_update FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineID OR filename = @Path"; cmd.Parameters.Add(new SqliteParameter("@MD5Hash", beatmapInfo.MD5Hash)); cmd.Parameters.Add(new SqliteParameter("@OnlineID", beatmapInfo.OnlineID)); @@ -207,10 +215,13 @@ namespace osu.Game.Beatmaps beatmapInfo.BeatmapSet.Status = status; beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0); + // TODO: DateSubmitted and DateRanked are not provided by local cache. beatmapInfo.OnlineID = reader.GetInt32(1); - beatmapInfo.Metadata.Author.OnlineID = reader.GetInt32(3); + beatmapInfo.OnlineMD5Hash = reader.GetString(4); + beatmapInfo.LastOnlineUpdate = reader.GetDateTimeOffset(5); + logForModel(set, $"Cached local retrieval for {beatmapInfo}."); return true; } diff --git a/osu.Game/Beatmaps/BeatmapOnlineStatus.cs b/osu.Game/Beatmaps/BeatmapOnlineStatus.cs index 7ac25b7b75..ced85e0908 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineStatus.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineStatus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index cdeaab06ed..8f3d0b7445 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs index 3d41f59b3d..051366fb99 100644 --- a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel.DataAnnotations; using osu.Game.Database; using osu.Game.IO; diff --git a/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs b/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs index 8a576e396a..b2d4cac210 100644 --- a/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 9a4207d5cf..b404f0b34d 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -12,8 +12,6 @@ using osu.Game.Extensions; using osu.Game.Models; using Realms; -#nullable enable - namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] @@ -28,6 +26,16 @@ namespace osu.Game.Beatmaps public DateTimeOffset DateAdded { get; set; } + /// + /// The date this beatmap set was first submitted. + /// + public DateTimeOffset? DateSubmitted { get; set; } + + /// + /// The date this beatmap set was ranked. + /// + public DateTimeOffset? DateRanked { get; set; } + [JsonIgnore] public IBeatmapMetadataInfo Metadata => Beatmaps.FirstOrDefault()?.Metadata ?? new BeatmapMetadata(); @@ -95,5 +103,7 @@ namespace osu.Game.Beatmaps IEnumerable IBeatmapSetInfo.Beatmaps => Beatmaps; IEnumerable IHasNamedFiles.Files => Files; + + public bool AllBeatmapsUpToDate => Beatmaps.All(b => b.MatchesOnlineVersion); } } diff --git a/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs b/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs index 6a19616a97..cea0063814 100644 --- a/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs b/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs index 14a63f3279..12424b797c 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineCovers.cs b/osu.Game/Beatmaps/BeatmapSetOnlineCovers.cs index aad31befa8..b76496b145 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineCovers.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineCovers.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs index e727e2c37f..ad2e994d3e 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps { public struct BeatmapSetOnlineGenre diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs index 658e5a4005..c71c279086 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps { public struct BeatmapSetOnlineLanguage diff --git a/osu.Game/Beatmaps/BeatmapStatistic.cs b/osu.Game/Beatmaps/BeatmapStatistic.cs index 94ebb56a5c..13e0e4ad5e 100644 --- a/osu.Game/Beatmaps/BeatmapStatistic.cs +++ b/osu.Game/Beatmaps/BeatmapStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Beatmaps/BeatmapStatisticIcon.cs b/osu.Game/Beatmaps/BeatmapStatisticIcon.cs index 181fb540df..8002910b52 100644 --- a/osu.Game/Beatmaps/BeatmapStatisticIcon.cs +++ b/osu.Game/Beatmaps/BeatmapStatisticIcon.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Humanizer; +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Extensions; namespace osu.Game.Beatmaps { @@ -23,7 +25,7 @@ namespace osu.Game.Beatmaps [BackgroundDependencyLoader] private void load(TextureStore textures) { - Texture = textures.Get($"Icons/BeatmapDetails/{iconType.ToString().Kebaberize()}"); + Texture = textures.Get($"Icons/BeatmapDetails/{iconType.ToString().ToKebabCase()}"); } } diff --git a/osu.Game/Beatmaps/BeatmapUpdater.cs b/osu.Game/Beatmaps/BeatmapUpdater.cs new file mode 100644 index 0000000000..d2c5e5616a --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapUpdater.cs @@ -0,0 +1,99 @@ +// Copyright (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 System.Linq; +using System.Threading.Tasks; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Database; +using osu.Game.Online.API; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Beatmaps +{ + /// + /// Handles all processing required to ensure a local beatmap is in a consistent state with any changes. + /// + public class BeatmapUpdater : IDisposable + { + private readonly IWorkingBeatmapCache workingBeatmapCache; + private readonly BeatmapOnlineLookupQueue onlineLookupQueue; + private readonly BeatmapDifficultyCache difficultyCache; + + public BeatmapUpdater(IWorkingBeatmapCache workingBeatmapCache, BeatmapDifficultyCache difficultyCache, IAPIProvider api, Storage storage) + { + this.workingBeatmapCache = workingBeatmapCache; + this.difficultyCache = difficultyCache; + + onlineLookupQueue = new BeatmapOnlineLookupQueue(api, storage); + } + + /// + /// Queue a beatmap for background processing. + /// + public void Queue(Live beatmap) + { + Logger.Log($"Queueing change for local beatmap {beatmap}"); + Task.Factory.StartNew(() => beatmap.PerformRead(Process)); + } + + /// + /// Run all processing on a beatmap immediately. + /// + public void Process(BeatmapSetInfo beatmapSet) => beatmapSet.Realm.Write(r => + { + // Before we use below, we want to invalidate. + workingBeatmapCache.Invalidate(beatmapSet); + + // TODO: this call currently uses the local `online.db` lookup. + // We probably don't want this to happen after initial import (as the data may be stale). + onlineLookupQueue.Update(beatmapSet); + + foreach (var beatmap in beatmapSet.Beatmaps) + { + difficultyCache.Invalidate(beatmap); + + var working = workingBeatmapCache.GetWorkingBeatmap(beatmap); + var ruleset = working.BeatmapInfo.Ruleset.CreateInstance(); + + Debug.Assert(ruleset != null); + + var calculator = ruleset.CreateDifficultyCalculator(working); + + beatmap.StarRating = calculator.Calculate().StarRating; + beatmap.Length = calculateLength(working.Beatmap); + beatmap.BPM = 60000 / working.Beatmap.GetMostCommonBeatLength(); + } + + // And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required. + workingBeatmapCache.Invalidate(beatmapSet); + }); + + private double calculateLength(IBeatmap b) + { + if (!b.HitObjects.Any()) + return 0; + + var lastObject = b.HitObjects.Last(); + + //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). + double endTime = lastObject.GetEndTime(); + double startTime = b.HitObjects.First().StartTime; + + return endTime - startTime; + } + + #region Implementation of IDisposable + + public void Dispose() + { + if (onlineLookupQueue.IsNotNull()) + onlineLookupQueue.Dispose(); + } + + #endregion + } +} diff --git a/osu.Game/Beatmaps/BeatmapUserSettings.cs b/osu.Game/Beatmaps/BeatmapUserSettings.cs index 5c71bf34b1..1d993e6d67 100644 --- a/osu.Game/Beatmaps/BeatmapUserSettings.cs +++ b/osu.Game/Beatmaps/BeatmapUserSettings.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable using Realms; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 4079a0cd5f..56a432aec4 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -9,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.ControlPoints { - public abstract class ControlPoint : IComparable, IDeepCloneable + public abstract class ControlPoint : IComparable, IDeepCloneable, IEquatable { /// /// The time at which the control point takes effect. @@ -28,7 +28,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// An existing control point to compare with. /// Whether this is redundant when placed alongside . - public abstract bool IsRedundant(ControlPoint existing); + public abstract bool IsRedundant(ControlPoint? existing); /// /// Create an unbound copy of this control point. @@ -46,5 +46,20 @@ namespace osu.Game.Beatmaps.ControlPoints { Time = other.Time; } + + public sealed override bool Equals(object? obj) + => obj is ControlPoint otherControlPoint + && Equals(otherControlPoint); + + public virtual bool Equals(ControlPoint? other) + { + if (ReferenceEquals(other, null)) return false; + if (ReferenceEquals(other, this)) return true; + + return Time == other.Time; + } + + // ReSharper disable once NonReadonlyMemberInGetHashCode + public override int GetHashCode() => Time.GetHashCode(); } } diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs index cb73ce884e..db479f0e5b 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointGroup.cs @@ -7,10 +7,10 @@ using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { - public class ControlPointGroup : IComparable + public class ControlPointGroup : IComparable, IEquatable { - public event Action ItemAdded; - public event Action ItemRemoved; + public event Action? ItemAdded; + public event Action? ItemRemoved; /// /// The time at which the control point takes effect. @@ -46,5 +46,23 @@ namespace osu.Game.Beatmaps.ControlPoints controlPoints.Remove(point); ItemRemoved?.Invoke(point); } + + public sealed override bool Equals(object? obj) + => obj is ControlPointGroup otherGroup + && Equals(otherGroup); + + public virtual bool Equals(ControlPointGroup? other) + => other != null + && Time == other.Time + && ControlPoints.SequenceEqual(other.ControlPoints); + + public override int GetHashCode() + { + HashCode hashCode = new HashCode(); + hashCode.Add(Time); + foreach (var point in controlPoints) + hashCode.Add(point); + return hashCode.ToHashCode(); + } } } diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index af03d639be..4be6b5eede 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -252,12 +254,12 @@ namespace osu.Game.Beatmaps.ControlPoints switch (newPoint) { - case TimingControlPoint _: + case TimingControlPoint: // Timing points are a special case and need to be added regardless of fallback availability. existing = BinarySearch(TimingPoints, time); break; - case EffectControlPoint _: + case EffectControlPoint: existing = EffectPointAt(time); break; } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index bf7ed8e6f5..c199d1da59 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,6 +1,7 @@ // Copyright (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.Game.Graphics; using osuTK.Graphics; @@ -10,7 +11,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// Note that going forward, this control point type should always be assigned directly to HitObjects. /// - public class DifficultyControlPoint : ControlPoint + public class DifficultyControlPoint : ControlPoint, IEquatable { public static readonly DifficultyControlPoint DEFAULT = new DifficultyControlPoint { @@ -39,7 +40,7 @@ namespace osu.Game.Beatmaps.ControlPoints set => SliderVelocityBindable.Value = value; } - public override bool IsRedundant(ControlPoint existing) + public override bool IsRedundant(ControlPoint? existing) => existing is DifficultyControlPoint existingDifficulty && SliderVelocity == existingDifficulty.SliderVelocity; @@ -49,5 +50,15 @@ namespace osu.Game.Beatmaps.ControlPoints base.CopyFrom(other); } + + public override bool Equals(ControlPoint? other) + => other is DifficultyControlPoint otherDifficultyControlPoint + && Equals(otherDifficultyControlPoint); + + public bool Equals(DifficultyControlPoint? other) + => base.Equals(other) + && SliderVelocity == other.SliderVelocity; + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), SliderVelocity); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 7f550a52fc..ead07b4eaa 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,13 +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 osu.Framework.Bindables; using osu.Game.Graphics; using osuTK.Graphics; namespace osu.Game.Beatmaps.ControlPoints { - public class EffectControlPoint : ControlPoint + public class EffectControlPoint : ControlPoint, IEquatable { public static readonly EffectControlPoint DEFAULT = new EffectControlPoint { @@ -66,7 +67,7 @@ namespace osu.Game.Beatmaps.ControlPoints set => KiaiModeBindable.Value = value; } - public override bool IsRedundant(ControlPoint existing) + public override bool IsRedundant(ControlPoint? existing) => !OmitFirstBarLine && existing is EffectControlPoint existingEffect && KiaiMode == existingEffect.KiaiMode @@ -81,5 +82,17 @@ namespace osu.Game.Beatmaps.ControlPoints base.CopyFrom(other); } + + public override bool Equals(ControlPoint? other) + => other is EffectControlPoint otherEffectControlPoint + && Equals(otherEffectControlPoint); + + public bool Equals(EffectControlPoint? other) + => base.Equals(other) + && OmitFirstBarLine == other.OmitFirstBarLine + && ScrollSpeed == other.ScrollSpeed + && KiaiMode == other.KiaiMode; + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), OmitFirstBarLine, ScrollSpeed, KiaiMode); } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index fb489f73b1..78dec67937 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,6 +1,7 @@ // Copyright (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.Game.Audio; using osu.Game.Graphics; @@ -11,7 +12,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// Note that going forward, this control point type should always be assigned directly to HitObjects. /// - public class SampleControlPoint : ControlPoint + public class SampleControlPoint : ControlPoint, IEquatable { public const string DEFAULT_BANK = "normal"; @@ -71,7 +72,7 @@ namespace osu.Game.Beatmaps.ControlPoints public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) => hitSampleInfo.With(newBank: hitSampleInfo.Bank ?? SampleBank, newVolume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume); - public override bool IsRedundant(ControlPoint existing) + public override bool IsRedundant(ControlPoint? existing) => existing is SampleControlPoint existingSample && SampleBank == existingSample.SampleBank && SampleVolume == existingSample.SampleVolume; @@ -83,5 +84,16 @@ namespace osu.Game.Beatmaps.ControlPoints base.CopyFrom(other); } + + public override bool Equals(ControlPoint? other) + => other is SampleControlPoint otherSampleControlPoint + && Equals(otherSampleControlPoint); + + public bool Equals(SampleControlPoint? other) + => base.Equals(other) + && SampleBank == other.SampleBank + && SampleVolume == other.SampleVolume; + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), SampleBank, SampleVolume); } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 3a7c8b2ec0..23d4d10fd8 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,8 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - +using System; using osu.Framework.Bindables; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; @@ -10,7 +9,7 @@ using osuTK.Graphics; namespace osu.Game.Beatmaps.ControlPoints { - public class TimingControlPoint : ControlPoint + public class TimingControlPoint : ControlPoint, IEquatable { /// /// The time signature at this control point. @@ -70,7 +69,7 @@ namespace osu.Game.Beatmaps.ControlPoints public double BPM => 60000 / BeatLength; // Timing points are never redundant as they can change the time signature. - public override bool IsRedundant(ControlPoint existing) => false; + public override bool IsRedundant(ControlPoint? existing) => false; public override void CopyFrom(ControlPoint other) { @@ -79,5 +78,16 @@ namespace osu.Game.Beatmaps.ControlPoints base.CopyFrom(other); } + + public override bool Equals(ControlPoint? other) + => other is TimingControlPoint otherTimingControlPoint + && Equals(otherTimingControlPoint); + + public bool Equals(TimingControlPoint? other) + => base.Equals(other) + && TimeSignature.Equals(other.TimeSignature) + && BeatLength.Equals(other.BeatLength); + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), TimeSignature, BeatLength); } } diff --git a/osu.Game/Beatmaps/CountdownType.cs b/osu.Game/Beatmaps/CountdownType.cs index 73f85bf701..7fb3de74fb 100644 --- a/osu.Game/Beatmaps/CountdownType.cs +++ b/osu.Game/Beatmaps/CountdownType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/DifficultyRating.cs b/osu.Game/Beatmaps/DifficultyRating.cs index f0ee0ad705..478c0e36df 100644 --- a/osu.Game/Beatmaps/DifficultyRating.cs +++ b/osu.Game/Beatmaps/DifficultyRating.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps { public enum DifficultyRating diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs index 4629b20569..ed2d6cd3a8 100644 --- a/osu.Game/Beatmaps/DifficultyRecommender.cs +++ b/osu.Game/Beatmaps/DifficultyRecommender.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index 916df429a4..4ba16839f5 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs index 6ab92a2ba2..4dd3a56244 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapDownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index 19026638ba..88d4991c5d 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs b/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs index 5ebdee0b09..80af4108c7 100644 --- a/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BundledBeatmapDownloader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -100,7 +102,7 @@ namespace osu.Game.Beatmaps.Drawables // Matches osu-stable, in order to provide new users with roughly the same randomised selection of bundled beatmaps. var random = new LegacyRandom(DateTime.UtcNow.Year * 1000 + (DateTime.UtcNow.DayOfYear / 7)); - downloadableFilenames.AddRange(sourceFilenames.OrderBy(x => random.NextDouble()).Take(limit ?? int.MaxValue)); + downloadableFilenames.AddRange(sourceFilenames.OrderBy(_ => random.NextDouble()).Take(limit ?? int.MaxValue)); } catch { } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 08aaa8da42..b9e0a4e6cb 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs index 1aaa72f5f0..bfec391b1d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs index 392f5d1bfa..64a28c5394 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs index eeb86f4702..9489116530 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs index ffb4e0c540..d55622d7aa 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 7826d64296..4b9e5d9ae4 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs index 2d411ad344..7ba677e5dc 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs index c1ba521925..d9ce64879f 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs index 098265506d..1f6538a890 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps.Drawables.Cards { /// diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs index f11a5916e1..55d3f0b969 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs index 82523cc865..8f8a47c199 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps.Drawables.Cards.Buttons; using osu.Game.Beatmaps.Drawables.Cards.Statistics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs index e362e3abeb..c5b251cc2b 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs index c94e335e8f..fdb43cb47e 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs index 9fed2fde6f..bc0fcb92bb 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/FavouriteButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; @@ -62,7 +64,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons }; favouriteRequest.Failure += e => { - Logger.Error(e, $"Failed to {actionType.ToString().ToLower()} beatmap: {e.Message}"); + Logger.Error(e, $"Failed to {actionType.ToString().ToLowerInvariant()} beatmap: {e.Message}"); Enabled.Value = true; }; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs index 9a6a3c01b7..127c5bd903 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs index f7bab26666..18eab09465 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs index 3a2cb80a8d..107c126eb5 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs index adde72d1e8..a80a7998a5 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs index fe37616755..7d70f3c4cd 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/HoverHandlingContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs index 1b2c5d3ffc..aad71610a5 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs index 9dbe5a9114..f6fc3070aa 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardDateStatistic.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs index f46926284f..89a4687500 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/BeatmapCardStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs index d924fd938b..cef1f630ed 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Humanizer; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs index 521d1a5f21..26b90ba0c0 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs index 23bd6ef0a9..4f3605c138 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs index d8f0c36bd9..f66d51de5d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Humanizer; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs index 2ebf9107f5..dcb2c3c760 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs index b81e18b0dd..9ca1e5c4c4 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 82be0559a7..679e9c3665 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -1,10 +1,6 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (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.Threading; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -14,19 +10,17 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; using osuTK; using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip + public class DifficultyIcon : CompositeDrawable, IHasCustomTooltip, IHasCurrentValue { - private readonly Container iconContainer; - /// /// Size of this difficulty icon. /// @@ -36,57 +30,53 @@ namespace osu.Game.Beatmaps.Drawables set => iconContainer.Size = value; } - [NotNull] - private readonly IBeatmapInfo beatmapInfo; + /// + /// Whether to display a tooltip on hover. Only works if a beatmap was provided at construction time. + /// + public bool ShowTooltip { get; set; } = true; + + private readonly IBeatmapInfo? beatmap; - [CanBeNull] private readonly IRulesetInfo ruleset; - [CanBeNull] - private readonly IReadOnlyList mods; + private Drawable background = null!; - private readonly bool shouldShowTooltip; + private readonly Container iconContainer; - private readonly bool performBackgroundDifficultyLookup; + private readonly BindableWithCurrent difficulty = new BindableWithCurrent(); - private readonly Bindable difficultyBindable = new Bindable(); - - private Drawable background; - - /// - /// Creates a new with a given and combination. - /// - /// The beatmap to show the difficulty of. - /// The ruleset to show the difficulty with. - /// The mods to show the difficulty with. - /// Whether to display a tooltip when hovered. - /// Whether to perform difficulty lookup (including calculation if necessary). - public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo ruleset, [CanBeNull] IReadOnlyList mods, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true) - : this(beatmapInfo, shouldShowTooltip, performBackgroundDifficultyLookup) + public virtual Bindable Current { - this.ruleset = ruleset ?? beatmapInfo.Ruleset; - this.mods = mods ?? Array.Empty(); - } - - /// - /// Creates a new that follows the currently-selected ruleset and mods. - /// - /// The beatmap to show the difficulty of. - /// Whether to display a tooltip when hovered. - /// Whether to perform difficulty lookup (including calculation if necessary). - public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true) - { - this.beatmapInfo = beatmapInfo ?? throw new ArgumentNullException(nameof(beatmapInfo)); - this.shouldShowTooltip = shouldShowTooltip; - this.performBackgroundDifficultyLookup = performBackgroundDifficultyLookup; - - AutoSizeAxes = Axes.Both; - - InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; + get => difficulty.Current; + set => difficulty.Current = value; } [Resolved] - private IRulesetStore rulesets { get; set; } + private IRulesetStore rulesets { get; set; } = null!; + + /// + /// Creates a new . Will use provided beatmap's for initial value. + /// + /// The beatmap to be displayed in the tooltip, and to be used for the initial star rating value. + /// An optional ruleset to be used for the icon display, in place of the beatmap's ruleset. + public DifficultyIcon(IBeatmapInfo beatmap, IRulesetInfo? ruleset = null) + : this(ruleset ?? beatmap.Ruleset) + { + this.beatmap = beatmap; + Current.Value = new StarDifficulty(beatmap.StarRating, 0); + } + + /// + /// Creates a new without an associated beatmap. + /// + /// The ruleset to be used for the icon display. + public DifficultyIcon(IRulesetInfo ruleset) + { + this.ruleset = ruleset; + + AutoSizeAxes = Axes.Both; + InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; + } [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -109,7 +99,6 @@ namespace osu.Game.Beatmaps.Drawables Child = background = new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.ForStarDifficulty(beatmapInfo.StarRating) // Default value that will be re-populated once difficulty calculation completes }, }, new ConstrainedIconContainer @@ -122,17 +111,12 @@ namespace osu.Game.Beatmaps.Drawables }, }; - if (performBackgroundDifficultyLookup) - iconContainer.Add(new DelayedLoadUnloadWrapper(() => new DifficultyRetriever(beatmapInfo, ruleset, mods) { StarDifficulty = { BindTarget = difficultyBindable } }, 0)); - else - difficultyBindable.Value = new StarDifficulty(beatmapInfo.StarRating, 0); - - difficultyBindable.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars)); + Current.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars), true); } private Drawable getRulesetIcon() { - int? onlineID = (ruleset ?? beatmapInfo.Ruleset).OnlineID; + int? onlineID = ruleset.OnlineID; if (onlineID >= 0 && rulesets.GetRuleset(onlineID.Value)?.CreateInstance() is Ruleset rulesetInstance) return rulesetInstance.CreateIcon(); @@ -140,51 +124,10 @@ namespace osu.Game.Beatmaps.Drawables return new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }; } - ITooltip IHasCustomTooltip.GetCustomTooltip() => new DifficultyIconTooltip(); + ITooltip IHasCustomTooltip. + GetCustomTooltip() => new DifficultyIconTooltip(); - DifficultyIconTooltipContent IHasCustomTooltip.TooltipContent => shouldShowTooltip ? new DifficultyIconTooltipContent(beatmapInfo, difficultyBindable) : null; - - private class DifficultyRetriever : Component - { - public readonly Bindable StarDifficulty = new Bindable(); - - private readonly IBeatmapInfo beatmapInfo; - private readonly IRulesetInfo ruleset; - private readonly IReadOnlyList mods; - - private CancellationTokenSource difficultyCancellation; - - [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } - - public DifficultyRetriever(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, IReadOnlyList mods) - { - this.beatmapInfo = beatmapInfo; - this.ruleset = ruleset; - this.mods = mods; - } - - private IBindable localStarDifficulty; - - [BackgroundDependencyLoader] - private void load() - { - difficultyCancellation = new CancellationTokenSource(); - localStarDifficulty = ruleset != null - ? difficultyCache.GetBindableDifficulty(beatmapInfo, ruleset, mods, difficultyCancellation.Token) - : difficultyCache.GetBindableDifficulty(beatmapInfo, difficultyCancellation.Token); - localStarDifficulty.BindValueChanged(d => - { - if (d.NewValue is StarDifficulty diff) - StarDifficulty.Value = diff; - }); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - difficultyCancellation?.Cancel(); - } - } + DifficultyIconTooltipContent IHasCustomTooltip. + TooltipContent => (ShowTooltip && beatmap != null ? new DifficultyIconTooltipContent(beatmap, Current) : null)!; } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index 5479644772..4732de6e79 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs index 5b467d67e2..22ca0a9037 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs index ad0ff876e8..50bd7ad48e 100644 --- a/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs deleted file mode 100644 index 799a02579e..0000000000 --- a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs +++ /dev/null @@ -1,37 +0,0 @@ -// 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.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Rulesets; -using osuTK.Graphics; - -namespace osu.Game.Beatmaps.Drawables -{ - /// - /// A difficulty icon that contains a counter on the right-side of it. - /// - /// - /// Used in cases when there are too many difficulty icons to show. - /// - public class GroupedDifficultyIcon : DifficultyIcon - { - public GroupedDifficultyIcon(IEnumerable beatmaps, IRulesetInfo ruleset, Color4 counterColour) - : base(beatmaps.OrderBy(b => b.StarRating).Last(), ruleset, null, false) - { - AddInternal(new OsuSpriteText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Padding = new MarginPadding { Left = Size.X }, - Margin = new MarginPadding { Left = 2, Right = 5 }, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), - Text = beatmaps.Count().ToString(), - Colour = counterColour, - }); - } - } -} diff --git a/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs index 0b19c27022..063990c89c 100644 --- a/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/OnlineBeatmapSetCover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index dde7680989..44bccd69d0 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 636c568bd0..f37771a74d 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs index 4a6a1b888e..236bb63e24 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableOnlineBeatmapSetCover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 6e879d09d5..9610dbcc78 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Beatmaps/EFBeatmapDifficulty.cs b/osu.Game/Beatmaps/EFBeatmapDifficulty.cs index 38371d3b38..8bcac24ca1 100644 --- a/osu.Game/Beatmaps/EFBeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/EFBeatmapDifficulty.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database; diff --git a/osu.Game/Beatmaps/EFBeatmapInfo.cs b/osu.Game/Beatmaps/EFBeatmapInfo.cs index 740adfd1c7..20abdc686a 100644 --- a/osu.Game/Beatmaps/EFBeatmapInfo.cs +++ b/osu.Game/Beatmaps/EFBeatmapInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -126,7 +128,7 @@ namespace osu.Game.Beatmaps public List Scores { get; set; } [JsonIgnore] - public DifficultyRating DifficultyRating => BeatmapDifficultyCache.GetDifficultyRating(StarRating); + public DifficultyRating DifficultyRating => StarDifficulty.GetDifficultyRating(StarRating); public override string ToString() => this.GetDisplayTitle(); diff --git a/osu.Game/Beatmaps/EFBeatmapMetadata.cs b/osu.Game/Beatmaps/EFBeatmapMetadata.cs index 7c27863a7f..c0588f128c 100644 --- a/osu.Game/Beatmaps/EFBeatmapMetadata.cs +++ b/osu.Game/Beatmaps/EFBeatmapMetadata.cs @@ -10,8 +10,6 @@ using osu.Game.Database; using osu.Game.Online.API.Requests.Responses; using osu.Game.Users; -#nullable enable - namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] diff --git a/osu.Game/Beatmaps/EFBeatmapSetInfo.cs b/osu.Game/Beatmaps/EFBeatmapSetInfo.cs index 12235abce0..1f41d3727c 100644 --- a/osu.Game/Beatmaps/EFBeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/EFBeatmapSetInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; diff --git a/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs b/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs index cd8aa31ead..02fcde5257 100644 --- a/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using osu.Framework.Audio.Track; diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index c1537d7240..ca1bcc97fd 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -72,7 +74,7 @@ namespace osu.Game.Beatmaps.Formats } if (line == null) - throw new IOException("Unknown file format (null)"); + throw new IOException("Unknown file format (no content)"); var decoder = typedDecoders.Where(d => line.StartsWith(d.Key, StringComparison.InvariantCulture)).Select(d => d.Value).FirstOrDefault(); diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index 853a590595..d5e96da246 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Beatmaps/Formats/IHasCustomColours.cs b/osu.Game/Beatmaps/Formats/IHasCustomColours.cs index dba3a37545..b651ef9515 100644 --- a/osu.Game/Beatmaps/Formats/IHasCustomColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasCustomColours.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs index 0d5c48f64d..4f292a9a1f 100644 --- a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.IO; using osu.Game.IO.Serialization; @@ -10,7 +12,7 @@ namespace osu.Game.Beatmaps.Formats { public static void Register() { - AddDecoder("{", m => new JsonBeatmapDecoder()); + AddDecoder("{", _ => new JsonBeatmapDecoder()); } protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 3a893a1238..89d3465ab6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 3b4200e7a9..03c63ff4f2 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Globalization; @@ -371,11 +373,11 @@ namespace osu.Game.Beatmaps.Formats switch (hitObject) { - case IHasPath _: + case IHasPath: type |= LegacyHitObjectType.Slider; break; - case IHasDuration _: + case IHasDuration: if (onlineRulesetID == 3) type |= LegacyHitObjectType.Hold; else diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index ff13e61360..52e760a068 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Formats { Section section = Section.General; - string line; + string? line; while ((line = stream.ReadLine()) != null) { @@ -143,7 +143,7 @@ namespace osu.Game.Beatmaps.Formats protected string CleanFilename(string path) => path.Trim('"').ToStandardisedPath(); - protected enum Section + public enum Section { General, Editor, @@ -160,7 +160,7 @@ namespace osu.Game.Beatmaps.Formats } [Obsolete("Do not use unless you're a legacy ruleset and 100% sure.")] - public class LegacyDifficultyControlPoint : DifficultyControlPoint + public class LegacyDifficultyControlPoint : DifficultyControlPoint, IEquatable { /// /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. @@ -186,9 +186,20 @@ namespace osu.Game.Beatmaps.Formats BpmMultiplier = ((LegacyDifficultyControlPoint)other).BpmMultiplier; } + + public override bool Equals(ControlPoint? other) + => other is LegacyDifficultyControlPoint otherLegacyDifficultyControlPoint + && Equals(otherLegacyDifficultyControlPoint); + + public bool Equals(LegacyDifficultyControlPoint? other) + => base.Equals(other) + && BpmMultiplier == other.BpmMultiplier; + + // ReSharper disable once NonReadonlyMemberInGetHashCode + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), BpmMultiplier); } - internal class LegacySampleControlPoint : SampleControlPoint + internal class LegacySampleControlPoint : SampleControlPoint, IEquatable { public int CustomSampleBank; @@ -202,7 +213,7 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public override bool IsRedundant(ControlPoint existing) + public override bool IsRedundant(ControlPoint? existing) => base.IsRedundant(existing) && existing is LegacySampleControlPoint existingSample && CustomSampleBank == existingSample.CustomSampleBank; @@ -213,6 +224,17 @@ namespace osu.Game.Beatmaps.Formats CustomSampleBank = ((LegacySampleControlPoint)other).CustomSampleBank; } + + public override bool Equals(ControlPoint? other) + => other is LegacySampleControlPoint otherLegacySampleControlPoint + && Equals(otherLegacySampleControlPoint); + + public bool Equals(LegacySampleControlPoint? other) + => base.Equals(other) + && CustomSampleBank == other.CustomSampleBank; + + // ReSharper disable once NonReadonlyMemberInGetHashCode + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), CustomSampleBank); } } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 3420fcf260..bf69100361 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; namespace osu.Game.Beatmaps.Formats diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 90a96e2ac8..b8f60f0bc6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -33,7 +35,7 @@ namespace osu.Game.Beatmaps.Formats { // note that this isn't completely correct AddDecoder(@"osu file format v", m => new LegacyStoryboardDecoder(Parsing.ParseInt(m.Split('v').Last()))); - AddDecoder(@"[Events]", m => new LegacyStoryboardDecoder()); + AddDecoder(@"[Events]", _ => new LegacyStoryboardDecoder()); SetFallbackDecoder(() => new LegacyStoryboardDecoder()); } diff --git a/osu.Game/Beatmaps/Formats/Parsing.cs b/osu.Game/Beatmaps/Formats/Parsing.cs index 4d512fdeed..ce04f27020 100644 --- a/osu.Game/Beatmaps/Formats/Parsing.cs +++ b/osu.Game/Beatmaps/Formats/Parsing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; diff --git a/osu.Game/Beatmaps/IBeatSyncProvider.cs b/osu.Game/Beatmaps/IBeatSyncProvider.cs index cc1cfc3cb5..362f02f2dd 100644 --- a/osu.Game/Beatmaps/IBeatSyncProvider.cs +++ b/osu.Game/Beatmaps/IBeatSyncProvider.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Timing; diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index dec1ef4294..25b147c267 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Timing; diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs index 2833af8ca2..f84188c5e2 100644 --- a/osu.Game/Beatmaps/IBeatmapConverter.cs +++ b/osu.Game/Beatmaps/IBeatmapConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Threading; diff --git a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs index 339364d442..dad9bbbd0b 100644 --- a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.Beatmaps { /// diff --git a/osu.Game/Beatmaps/IBeatmapInfo.cs b/osu.Game/Beatmaps/IBeatmapInfo.cs index ab096b8897..4f2c08f63d 100644 --- a/osu.Game/Beatmaps/IBeatmapInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapInfo.cs @@ -5,8 +5,6 @@ using System; using osu.Game.Database; using osu.Game.Rulesets; -#nullable enable - namespace osu.Game.Beatmaps { /// diff --git a/osu.Game/Beatmaps/IBeatmapMetadataInfo.cs b/osu.Game/Beatmaps/IBeatmapMetadataInfo.cs index 61adc0ac34..9c96aba85b 100644 --- a/osu.Game/Beatmaps/IBeatmapMetadataInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapMetadataInfo.cs @@ -4,8 +4,6 @@ using System; using osu.Game.Users; -#nullable enable - namespace osu.Game.Beatmaps { /// diff --git a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs index 385646eeaa..e1634e7d24 100644 --- a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.Beatmaps { /// @@ -15,25 +13,50 @@ namespace osu.Game.Beatmaps /// int? MaxCombo { get; } + /// + /// The approach rate. + /// + float ApproachRate { get; } + + /// + /// The circle size. + /// + float CircleSize { get; } + + /// + /// The drain rate. + /// + float DrainRate { get; } + + /// + /// The overall difficulty. + /// + float OverallDifficulty { get; } + /// /// The amount of circles in this beatmap. /// - public int CircleCount { get; } + int CircleCount { get; } /// /// The amount of sliders in this beatmap. /// - public int SliderCount { get; } + int SliderCount { get; } + + /// + /// The amount of spinners in tihs beatmap. + /// + int SpinnerCount { get; } /// /// The amount of plays this beatmap has. /// - public int PlayCount { get; } + int PlayCount { get; } /// /// The amount of passes this beatmap has. /// - public int PassCount { get; } + int PassCount { get; } APIFailTimes? FailTimes { get; } } diff --git a/osu.Game/Beatmaps/IBeatmapProcessor.cs b/osu.Game/Beatmaps/IBeatmapProcessor.cs index 014dccf5e3..0a4a98c606 100644 --- a/osu.Game/Beatmaps/IBeatmapProcessor.cs +++ b/osu.Game/Beatmaps/IBeatmapProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs index dfea0c7a30..22ff7ce8c8 100644 --- a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs +++ b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.IO; diff --git a/osu.Game/Beatmaps/IBeatmapSetInfo.cs b/osu.Game/Beatmaps/IBeatmapSetInfo.cs index 9755120457..2ecd16cb75 100644 --- a/osu.Game/Beatmaps/IBeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapSetInfo.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; using osu.Game.Database; -#nullable enable - namespace osu.Game.Beatmaps { /// diff --git a/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs index 33d8929008..3f50b4eaf3 100644 --- a/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs @@ -3,8 +3,6 @@ using System; -#nullable enable - namespace osu.Game.Beatmaps { /// diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 3e2868470a..2188bd6a2b 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using System.Threading; diff --git a/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs b/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs index 2b0a2e7a4d..5c3c72c9e4 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; @@ -54,12 +56,12 @@ namespace osu.Game.Beatmaps.Legacy { switch (newPoint) { - case SampleControlPoint _: + case SampleControlPoint: // intentionally don't use SamplePointAt (we always need to consider the first sample point). var existing = BinarySearch(SamplePoints, time); return newPoint.IsRedundant(existing); - case DifficultyControlPoint _: + case DifficultyControlPoint: return newPoint.IsRedundant(DifficultyPointAt(time)); default: diff --git a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs index 5bf80c34d7..b3717c81dc 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs index 32a7122978..42d21d14f6 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps.Legacy { internal enum LegacyEventType diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs index ec9839b893..ec947c6dc2 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs index d7743565f8..d1782ec862 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyMods.cs b/osu.Game/Beatmaps/Legacy/LegacyMods.cs index 0e517ea3df..27b2e313ec 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyMods.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyMods.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs index 31f67d6dfd..62b0edc384 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps.Legacy { internal enum LegacyOrigins diff --git a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs index 8cac29cb87..f8a57c3ac9 100644 --- a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs +++ b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps.Legacy { internal enum LegacySampleBank diff --git a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs index ea23c49c4a..69d0c96b57 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Beatmaps.Legacy { internal enum LegacyStoryLayer diff --git a/osu.Game/Beatmaps/MetadataUtils.cs b/osu.Game/Beatmaps/MetadataUtils.cs index b27c59b4de..89c821c16c 100644 --- a/osu.Game/Beatmaps/MetadataUtils.cs +++ b/osu.Game/Beatmaps/MetadataUtils.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Linq; using System.Text; diff --git a/osu.Game/Beatmaps/StarDifficulty.cs b/osu.Game/Beatmaps/StarDifficulty.cs index f438b6f0bc..6aac275a6a 100644 --- a/osu.Game/Beatmaps/StarDifficulty.cs +++ b/osu.Game/Beatmaps/StarDifficulty.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; +using osu.Framework.Utils; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Beatmaps @@ -31,7 +34,7 @@ namespace osu.Game.Beatmaps /// public StarDifficulty([NotNull] DifficultyAttributes attributes) { - Stars = attributes.StarRating; + Stars = double.IsFinite(attributes.StarRating) ? attributes.StarRating : 0; MaxCombo = attributes.MaxCombo; Attributes = attributes; // Todo: Add more members (BeatmapInfo.DifficultyRating? Attributes? Etc...) @@ -43,11 +46,39 @@ namespace osu.Game.Beatmaps /// public StarDifficulty(double starDifficulty, int maxCombo) { - Stars = starDifficulty; + Stars = double.IsFinite(starDifficulty) ? starDifficulty : 0; MaxCombo = maxCombo; Attributes = null; } - public DifficultyRating DifficultyRating => BeatmapDifficultyCache.GetDifficultyRating(Stars); + public DifficultyRating DifficultyRating => GetDifficultyRating(Stars); + + /// + /// Retrieves the that describes a star rating. + /// + /// + /// For more information, see: https://osu.ppy.sh/help/wiki/Difficulties + /// + /// The star rating. + /// The that best describes . + public static DifficultyRating GetDifficultyRating(double starRating) + { + if (Precision.AlmostBigger(starRating, 6.5, 0.005)) + return DifficultyRating.ExpertPlus; + + if (Precision.AlmostBigger(starRating, 5.3, 0.005)) + return DifficultyRating.Expert; + + if (Precision.AlmostBigger(starRating, 4.0, 0.005)) + return DifficultyRating.Insane; + + if (Precision.AlmostBigger(starRating, 2.7, 0.005)) + return DifficultyRating.Hard; + + if (Precision.AlmostBigger(starRating, 2.0, 0.005)) + return DifficultyRating.Normal; + + return DifficultyRating.Easy; + } } } diff --git a/osu.Game/Beatmaps/Timing/BreakPeriod.cs b/osu.Game/Beatmaps/Timing/BreakPeriod.cs index 4c90b16745..274b56a862 100644 --- a/osu.Game/Beatmaps/Timing/BreakPeriod.cs +++ b/osu.Game/Beatmaps/Timing/BreakPeriod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Screens.Play; namespace osu.Game.Beatmaps.Timing diff --git a/osu.Game/Beatmaps/Timing/TimeSignature.cs b/osu.Game/Beatmaps/Timing/TimeSignature.cs index eebbcc34cd..7499a725dc 100644 --- a/osu.Game/Beatmaps/Timing/TimeSignature.cs +++ b/osu.Game/Beatmaps/Timing/TimeSignature.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Beatmaps.Timing diff --git a/osu.Game/Beatmaps/Timing/TimeSignatures.cs b/osu.Game/Beatmaps/Timing/TimeSignatures.cs index d783d3f9ec..95c971eebf 100644 --- a/osu.Game/Beatmaps/Timing/TimeSignatures.cs +++ b/osu.Game/Beatmaps/Timing/TimeSignatures.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.ComponentModel; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 09072ec897..16464932e0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index bc810ee35e..df44f01629 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -74,10 +76,13 @@ namespace osu.Game.Beatmaps { Logger.Log($"Invalidating working beatmap cache for {info}"); workingCache.Remove(working); + OnInvalidated?.Invoke(working); } } } + public event Action OnInvalidated; + public virtual WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo) { if (beatmapInfo?.BeatmapSet == null) @@ -132,8 +137,17 @@ namespace osu.Game.Beatmaps try { - using (var stream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path)))) - return Decoder.GetDecoder(stream).Decode(stream); + string fileStorePath = BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path); + var stream = GetStream(fileStorePath); + + if (stream == null) + { + Logger.Log($"Beatmap failed to load (file {BeatmapInfo.Path} not found on disk at expected location {fileStorePath}).", level: LogLevel.Error); + return null; + } + + using (var reader = new LineBufferedReader(stream)) + return Decoder.GetDecoder(reader).Decode(reader); } catch (Exception e) { @@ -149,7 +163,16 @@ namespace osu.Game.Beatmaps try { - return resources.LargeTextureStore.Get(BeatmapSetInfo.GetPathForFile(Metadata.BackgroundFile)); + string fileStorePath = BeatmapSetInfo.GetPathForFile(Metadata.BackgroundFile); + var texture = resources.LargeTextureStore.Get(fileStorePath); + + if (texture == null) + { + Logger.Log($"Beatmap background failed to load (file {Metadata.BackgroundFile} not found on disk at expected location {fileStorePath})."); + return null; + } + + return texture; } catch (Exception e) { @@ -168,7 +191,16 @@ namespace osu.Game.Beatmaps try { - return resources.Tracks.Get(BeatmapSetInfo.GetPathForFile(Metadata.AudioFile)); + string fileStorePath = BeatmapSetInfo.GetPathForFile(Metadata.AudioFile); + var track = resources.Tracks.Get(fileStorePath); + + if (track == null) + { + Logger.Log($"Beatmap failed to load (file {Metadata.AudioFile} not found on disk at expected location {fileStorePath}).", level: LogLevel.Error); + return null; + } + + return track; } catch (Exception e) { @@ -187,8 +219,17 @@ namespace osu.Game.Beatmaps try { - var trackData = GetStream(BeatmapSetInfo.GetPathForFile(Metadata.AudioFile)); - return trackData == null ? null : new Waveform(trackData); + string fileStorePath = BeatmapSetInfo.GetPathForFile(Metadata.AudioFile); + + var trackData = GetStream(fileStorePath); + + if (trackData == null) + { + Logger.Log($"Beatmap waveform failed to load (file {Metadata.AudioFile} not found on disk at expected location {fileStorePath}).", level: LogLevel.Error); + return null; + } + + return new Waveform(trackData); } catch (Exception e) { @@ -206,20 +247,38 @@ namespace osu.Game.Beatmaps try { - using (var stream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path)))) + string fileStorePath = BeatmapSetInfo.GetPathForFile(BeatmapInfo.Path); + var beatmapFileStream = GetStream(fileStorePath); + + if (beatmapFileStream == null) { - var decoder = Decoder.GetDecoder(stream); + Logger.Log($"Beatmap failed to load (file {BeatmapInfo.Path} not found on disk at expected location {fileStorePath})", level: LogLevel.Error); + return null; + } - string storyboardFilename = BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename; + using (var reader = new LineBufferedReader(beatmapFileStream)) + { + var decoder = Decoder.GetDecoder(reader); - // todo: support loading from both set-wide storyboard *and* beatmap specific. - if (string.IsNullOrEmpty(storyboardFilename)) - storyboard = decoder.Decode(stream); - else + Stream storyboardFileStream = null; + + if (BeatmapSetInfo?.Files.FirstOrDefault(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename is string storyboardFilename) { - using (var secondaryStream = new LineBufferedReader(GetStream(BeatmapSetInfo.GetPathForFile(storyboardFilename)))) - storyboard = decoder.Decode(stream, secondaryStream); + string storyboardFileStorePath = BeatmapSetInfo?.GetPathForFile(storyboardFilename); + storyboardFileStream = GetStream(storyboardFileStorePath); + + if (storyboardFileStream == null) + Logger.Log($"Storyboard failed to load (file {storyboardFilename} not found on disk at expected location {storyboardFileStorePath})", level: LogLevel.Error); } + + if (storyboardFileStream != null) + { + // Stand-alone storyboard was found, so parse in addition to the beatmap's local storyboard. + using (var secondaryReader = new LineBufferedReader(storyboardFileStream)) + storyboard = decoder.Decode(reader, secondaryReader); + } + else + storyboard = decoder.Decode(reader); } } catch (Exception e) diff --git a/osu.Game/Collections/BeatmapCollection.cs b/osu.Game/Collections/BeatmapCollection.cs index 7e4b15ecf9..742d757bec 100644 --- a/osu.Game/Collections/BeatmapCollection.cs +++ b/osu.Game/Collections/BeatmapCollection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Game.Beatmaps; @@ -23,9 +25,9 @@ namespace osu.Game.Collections public readonly Bindable Name = new Bindable(); /// - /// The beatmaps contained by the collection. + /// The es of beatmaps contained by the collection. /// - public readonly BindableList Beatmaps = new BindableList(); + public readonly BindableList BeatmapHashes = new BindableList(); /// /// The date when this collection was last modified. @@ -34,7 +36,7 @@ namespace osu.Game.Collections public BeatmapCollection() { - Beatmaps.CollectionChanged += (_, __) => onChange(); + BeatmapHashes.CollectionChanged += (_, _) => onChange(); Name.ValueChanged += _ => onChange(); } diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index c46ba8e06e..d099eb6e1b 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Specialized; using System.Diagnostics; using System.Linq; @@ -38,7 +40,7 @@ namespace osu.Game.Collections } private readonly IBindableList collections = new BindableList(); - private readonly IBindableList beatmaps = new BindableList(); + private readonly IBindableList beatmaps = new BindableList(); private readonly BindableList filters = new BindableList(); [Resolved(CanBeNull = true)] @@ -65,7 +67,7 @@ namespace osu.Game.Collections // An extra bindable is enough to subvert this behaviour. base.Current = Current; - collections.BindCollectionChanged((_, __) => collectionsChanged(), true); + collections.BindCollectionChanged((_, _) => collectionsChanged(), true); Current.BindValueChanged(filterChanged, true); } @@ -95,10 +97,10 @@ namespace osu.Game.Collections beatmaps.CollectionChanged -= filterBeatmapsChanged; if (filter.OldValue?.Collection != null) - beatmaps.UnbindFrom(filter.OldValue.Collection.Beatmaps); + beatmaps.UnbindFrom(filter.OldValue.Collection.BeatmapHashes); if (filter.NewValue?.Collection != null) - beatmaps.BindTo(filter.NewValue.Collection.Beatmaps); + beatmaps.BindTo(filter.NewValue.Collection.BeatmapHashes); beatmaps.CollectionChanged += filterBeatmapsChanged; @@ -196,7 +198,7 @@ namespace osu.Game.Collections private IBindable beatmap { get; set; } [CanBeNull] - private readonly BindableList collectionBeatmaps; + private readonly BindableList collectionBeatmaps; [NotNull] private readonly Bindable collectionName; @@ -208,7 +210,7 @@ namespace osu.Game.Collections public CollectionDropdownMenuItem(MenuItem item) : base(item) { - collectionBeatmaps = Item.Collection?.Beatmaps.GetBoundCopy(); + collectionBeatmaps = Item.Collection?.BeatmapHashes.GetBoundCopy(); collectionName = Item.CollectionName.GetBoundCopy(); } @@ -231,7 +233,7 @@ namespace osu.Game.Collections if (collectionBeatmaps != null) { - collectionBeatmaps.CollectionChanged += (_, __) => collectionChanged(); + collectionBeatmaps.CollectionChanged += (_, _) => collectionChanged(); beatmap.BindValueChanged(_ => collectionChanged(), true); } @@ -258,7 +260,7 @@ namespace osu.Game.Collections { Debug.Assert(collectionBeatmaps != null); - beatmapInCollection = collectionBeatmaps.Contains(beatmap.Value.BeatmapInfo); + beatmapInCollection = collectionBeatmaps.Contains(beatmap.Value.BeatmapInfo.MD5Hash); addOrRemoveButton.Enabled.Value = !beatmap.IsDefault; addOrRemoveButton.Icon = beatmapInCollection ? FontAwesome.Solid.MinusSquare : FontAwesome.Solid.PlusSquare; @@ -285,8 +287,8 @@ namespace osu.Game.Collections { Debug.Assert(collectionBeatmaps != null); - if (!collectionBeatmaps.Remove(beatmap.Value.BeatmapInfo)) - collectionBeatmaps.Add(beatmap.Value.BeatmapInfo); + if (!collectionBeatmaps.Remove(beatmap.Value.BeatmapInfo.MD5Hash)) + collectionBeatmaps.Add(beatmap.Value.BeatmapInfo.MD5Hash); } protected override Drawable CreateContent() => content = (Content)base.CreateContent(); diff --git a/osu.Game/Collections/CollectionFilterMenuItem.cs b/osu.Game/Collections/CollectionFilterMenuItem.cs index 0617996872..031f05c0b4 100644 --- a/osu.Game/Collections/CollectionFilterMenuItem.cs +++ b/osu.Game/Collections/CollectionFilterMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Bindables; diff --git a/osu.Game/Collections/CollectionManager.cs b/osu.Game/Collections/CollectionManager.cs index 700b0f5dcb..796b3c426c 100644 --- a/osu.Game/Collections/CollectionManager.cs +++ b/osu.Game/Collections/CollectionManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -13,7 +15,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.IO; using osu.Game.IO.Legacy; @@ -40,9 +41,6 @@ namespace osu.Game.Collections public readonly BindableList Collections = new BindableList(); - [Resolved] - private BeatmapManager beatmaps { get; set; } - private readonly Storage storage; public CollectionManager(Storage storage) @@ -173,10 +171,10 @@ namespace osu.Game.Collections if (existing == null) Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } }); - foreach (var newBeatmap in newCol.Beatmaps) + foreach (string newBeatmap in newCol.BeatmapHashes) { - if (!existing.Beatmaps.Contains(newBeatmap)) - existing.Beatmaps.Add(newBeatmap); + if (!existing.BeatmapHashes.Contains(newBeatmap)) + existing.BeatmapHashes.Add(newBeatmap); } } @@ -226,9 +224,7 @@ namespace osu.Game.Collections string checksum = sr.ReadString(); - var beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == checksum); - if (beatmap != null) - collection.Beatmaps.Add(beatmap); + collection.BeatmapHashes.Add(checksum); } if (notification != null) @@ -265,7 +261,7 @@ namespace osu.Game.Collections private void backgroundSave() { int current = Interlocked.Increment(ref lastSave); - Task.Delay(100).ContinueWith(task => + Task.Delay(100).ContinueWith(_ => { if (current != lastSave) return; @@ -299,11 +295,12 @@ namespace osu.Game.Collections { sw.Write(c.Name.Value); - var beatmapsCopy = c.Beatmaps.ToArray(); + string[] beatmapsCopy = c.BeatmapHashes.ToArray(); + sw.Write(beatmapsCopy.Length); - foreach (var b in beatmapsCopy) - sw.Write(b.MD5Hash); + foreach (string b in beatmapsCopy) + sw.Write(b); } } diff --git a/osu.Game/Collections/CollectionToggleMenuItem.cs b/osu.Game/Collections/CollectionToggleMenuItem.cs new file mode 100644 index 0000000000..f2b10305b8 --- /dev/null +++ b/osu.Game/Collections/CollectionToggleMenuItem.cs @@ -0,0 +1,23 @@ +// 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.UserInterface; + +namespace osu.Game.Collections +{ + public class CollectionToggleMenuItem : ToggleMenuItem + { + public CollectionToggleMenuItem(BeatmapCollection collection, IBeatmapInfo beatmap) + : base(collection.Name.Value, MenuItemType.Standard, state => + { + if (state) + collection.BeatmapHashes.Add(beatmap.MD5Hash); + else + collection.BeatmapHashes.Remove(beatmap.MD5Hash); + }) + { + State.Value = collection.BeatmapHashes.Contains(beatmap.MD5Hash); + } + } +} diff --git a/osu.Game/Collections/DeleteCollectionDialog.cs b/osu.Game/Collections/DeleteCollectionDialog.cs index e5a2f6fb81..1da2870913 100644 --- a/osu.Game/Collections/DeleteCollectionDialog.cs +++ b/osu.Game/Collections/DeleteCollectionDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Humanizer; using osu.Framework.Graphics.Sprites; @@ -13,7 +15,7 @@ namespace osu.Game.Collections public DeleteCollectionDialog(BeatmapCollection collection, Action deleteAction) { HeaderText = "Confirm deletion of"; - BodyText = $"{collection.Name.Value} ({"beatmap".ToQuantity(collection.Beatmaps.Count)})"; + BodyText = $"{collection.Name.Value} ({"beatmap".ToQuantity(collection.BeatmapHashes.Count)})"; Icon = FontAwesome.Regular.TrashAlt; diff --git a/osu.Game/Collections/DrawableCollectionList.cs b/osu.Game/Collections/DrawableCollectionList.cs index 3c664a11d9..4fe5733c2f 100644 --- a/osu.Game/Collections/DrawableCollectionList.cs +++ b/osu.Game/Collections/DrawableCollectionList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Collections/DrawableCollectionListItem.cs b/osu.Game/Collections/DrawableCollectionListItem.cs index 5a20b7e7bd..4596fc0e52 100644 --- a/osu.Game/Collections/DrawableCollectionListItem.cs +++ b/osu.Game/Collections/DrawableCollectionListItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -225,7 +227,7 @@ namespace osu.Game.Collections { background.FlashColour(Color4.White, 150); - if (collection.Beatmaps.Count == 0) + if (collection.BeatmapHashes.Count == 0) deleteCollection(); else dialogOverlay?.Push(new DeleteCollectionDialog(collection, deleteCollection)); diff --git a/osu.Game/Collections/ManageCollectionsDialog.cs b/osu.Game/Collections/ManageCollectionsDialog.cs index cb350bca33..a9d699bc9f 100644 --- a/osu.Game/Collections/ManageCollectionsDialog.cs +++ b/osu.Game/Collections/ManageCollectionsDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; diff --git a/osu.Game/Configuration/BackgroundSource.cs b/osu.Game/Configuration/BackgroundSource.cs index 18e0603860..b4a1fd78c3 100644 --- a/osu.Game/Configuration/BackgroundSource.cs +++ b/osu.Game/Configuration/BackgroundSource.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs index 65d9f7799d..0c1b4021a1 100644 --- a/osu.Game/Configuration/DatabasedSetting.cs +++ b/osu.Game/Configuration/DatabasedSetting.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database; diff --git a/osu.Game/Configuration/DevelopmentOsuConfigManager.cs b/osu.Game/Configuration/DevelopmentOsuConfigManager.cs index ff19dd874c..dda30c1d00 100644 --- a/osu.Game/Configuration/DevelopmentOsuConfigManager.cs +++ b/osu.Game/Configuration/DevelopmentOsuConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Platform; using osu.Framework.Testing; diff --git a/osu.Game/Configuration/DiscordRichPresenceMode.cs b/osu.Game/Configuration/DiscordRichPresenceMode.cs index 2e58e3554b..935619920a 100644 --- a/osu.Game/Configuration/DiscordRichPresenceMode.cs +++ b/osu.Game/Configuration/DiscordRichPresenceMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/HUDVisibilityMode.cs b/osu.Game/Configuration/HUDVisibilityMode.cs index 10f3f65355..ec54bfcb71 100644 --- a/osu.Game/Configuration/HUDVisibilityMode.cs +++ b/osu.Game/Configuration/HUDVisibilityMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/InMemoryConfigManager.cs b/osu.Game/Configuration/InMemoryConfigManager.cs index ccf697f680..d8879daa3f 100644 --- a/osu.Game/Configuration/InMemoryConfigManager.cs +++ b/osu.Game/Configuration/InMemoryConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Configuration; diff --git a/osu.Game/Configuration/IntroSequence.cs b/osu.Game/Configuration/IntroSequence.cs index 5672c44bbe..8327ea2f57 100644 --- a/osu.Game/Configuration/IntroSequence.cs +++ b/osu.Game/Configuration/IntroSequence.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Configuration { public enum IntroSequence diff --git a/osu.Game/Configuration/ModSettingChangeTracker.cs b/osu.Game/Configuration/ModSettingChangeTracker.cs index e2ade7dc6a..0061746425 100644 --- a/osu.Game/Configuration/ModSettingChangeTracker.cs +++ b/osu.Game/Configuration/ModSettingChangeTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 20d555c16c..e816fd50f3 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -18,6 +20,7 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Overlays; +using osu.Game.Overlays.Mods.Input; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; @@ -45,6 +48,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.SongSelectSortingMode, SortMode.Title); SetDefault(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation); + SetDefault(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Sequential); SetDefault(OsuSetting.ChatDisplayHeight, ChatOverlay.DEFAULT_HEIGHT, 0.2f, 1f); @@ -163,6 +167,8 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.DiscordRichPresence, DiscordRichPresenceMode.Full); SetDefault(OsuSetting.EditorWaveformOpacity, 0.25f); + + SetDefault(OsuSetting.LastProcessedMetadataId, -1); } public IDictionary GetLoggableState() => @@ -218,6 +224,12 @@ namespace osu.Game.Configuration return new TrackedSettings { + new TrackedSetting(OsuSetting.ShowFpsDisplay, state => new SettingDescription( + rawValue: state, + name: GlobalActionKeyBindingStrings.ToggleFPSCounter, + value: state ? CommonStrings.Enabled.ToLower() : CommonStrings.Disabled.ToLower(), + shortcut: LookupKeyBindings(GlobalAction.ToggleFPSDisplay)) + ), new TrackedSetting(OsuSetting.MouseDisableButtons, disabledState => new SettingDescription( rawValue: !disabledState, name: GlobalActionKeyBindingStrings.ToggleGameplayMouseButtons, @@ -322,6 +334,7 @@ namespace osu.Game.Configuration SongSelectGroupingMode, SongSelectSortingMode, RandomSelectAlgorithm, + ModSelectHotkeyStyle, ShowFpsDisplay, ChatDisplayHeight, BeatmapListingCardSize, @@ -358,5 +371,6 @@ namespace osu.Game.Configuration DiscordRichPresence, AutomaticallyDownloadWhenSpectating, ShowOnlineExplicitContent, + LastProcessedMetadataId } } diff --git a/osu.Game/Configuration/RandomSelectAlgorithm.cs b/osu.Game/Configuration/RandomSelectAlgorithm.cs index b22f2ae485..9a02aaee60 100644 --- a/osu.Game/Configuration/RandomSelectAlgorithm.cs +++ b/osu.Game/Configuration/RandomSelectAlgorithm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/RealmRulesetSetting.cs b/osu.Game/Configuration/RealmRulesetSetting.cs index 3fea35ee9d..2e8ccc6b0c 100644 --- a/osu.Game/Configuration/RealmRulesetSetting.cs +++ b/osu.Game/Configuration/RealmRulesetSetting.cs @@ -3,8 +3,6 @@ using Realms; -#nullable enable - namespace osu.Game.Configuration { [MapTo(@"RulesetSetting")] diff --git a/osu.Game/Configuration/ReleaseStream.cs b/osu.Game/Configuration/ReleaseStream.cs index ed0bee1dd8..9cdd91bfd0 100644 --- a/osu.Game/Configuration/ReleaseStream.cs +++ b/osu.Game/Configuration/ReleaseStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Configuration { public enum ReleaseStream diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs index 0bcc908f71..25c3692a1a 100644 --- a/osu.Game/Configuration/ScalingMode.cs +++ b/osu.Game/Configuration/ScalingMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/ScreenshotFormat.cs b/osu.Game/Configuration/ScreenshotFormat.cs index 6d4c96bfa9..57c08538b8 100644 --- a/osu.Game/Configuration/ScreenshotFormat.cs +++ b/osu.Game/Configuration/ScreenshotFormat.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/ScrollVisualisationMethod.cs b/osu.Game/Configuration/ScrollVisualisationMethod.cs index 5f48fe8bfd..111bb95e67 100644 --- a/osu.Game/Configuration/ScrollVisualisationMethod.cs +++ b/osu.Game/Configuration/ScrollVisualisationMethod.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/SeasonalBackgroundMode.cs b/osu.Game/Configuration/SeasonalBackgroundMode.cs index 6ef835ce5f..909798fe97 100644 --- a/osu.Game/Configuration/SeasonalBackgroundMode.cs +++ b/osu.Game/Configuration/SeasonalBackgroundMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Configuration { public enum SeasonalBackgroundMode diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 837ee7e634..12a30a0c84 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; diff --git a/osu.Game/Configuration/SettingSourceAttribute.cs b/osu.Game/Configuration/SettingSourceAttribute.cs index 89f0e73f4f..21e67363c3 100644 --- a/osu.Game/Configuration/SettingSourceAttribute.cs +++ b/osu.Game/Configuration/SettingSourceAttribute.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs index e5d2d572c8..fda7193fea 100644 --- a/osu.Game/Configuration/SettingsStore.cs +++ b/osu.Game/Configuration/SettingsStore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Database; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/StorageConfigManager.cs b/osu.Game/Configuration/StorageConfigManager.cs index 90ea42b638..c8781918e1 100644 --- a/osu.Game/Configuration/StorageConfigManager.cs +++ b/osu.Game/Configuration/StorageConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game/Configuration/ToolbarClockDisplayMode.cs b/osu.Game/Configuration/ToolbarClockDisplayMode.cs index 2f42f7a9b5..682e221ef8 100644 --- a/osu.Game/Configuration/ToolbarClockDisplayMode.cs +++ b/osu.Game/Configuration/ToolbarClockDisplayMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Configuration { public enum ToolbarClockDisplayMode diff --git a/osu.Game/Database/BeatmapLookupCache.cs b/osu.Game/Database/BeatmapLookupCache.cs index 06edc3e2da..53cb7d72fc 100644 --- a/osu.Game/Database/BeatmapLookupCache.cs +++ b/osu.Game/Database/BeatmapLookupCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 45557aa5ec..af91fb4971 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -151,7 +153,7 @@ namespace osu.Game.Database { Logger.Log($"Creating full EF database backup at {backupFilename}", LoggingTarget.Database); - using (var source = storage.GetStream(DATABASE_NAME)) + using (var source = storage.GetStream(DATABASE_NAME, mode: FileMode.Open)) using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew)) source.CopyTo(destination); } @@ -207,6 +209,10 @@ namespace osu.Game.Database public void SetMigrationCompletion() => migrationComplete.Set(); - public void WaitForMigrationCompletion() => migrationComplete.Wait(); + public void WaitForMigrationCompletion() + { + if (!migrationComplete.Wait(300000)) + throw new TimeoutException("Migration took too long (likely stuck)."); + } } } diff --git a/osu.Game/Database/DatabaseWriteUsage.cs b/osu.Game/Database/DatabaseWriteUsage.cs index 84c39e3532..b5f25eae20 100644 --- a/osu.Game/Database/DatabaseWriteUsage.cs +++ b/osu.Game/Database/DatabaseWriteUsage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; diff --git a/osu.Game/Database/EFToRealmMigrator.cs b/osu.Game/Database/EFToRealmMigrator.cs index 4e98b7d3d2..294a8cd3ed 100644 --- a/osu.Game/Database/EFToRealmMigrator.cs +++ b/osu.Game/Database/EFToRealmMigrator.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.IO; using System.Linq; @@ -123,8 +121,29 @@ namespace osu.Game.Database private void beginMigration() { + const string backup_folder = "backups"; + + string backupSuffix = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; + + // required for initial backup. + var realmBlockOperations = realm.BlockAllOperations("EF migration"); + Task.Factory.StartNew(() => { + try + { + realm.CreateBackup(Path.Combine(backup_folder, $"client.{backupSuffix}.realm")); + } + finally + { + // Once the backup is created, we need to stop blocking operations so the migration can complete. + realmBlockOperations.Dispose(); + // Clean up here so we don't accidentally dispose twice. + realmBlockOperations = null; + } + + efContextFactory.CreateBackup(Path.Combine(backup_folder, $"client.{backupSuffix}.db")); + using (var ef = efContextFactory.Get()) { realm.Write(r => @@ -182,7 +201,6 @@ namespace osu.Game.Database true); const string attachment_filename = "attach_me.zip"; - const string backup_folder = "backups"; var backupStorage = storage.GetStorageForDirectory(backup_folder); @@ -209,6 +227,9 @@ namespace osu.Game.Database // If we were to not do this, the migration would run another time the next time the user starts the game. deletePreRealmData(); + // If something went wrong and the disposal token wasn't invoked above, ensure it is here. + realmBlockOperations?.Dispose(); + migrationCompleted.SetResult(true); efContextFactory.SetMigrationCompletion(); }); @@ -422,7 +443,6 @@ namespace osu.Game.Database TotalScore = score.TotalScore, MaxCombo = score.MaxCombo, Accuracy = score.Accuracy, - HasReplay = ((IScoreInfo)score).HasReplay, Date = score.Date, PP = score.PP, Rank = score.Rank, diff --git a/osu.Game/Database/EmptyRealmSet.cs b/osu.Game/Database/EmptyRealmSet.cs index b7f27ba035..7db946d79f 100644 --- a/osu.Game/Database/EmptyRealmSet.cs +++ b/osu.Game/Database/EmptyRealmSet.cs @@ -9,8 +9,6 @@ using System.ComponentModel; using Realms; using Realms.Schema; -#nullable enable - namespace osu.Game.Database { public class EmptyRealmSet : IRealmCollection diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index 74fd6fcc36..3ce343249b 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Threading.Tasks; @@ -12,14 +14,22 @@ namespace osu.Game.Database public interface ICanAcceptFiles { /// - /// Import the specified paths. + /// Import one or more items from filesystem . /// + /// + /// This will be treated as a low priority batch import if more than one path is specified. + /// This will post notifications tracking progress. + /// /// The files which should be imported. Task Import(params string[] paths); /// /// Import the specified files from the given import tasks. /// + /// + /// This will be treated as a low priority batch import if more than one path is specified. + /// This will post notifications tracking progress. + /// /// The import tasks from which the files should be imported. Task Import(params ImportTask[] tasks); diff --git a/osu.Game/Database/IDatabaseContextFactory.cs b/osu.Game/Database/IDatabaseContextFactory.cs index 72b70a208f..bddabad586 100644 --- a/osu.Game/Database/IDatabaseContextFactory.cs +++ b/osu.Game/Database/IDatabaseContextFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Database { public interface IDatabaseContextFactory diff --git a/osu.Game/Database/IHasFiles.cs b/osu.Game/Database/IHasFiles.cs index 3f6531832f..9f8ce05218 100644 --- a/osu.Game/Database/IHasFiles.cs +++ b/osu.Game/Database/IHasFiles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using JetBrains.Annotations; diff --git a/osu.Game/Database/IHasGuidPrimaryKey.cs b/osu.Game/Database/IHasGuidPrimaryKey.cs index f52dc5c8ef..9cf7cf0683 100644 --- a/osu.Game/Database/IHasGuidPrimaryKey.cs +++ b/osu.Game/Database/IHasGuidPrimaryKey.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; using Realms; diff --git a/osu.Game/Database/IHasNamedFiles.cs b/osu.Game/Database/IHasNamedFiles.cs index 08906aaa08..3524eb4c99 100644 --- a/osu.Game/Database/IHasNamedFiles.cs +++ b/osu.Game/Database/IHasNamedFiles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; namespace osu.Game.Database diff --git a/osu.Game/Database/IHasOnlineID.cs b/osu.Game/Database/IHasOnlineID.cs index 7a720989cd..e703ce58b8 100644 --- a/osu.Game/Database/IHasOnlineID.cs +++ b/osu.Game/Database/IHasOnlineID.cs @@ -3,8 +3,6 @@ using System; -#nullable enable - namespace osu.Game.Database { public interface IHasOnlineID diff --git a/osu.Game/Database/IHasPrimaryKey.cs b/osu.Game/Database/IHasPrimaryKey.cs index 51a49948fe..84709ccd26 100644 --- a/osu.Game/Database/IHasPrimaryKey.cs +++ b/osu.Game/Database/IHasPrimaryKey.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; diff --git a/osu.Game/Database/IHasRealmFiles.cs b/osu.Game/Database/IHasRealmFiles.cs index 024d9f2a89..2adfe73d1e 100644 --- a/osu.Game/Database/IHasRealmFiles.cs +++ b/osu.Game/Database/IHasRealmFiles.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using osu.Game.Models; -#nullable enable - namespace osu.Game.Database { /// diff --git a/osu.Game/Database/IModelDownloader.cs b/osu.Game/Database/IModelDownloader.cs index 81fba14244..6f30dd207e 100644 --- a/osu.Game/Database/IModelDownloader.cs +++ b/osu.Game/Database/IModelDownloader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Online.API; diff --git a/osu.Game/Database/IModelFileManager.cs b/osu.Game/Database/IModelFileManager.cs index 390be4a69d..c40b57f663 100644 --- a/osu.Game/Database/IModelFileManager.cs +++ b/osu.Game/Database/IModelFileManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; namespace osu.Game.Database diff --git a/osu.Game/Database/IModelImporter.cs b/osu.Game/Database/IModelImporter.cs index 90df13477e..ebb8be39ef 100644 --- a/osu.Game/Database/IModelImporter.cs +++ b/osu.Game/Database/IModelImporter.cs @@ -1,55 +1,36 @@ // Copyright (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.Threading; using System.Threading.Tasks; -using osu.Game.IO.Archives; using osu.Game.Overlays.Notifications; -#nullable enable - namespace osu.Game.Database { /// /// A class which handles importing of associated models to the game store. /// /// The model type. - public interface IModelImporter : IPostNotifications, IPostImports, ICanAcceptFiles + public interface IModelImporter : IPostNotifications, ICanAcceptFiles where TModel : class, IHasGuidPrimaryKey { + /// + /// Process multiple import tasks, updating a tracking notification with progress. + /// + /// The notification to update. + /// The import tasks. + /// The imported models. Task>> Import(ProgressNotification notification, params ImportTask[] tasks); - /// - /// Import one from the filesystem and delete the file on success. - /// Note that this bypasses the UI flow and should only be used for special cases or testing. - /// - /// The containing data about the to import. - /// Whether this is a low priority import. - /// An optional cancellation token. - /// The imported model, if successful. - Task?> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default); - - /// - /// Silently import an item from an . - /// - /// The archive to be imported. - /// Whether this is a low priority import. - /// An optional cancellation token. - Task?> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default); - - /// - /// Silently import an item from a . - /// - /// The model to be imported. - /// An optional archive to use for model population. - /// Whether this is a low priority import. - /// An optional cancellation token. - Live? Import(TModel item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default); - /// /// A user displayable name for the model type associated with this manager. /// - string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLower()}"; + string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLowerInvariant()}"; + + /// + /// Fired when the user requests to view the resulting import. + /// + public Action>>? PresentImport { set; } } } diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 187ac86a59..988178818d 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; namespace osu.Game.Database diff --git a/osu.Game/Database/INamedFile.cs b/osu.Game/Database/INamedFile.cs index 2bd45d4e42..5378d15a75 100644 --- a/osu.Game/Database/INamedFile.cs +++ b/osu.Game/Database/INamedFile.cs @@ -3,8 +3,6 @@ using osu.Game.Models; -#nullable enable - namespace osu.Game.Database { /// diff --git a/osu.Game/Database/INamedFileInfo.cs b/osu.Game/Database/INamedFileInfo.cs index d95f228440..9df4a0869c 100644 --- a/osu.Game/Database/INamedFileInfo.cs +++ b/osu.Game/Database/INamedFileInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.IO; namespace osu.Game.Database diff --git a/osu.Game/Database/INamedFileUsage.cs b/osu.Game/Database/INamedFileUsage.cs index e558ffe0fb..e2721f17bf 100644 --- a/osu.Game/Database/INamedFileUsage.cs +++ b/osu.Game/Database/INamedFileUsage.cs @@ -3,8 +3,6 @@ using osu.Game.IO; -#nullable enable - namespace osu.Game.Database { /// diff --git a/osu.Game/Database/IPostImports.cs b/osu.Game/Database/IPostImports.cs deleted file mode 100644 index 6f047098da..0000000000 --- a/osu.Game/Database/IPostImports.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (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; - -#nullable enable - -namespace osu.Game.Database -{ - public interface IPostImports - where TModel : class, IHasGuidPrimaryKey - { - /// - /// Fired when the user requests to view the resulting import. - /// - public Action>>? PostImport { set; } - } -} diff --git a/osu.Game/Database/IPostNotifications.cs b/osu.Game/Database/IPostNotifications.cs index d4fd64e79e..8bb2c54945 100644 --- a/osu.Game/Database/IPostNotifications.cs +++ b/osu.Game/Database/IPostNotifications.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Overlays.Notifications; diff --git a/osu.Game/Database/ISoftDelete.cs b/osu.Game/Database/ISoftDelete.cs index afa42c2002..b07c8db2de 100644 --- a/osu.Game/Database/ISoftDelete.cs +++ b/osu.Game/Database/ISoftDelete.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Database { /// diff --git a/osu.Game/Database/ImportProgressNotification.cs b/osu.Game/Database/ImportProgressNotification.cs index aaee3e117f..46f9936bc2 100644 --- a/osu.Game/Database/ImportProgressNotification.cs +++ b/osu.Game/Database/ImportProgressNotification.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays.Notifications; namespace osu.Game.Database diff --git a/osu.Game/Database/ImportTask.cs b/osu.Game/Database/ImportTask.cs index d75c1a73e6..e7f599d85f 100644 --- a/osu.Game/Database/ImportTask.cs +++ b/osu.Game/Database/ImportTask.cs @@ -1,19 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.IO; using osu.Framework.Extensions; using osu.Game.IO.Archives; -using osu.Game.Stores; using osu.Game.Utils; using SharpCompress.Common; namespace osu.Game.Database { /// - /// An encapsulated import task to be imported to an . + /// An encapsulated import task to be imported to an . /// public class ImportTask { @@ -36,7 +33,7 @@ namespace osu.Game.Database } /// - /// Construct a new import task from a stream. + /// Construct a new import task from a stream. The provided stream will be disposed after reading. /// public ImportTask(Stream stream, string filename) { @@ -65,6 +62,7 @@ namespace osu.Game.Database { // This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out). memoryStream = new MemoryStream(stream.ReadAllBytesToArray()); + stream.Dispose(); } if (ZipUtils.IsZipArchive(memoryStream)) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index fb8ee8f5f5..d064b9ed58 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Platform; using osu.Game.Beatmaps; diff --git a/osu.Game/Database/LegacyBeatmapImporter.cs b/osu.Game/Database/LegacyBeatmapImporter.cs index 97f6eba6c2..6805cb36b8 100644 --- a/osu.Game/Database/LegacyBeatmapImporter.cs +++ b/osu.Game/Database/LegacyBeatmapImporter.cs @@ -1,6 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.IO; @@ -13,6 +18,24 @@ namespace osu.Game.Database protected override Storage PrepareStableStorage(StableStorage stableStorage) => stableStorage.GetSongStorage(); + protected override IEnumerable GetStableImportPaths(Storage storage) + { + foreach (string directory in storage.GetDirectories(string.Empty)) + { + var directoryStorage = storage.GetStorageForDirectory(directory); + + if (!directoryStorage.GetFiles(string.Empty).ExcludeSystemFileNames().Any()) + { + // if a directory doesn't contain files, attempt looking for beatmaps inside of that directory. + // this is a special behaviour in stable for beatmaps only, see https://github.com/ppy/osu/issues/18615. + foreach (string subDirectory in GetStableImportPaths(directoryStorage)) + yield return subDirectory; + } + else + yield return storage.GetFullPath(directory); + } + } + public LegacyBeatmapImporter(IModelImporter importer) : base(importer) { diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 992d1854e7..d9fdc40abc 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Platform; using osu.Game.Extensions; diff --git a/osu.Game/Database/LegacyImportManager.cs b/osu.Game/Database/LegacyImportManager.cs index af9db1b6ec..f40e0d33c2 100644 --- a/osu.Game/Database/LegacyImportManager.cs +++ b/osu.Game/Database/LegacyImportManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Threading; diff --git a/osu.Game/Database/LegacyModelImporter.cs b/osu.Game/Database/LegacyModelImporter.cs index 9b2a54dada..df354a856e 100644 --- a/osu.Game/Database/LegacyModelImporter.cs +++ b/osu.Game/Database/LegacyModelImporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 336f50bc3d..6fa02b957d 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using osu.Framework.Platform; diff --git a/osu.Game/Database/LegacyScoreImporter.cs b/osu.Game/Database/LegacyScoreImporter.cs index 131b4ffb0e..f61241141e 100644 --- a/osu.Game/Database/LegacyScoreImporter.cs +++ b/osu.Game/Database/LegacyScoreImporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 9432a1b5fc..1d5364fb8d 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Platform; using osu.Game.Skinning; diff --git a/osu.Game/Database/LegacySkinImporter.cs b/osu.Game/Database/LegacySkinImporter.cs index 2f05ccae45..42b2f2e1d8 100644 --- a/osu.Game/Database/LegacySkinImporter.cs +++ b/osu.Game/Database/LegacySkinImporter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Skinning; namespace osu.Game.Database diff --git a/osu.Game/Database/Live.cs b/osu.Game/Database/Live.cs index 6256902e17..e9f99e1e44 100644 --- a/osu.Game/Database/Live.cs +++ b/osu.Game/Database/Live.cs @@ -3,8 +3,6 @@ using System; -#nullable enable - namespace osu.Game.Database { /// diff --git a/osu.Game/Database/MemoryCachingComponent.cs b/osu.Game/Database/MemoryCachingComponent.cs index a1a1279d71..571a9ccc7c 100644 --- a/osu.Game/Database/MemoryCachingComponent.cs +++ b/osu.Game/Database/MemoryCachingComponent.cs @@ -1,11 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; +using osu.Framework.Statistics; namespace osu.Game.Database { @@ -17,8 +22,16 @@ namespace osu.Game.Database { private readonly ConcurrentDictionary cache = new ConcurrentDictionary(); + private readonly GlobalStatistic statistics; + protected virtual bool CacheNullValues => true; + protected MemoryCachingComponent() + { + statistics = GlobalStatistics.Get(nameof(MemoryCachingComponent), GetType().ReadableName()); + statistics.Value = new MemoryCachingStatistics(); + } + /// /// Retrieve the cached value for the given lookup. /// @@ -27,16 +40,39 @@ namespace osu.Game.Database protected async Task GetAsync([NotNull] TLookup lookup, CancellationToken token = default) { if (CheckExists(lookup, out TValue performance)) + { + statistics.Value.HitCount++; return performance; + } var computed = await ComputeValueAsync(lookup, token).ConfigureAwait(false); + statistics.Value.MissCount++; + if (computed != null || CacheNullValues) + { cache[lookup] = computed; + statistics.Value.Usage = cache.Count; + } return computed; } + /// + /// Invalidate all entries matching a provided predicate. + /// + /// The predicate to decide which keys should be invalidated. + protected void Invalidate(Func matchKeyPredicate) + { + foreach (var kvp in cache) + { + if (matchKeyPredicate(kvp.Key)) + cache.TryRemove(kvp.Key, out _); + } + + statistics.Value.Usage = cache.Count; + } + protected bool CheckExists([NotNull] TLookup lookup, out TValue value) => cache.TryGetValue(lookup, out value); @@ -47,5 +83,31 @@ namespace osu.Game.Database /// An optional to cancel the operation. /// The computed value. protected abstract Task ComputeValueAsync(TLookup lookup, CancellationToken token = default); + + private class MemoryCachingStatistics + { + /// + /// Total number of cache hits. + /// + public int HitCount; + + /// + /// Total number of cache misses. + /// + public int MissCount; + + /// + /// Total number of cached entities. + /// + public int Usage; + + public override string ToString() + { + int totalAccesses = HitCount + MissCount; + double hitRate = totalAccesses == 0 ? 0 : (double)HitCount / totalAccesses; + + return $"i:{Usage} h:{HitCount} m:{MissCount} {hitRate:0%}"; + } + } } } diff --git a/osu.Game/Database/ModelDownloader.cs b/osu.Game/Database/ModelDownloader.cs index 2fa3357b06..02bcb342e4 100644 --- a/osu.Game/Database/ModelDownloader.cs +++ b/osu.Game/Database/ModelDownloader.cs @@ -17,18 +17,18 @@ namespace osu.Game.Database where TModel : class, IHasGuidPrimaryKey, ISoftDelete, IEquatable, T where T : class { - public Action PostNotification { protected get; set; } + public Action? PostNotification { protected get; set; } - public event Action> DownloadBegan; + public event Action>? DownloadBegan; - public event Action> DownloadFailed; + public event Action>? DownloadFailed; private readonly IModelImporter importer; - private readonly IAPIProvider api; + private readonly IAPIProvider? api; protected readonly List> CurrentDownloads = new List>(); - protected ModelDownloader(IModelImporter importer, IAPIProvider api) + protected ModelDownloader(IModelImporter importer, IAPIProvider? api) { this.importer = importer; this.api = api; @@ -85,7 +85,7 @@ namespace osu.Game.Database CurrentDownloads.Add(request); PostNotification?.Invoke(notification); - api.PerformAsync(request); + api?.PerformAsync(request); DownloadBegan?.Invoke(request); return true; @@ -103,7 +103,7 @@ namespace osu.Game.Database } } - public abstract ArchiveDownloadRequest GetExistingDownload(T model); + public abstract ArchiveDownloadRequest? GetExistingDownload(T model); private bool canDownload(T model) => GetExistingDownload(model) == null && api != null; diff --git a/osu.Game/Stores/RealmArchiveModelManager.cs b/osu.Game/Database/ModelManager.cs similarity index 88% rename from osu.Game/Stores/RealmArchiveModelManager.cs rename to osu.Game/Database/ModelManager.cs index cc8229b436..4224c92f2c 100644 --- a/osu.Game/Stores/RealmArchiveModelManager.cs +++ b/osu.Game/Database/ModelManager.cs @@ -3,31 +3,28 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using osu.Framework.Platform; -using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Models; using osu.Game.Overlays.Notifications; using Realms; -#nullable enable - -namespace osu.Game.Stores +namespace osu.Game.Database { - /// - /// Class which adds all the missing pieces bridging the gap between and (legacy) ArchiveModelManager. - /// - public abstract class RealmArchiveModelManager : RealmArchiveModelImporter, IModelManager, IModelFileManager + public class ModelManager : IModelManager, IModelFileManager where TModel : RealmObject, IHasRealmFiles, IHasGuidPrimaryKey, ISoftDelete { + protected RealmAccess Realm { get; } + private readonly RealmFileStore realmFileStore; - protected RealmArchiveModelManager(Storage storage, RealmAccess realm) - : base(storage, realm) + public ModelManager(Storage storage, RealmAccess realm) { realmFileStore = new RealmFileStore(realm, storage); + Realm = realm; } public void DeleteFile(TModel item, RealmNamedFileUsage file) => @@ -50,6 +47,7 @@ namespace osu.Game.Stores Realm.Realm.Write(realm => { var managed = realm.Find(item.ID); + Debug.Assert(managed != null); operation(managed); item.Files.Clear(); @@ -63,7 +61,7 @@ namespace osu.Game.Stores /// /// Delete a file from within an ongoing realm transaction. /// - protected void DeleteFile(TModel item, RealmNamedFileUsage file, Realm realm) + public void DeleteFile(TModel item, RealmNamedFileUsage file, Realm realm) { item.Files.Remove(file); } @@ -71,7 +69,7 @@ namespace osu.Game.Stores /// /// Replace a file from within an ongoing realm transaction. /// - protected void ReplaceFile(RealmNamedFileUsage file, Stream contents, Realm realm) + public void ReplaceFile(RealmNamedFileUsage file, Stream contents, Realm realm) { file.File = realmFileStore.Add(contents, realm); } @@ -79,7 +77,7 @@ namespace osu.Game.Stores /// /// Add a file from within an ongoing realm transaction. If the file already exists, it is overwritten. /// - protected void AddFile(TModel item, Stream contents, string filename, Realm realm) + public void AddFile(TModel item, Stream contents, string filename, Realm realm) { var existing = item.Files.FirstOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase)); @@ -201,6 +199,10 @@ namespace osu.Game.Stores }); } - public abstract bool IsAvailableLocally(TModel model); + public virtual bool IsAvailableLocally(TModel model) => true; + + public Action? PostNotification { get; set; } + + public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLowerInvariant()}"; } } diff --git a/osu.Game/Database/OnlineLookupCache.cs b/osu.Game/Database/OnlineLookupCache.cs index 506103a2c0..317c37bbfb 100644 --- a/osu.Game/Database/OnlineLookupCache.cs +++ b/osu.Game/Database/OnlineLookupCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 79183b6f0e..118a8ee469 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 086ec52d80..dff2bdddbd 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.ComponentModel; @@ -28,7 +26,6 @@ using osu.Game.Models; using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Skinning; -using osu.Game.Stores; using Realms; using Realms.Exceptions; @@ -61,15 +58,23 @@ namespace osu.Game.Database /// 12 2021-11-24 Add Status to RealmBeatmapSet. /// 13 2022-01-13 Final migration of beatmaps and scores to realm (multiple new storage fields). /// 14 2022-03-01 Added BeatmapUserSettings to BeatmapInfo. + /// 15 2022-07-13 Added LastPlayed to BeatmapInfo. + /// 16 2022-07-15 Removed HasReplay from ScoreInfo. + /// 17 2022-07-16 Added CountryCode to RealmUser. + /// 18 2022-07-19 Added OnlineMD5Hash and LastOnlineUpdate to BeatmapInfo. + /// 19 2022-07-19 Added DateSubmitted and DateRanked to BeatmapSetInfo. /// - private const int schema_version = 14; + private const int schema_version = 19; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. /// private readonly SemaphoreSlim realmRetrievalLock = new SemaphoreSlim(1); - private readonly ThreadLocal currentThreadCanCreateRealmInstances = new ThreadLocal(); + /// + /// true when the current thread has already entered the . + /// + private readonly ThreadLocal currentThreadHasRealmRetrievalLock = new ThreadLocal(); /// /// Holds a map of functions registered via and and a coinciding action which when triggered, @@ -101,10 +106,14 @@ namespace osu.Game.Database private static readonly GlobalStatistic total_writes_async = GlobalStatistics.Get(@"Realm", @"Writes (Async)"); - private readonly object realmLock = new object(); - private Realm? updateRealm; + /// + /// Tracks whether a realm was ever fetched from this instance. + /// After a fetch occurs, blocking operations will be guaranteed to restore any subscriptions. + /// + private bool hasInitialisedOnce; + private bool isSendingNotificationResetEvents; public Realm Realm => ensureUpdateRealm(); @@ -119,23 +128,21 @@ namespace osu.Game.Database if (!ThreadSafety.IsUpdateThread) throw new InvalidOperationException(@$"Use {nameof(getRealmInstance)} when performing realm operations from a non-update thread"); - lock (realmLock) + if (updateRealm == null) { - if (updateRealm == null) - { - updateRealm = getRealmInstance(); + updateRealm = getRealmInstance(); + hasInitialisedOnce = true; - Logger.Log(@$"Opened realm ""{updateRealm.Config.DatabasePath}"" at version {updateRealm.Config.SchemaVersion}"); + Logger.Log(@$"Opened realm ""{updateRealm.Config.DatabasePath}"" at version {updateRealm.Config.SchemaVersion}"); - // Resubscribe any subscriptions - foreach (var action in customSubscriptionsResetMap.Keys) - registerSubscription(action); - } - - Debug.Assert(updateRealm != null); - - return updateRealm; + // Resubscribe any subscriptions + foreach (var action in customSubscriptionsResetMap.Keys.ToArray()) + registerSubscription(action); } + + Debug.Assert(updateRealm != null); + + return updateRealm; } internal static bool CurrentThreadSubscriptionsAllowed => current_thread_subscriptions_allowed.Value; @@ -185,14 +192,14 @@ namespace osu.Game.Database // If a newer version database already exists, don't backup again. We can presume that the first backup is the one we care about. if (!storage.Exists(newerVersionFilename)) - CreateBackup(newerVersionFilename); + createBackup(newerVersionFilename); storage.Delete(Filename); } else { Logger.Error(e, "Realm startup failed with unrecoverable error; starting with a fresh database. A backup of your database has been made."); - CreateBackup($"{Filename.Replace(realm_extension, string.Empty)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}_corrupt{realm_extension}"); + createBackup($"{Filename.Replace(realm_extension, string.Empty)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}_corrupt{realm_extension}"); storage.Delete(Filename); } @@ -237,7 +244,7 @@ namespace osu.Game.Database } // For extra safety, also store the temporarily-used database which we are about to replace. - CreateBackup($"{Filename.Replace(realm_extension, string.Empty)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}_newer_version_before_recovery{realm_extension}"); + createBackup($"{Filename.Replace(realm_extension, string.Empty)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}_newer_version_before_recovery{realm_extension}"); storage.Delete(Filename); @@ -384,15 +391,43 @@ namespace osu.Game.Database } } + private readonly CountdownEvent pendingAsyncWrites = new CountdownEvent(0); + /// /// Write changes to realm asynchronously, guaranteeing order of execution. /// /// The work to run. - public async Task WriteAsync(Action action) + public Task WriteAsync(Action action) { - total_writes_async.Value++; - using (var realm = getRealmInstance()) - await realm.WriteAsync(() => action(realm)); + if (isDisposed) + throw new ObjectDisposedException(nameof(RealmAccess)); + + // Required to ensure the write is tracked and accounted for before disposal. + // Can potentially be avoided if we have a need to do so in the future. + if (!ThreadSafety.IsUpdateThread) + throw new InvalidOperationException(@$"{nameof(WriteAsync)} must be called from the update thread."); + + // CountdownEvent will fail if already at zero. + if (!pendingAsyncWrites.TryAddCount()) + pendingAsyncWrites.Reset(1); + + // Regardless of calling Realm.GetInstance or Realm.GetInstanceAsync, there is a blocking overhead on retrieval. + // Adding a forced Task.Run resolves this. + var writeTask = Task.Run(async () => + { + total_writes_async.Value++; + + // Not attempting to use Realm.GetInstanceAsync as there's seemingly no benefit to us (for now) and it adds complexity due to locking + // concerns in getRealmInstance(). On a quick check, it looks to be more suited to cases where realm is connecting to an online sync + // server, which we don't use. May want to report upstream or revisit in the future. + using (var realm = getRealmInstance()) + // ReSharper disable once AccessToDisposedClosure (WriteAsync should be marked as [InstantHandle]). + await realm.WriteAsync(() => action(realm)); + + pendingAsyncWrites.Signal(); + }); + + return writeTask; } /// @@ -417,14 +452,15 @@ namespace osu.Game.Database public IDisposable RegisterForNotifications(Func> query, NotificationCallbackDelegate callback) where T : RealmObjectBase { - lock (realmLock) - { - Func action = realm => query(realm).QueryAsyncWithNotifications(callback); + Func action = realm => query(realm).QueryAsyncWithNotifications(callback); + lock (notificationsResetMap) + { // Store an action which is used when blocking to ensure consumers don't use results of a stale changeset firing. notificationsResetMap.Add(action, () => callback(new EmptyRealmSet(), null, null)); - return RegisterCustomSubscription(action); } + + return RegisterCustomSubscription(action); } /// @@ -446,7 +482,7 @@ namespace osu.Game.Database public IDisposable SubscribeToPropertyChanged(Func modelAccessor, Expression> propertyLookup, Action onChanged) where TModel : RealmObjectBase { - return RegisterCustomSubscription(r => + return RegisterCustomSubscription(_ => { string propertyName = getMemberName(propertyLookup); @@ -515,15 +551,17 @@ namespace osu.Game.Database void unsubscribe() { - lock (realmLock) + if (customSubscriptionsResetMap.TryGetValue(action, out var unsubscriptionAction)) { - if (customSubscriptionsResetMap.TryGetValue(action, out var unsubscriptionAction)) + unsubscriptionAction?.Dispose(); + customSubscriptionsResetMap.Remove(action); + + lock (notificationsResetMap) { - unsubscriptionAction?.Dispose(); - customSubscriptionsResetMap.Remove(action); notificationsResetMap.Remove(action); - total_subscriptions.Value--; } + + total_subscriptions.Value--; } } }); @@ -533,19 +571,16 @@ namespace osu.Game.Database { Debug.Assert(ThreadSafety.IsUpdateThread); - lock (realmLock) - { - // Retrieve realm instance outside of flag update to ensure that the instance is retrieved, - // as attempting to access it inside the subscription if it's not constructed would lead to - // cyclic invocations of the subscription callback. - var realm = Realm; + // Retrieve realm instance outside of flag update to ensure that the instance is retrieved, + // as attempting to access it inside the subscription if it's not constructed would lead to + // cyclic invocations of the subscription callback. + var realm = Realm; - Debug.Assert(!customSubscriptionsResetMap.TryGetValue(action, out var found) || found == null); + Debug.Assert(!customSubscriptionsResetMap.TryGetValue(action, out var found) || found == null); - current_thread_subscriptions_allowed.Value = true; - customSubscriptionsResetMap[action] = action(realm); - current_thread_subscriptions_allowed.Value = false; - } + current_thread_subscriptions_allowed.Value = true; + customSubscriptionsResetMap[action] = action(realm); + current_thread_subscriptions_allowed.Value = false; } private Realm getRealmInstance() @@ -557,10 +592,11 @@ namespace osu.Game.Database try { - if (!currentThreadCanCreateRealmInstances.Value) + // Ensure that the thread that currently has the `realmRetrievalLock` can retrieve nested contexts and not deadlock on itself. + if (!currentThreadHasRealmRetrievalLock.Value) { realmRetrievalLock.Wait(); - currentThreadCanCreateRealmInstances.Value = true; + currentThreadHasRealmRetrievalLock.Value = true; tookSemaphoreLock = true; } else @@ -584,7 +620,7 @@ namespace osu.Game.Database if (tookSemaphoreLock) { realmRetrievalLock.Release(); - currentThreadCanCreateRealmInstances.Value = false; + currentThreadHasRealmRetrievalLock.Value = false; } } } @@ -751,28 +787,37 @@ namespace osu.Game.Database private string? getRulesetShortNameFromLegacyID(long rulesetId) => efContextFactory?.Get().RulesetInfo.FirstOrDefault(r => r.ID == rulesetId)?.ShortName; + /// + /// Create a full realm backup. + /// + /// The filename for the backup. public void CreateBackup(string backupFilename) { - using (BlockAllOperations()) + if (realmRetrievalLock.CurrentCount != 0) + throw new InvalidOperationException($"Call {nameof(BlockAllOperations)} before creating a backup."); + + createBackup(backupFilename); + } + + private void createBackup(string backupFilename) + { + Logger.Log($"Creating full realm database backup at {backupFilename}", LoggingTarget.Database); + + int attempts = 10; + + while (attempts-- > 0) { - Logger.Log($"Creating full realm database backup at {backupFilename}", LoggingTarget.Database); - - int attempts = 10; - - while (attempts-- > 0) + try { - try - { - using (var source = storage.GetStream(Filename)) - using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew)) - source.CopyTo(destination); - return; - } - catch (IOException) - { - // file may be locked during use. - Thread.Sleep(500); - } + using (var source = storage.GetStream(Filename, mode: FileMode.Open)) + using (var destination = storage.GetStream(backupFilename, FileAccess.Write, FileMode.CreateNew)) + source.CopyTo(destination); + return; + } + catch (IOException) + { + // file may be locked during use. + Thread.Sleep(500); } } } @@ -784,9 +829,15 @@ namespace osu.Game.Database /// This should be used in places we need to ensure no ongoing reads/writes are occurring with realm. /// ie. to move the realm backing file to a new location. /// + /// The reason for blocking. Used for logging purposes. /// An which should be disposed to end the blocking section. - public IDisposable BlockAllOperations() + public IDisposable BlockAllOperations(string reason) { + Logger.Log($@"Attempting to block all realm operations for {reason}.", LoggingTarget.Database); + + if (!ThreadSafety.IsUpdateThread) + throw new InvalidOperationException(@$"{nameof(BlockAllOperations)} must be called from the update thread."); + if (isDisposed) throw new ObjectDisposedException(nameof(RealmAccess)); @@ -796,39 +847,27 @@ namespace osu.Game.Database { realmRetrievalLock.Wait(); - lock (realmLock) + if (hasInitialisedOnce) { - if (updateRealm == null) + syncContext = SynchronizationContext.Current; + + // Before disposing the update context, clean up all subscriptions. + // Note that in the case of realm notification subscriptions, this is not really required (they will be cleaned up by disposal). + // In the case of custom subscriptions, we want them to fire before the update realm is disposed in case they do any follow-up work. + foreach (var action in customSubscriptionsResetMap.ToArray()) { - // null realm means the update thread has not yet retrieved its instance. - // we don't need to worry about reviving the update instance in this case, so don't bother with the SynchronizationContext. - Debug.Assert(!ThreadSafety.IsUpdateThread); + action.Value?.Dispose(); + customSubscriptionsResetMap[action.Key] = null; } - else - { - if (!ThreadSafety.IsUpdateThread) - throw new InvalidOperationException(@$"{nameof(BlockAllOperations)} must be called from the update thread."); - - syncContext = SynchronizationContext.Current; - - // Before disposing the update context, clean up all subscriptions. - // Note that in the case of realm notification subscriptions, this is not really required (they will be cleaned up by disposal). - // In the case of custom subscriptions, we want them to fire before the update realm is disposed in case they do any follow-up work. - foreach (var action in customSubscriptionsResetMap) - { - action.Value?.Dispose(); - customSubscriptionsResetMap[action.Key] = null; - } - } - - Logger.Log(@"Blocking realm operations.", LoggingTarget.Database); updateRealm?.Dispose(); updateRealm = null; } + Logger.Log(@"Lock acquired for blocking operations", LoggingTarget.Database); + const int sleep_length = 200; - int timeout = 5000; + int timeSpent = 0; try { @@ -836,10 +875,10 @@ namespace osu.Game.Database while (!Compact()) { Thread.Sleep(sleep_length); - timeout -= sleep_length; + timeSpent += sleep_length; - if (timeout < 0) - throw new TimeoutException(@"Took too long to acquire lock"); + if (timeSpent > 5000) + throw new TimeoutException($@"Realm compact failed after {timeSpent / sleep_length} attempts over {timeSpent / 1000} seconds"); } } catch (RealmException e) @@ -849,6 +888,8 @@ namespace osu.Game.Database Logger.Log($"Realm compact failed with error {e}", LoggingTarget.Database); } + Logger.Log(@"Realm usage isolated via compact", LoggingTarget.Database); + // In order to ensure events arrive in the correct order, these *must* be fired post disposal of the update realm, // and must be posted to the synchronization context. // This is because realm may fire event callbacks between the `unregisterAllSubscriptions` and `updateRealm.Dispose` @@ -862,8 +903,11 @@ namespace osu.Game.Database try { - foreach (var action in notificationsResetMap.Values) - action(); + lock (notificationsResetMap) + { + foreach (var action in notificationsResetMap.Values) + action(); + } } finally { @@ -881,16 +925,39 @@ namespace osu.Game.Database void restoreOperation() { + // Release of lock needs to happen here rather than on the update thread, as there may be another + // operation already blocking the update thread waiting for the blocking operation to complete. Logger.Log(@"Restoring realm operations.", LoggingTarget.Database); realmRetrievalLock.Release(); + if (syncContext == null) return; + + ManualResetEventSlim updateRealmReestablished = new ManualResetEventSlim(); + // Post back to the update thread to revive any subscriptions. // In the case we are on the update thread, let's also require this to run synchronously. // This requirement is mostly due to test coverage, but shouldn't cause any harm. if (ThreadSafety.IsUpdateThread) - syncContext?.Send(_ => ensureUpdateRealm(), null); + { + syncContext.Send(_ => + { + ensureUpdateRealm(); + updateRealmReestablished.Set(); + }, null); + } else - syncContext?.Post(_ => ensureUpdateRealm(), null); + { + syncContext.Post(_ => + { + ensureUpdateRealm(); + updateRealmReestablished.Set(); + }, null); + } + + // Wait for the post to complete to ensure a second `Migrate` operation doesn't start in the mean time. + // This is important to ensure `ensureUpdateRealm` is run before another blocking migration operation starts. + if (!updateRealmReestablished.Wait(10000)) + throw new TimeoutException(@"Reestablishing update realm after block took too long"); } } @@ -901,10 +968,10 @@ namespace osu.Game.Database public void Dispose() { - lock (realmLock) - { - updateRealm?.Dispose(); - } + if (!pendingAsyncWrites.Wait(10000)) + Logger.Log("Realm took too long waiting on pending async writes", level: LogLevel.Error); + + updateRealm?.Dispose(); if (!isDisposed) { diff --git a/osu.Game/Stores/RealmArchiveModelImporter.cs b/osu.Game/Database/RealmArchiveModelImporter.cs similarity index 73% rename from osu.Game/Stores/RealmArchiveModelImporter.cs rename to osu.Game/Database/RealmArchiveModelImporter.cs index 6d1449a4b4..aa7fac07a8 100644 --- a/osu.Game/Stores/RealmArchiveModelImporter.cs +++ b/osu.Game/Database/RealmArchiveModelImporter.cs @@ -13,16 +13,13 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Threading; -using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO.Archives; using osu.Game.Models; using osu.Game.Overlays.Notifications; using Realms; -#nullable enable - -namespace osu.Game.Stores +namespace osu.Game.Database { /// /// Encapsulates a model store class to give it import functionality. @@ -32,12 +29,16 @@ namespace osu.Game.Stores public abstract class RealmArchiveModelImporter : IModelImporter where TModel : RealmObject, IHasRealmFiles, IHasGuidPrimaryKey, ISoftDelete { + /// + /// The maximum number of concurrent imports to run per import scheduler. + /// private const int import_queue_request_concurrency = 1; /// - /// The size of a batch import operation before considering it a lower priority operation. + /// The minimum number of items in a single import call in order for the import to be processed as a batch. + /// Batch imports will apply optimisations preferring speed over consistency when detecting changes in already-imported items. /// - private const int low_priority_import_batch_size = 1; + private const int minimum_items_considered_batch_import = 10; /// /// A singleton scheduler shared by all . @@ -49,13 +50,13 @@ namespace osu.Game.Stores private static readonly ThreadedTaskScheduler import_scheduler = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(RealmArchiveModelImporter)); /// - /// A second scheduler for lower priority imports. + /// A second scheduler for batch imports. /// For simplicity, these will just run in parallel with normal priority imports, but a future refactor would see this implemented via a custom scheduler/queue. /// See https://gist.github.com/peppy/f0e118a14751fc832ca30dd48ba3876b for an incomplete version of this. /// - private static readonly ThreadedTaskScheduler import_scheduler_low_priority = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(RealmArchiveModelImporter)); + private static readonly ThreadedTaskScheduler import_scheduler_batch = new ThreadedTaskScheduler(import_queue_request_concurrency, nameof(RealmArchiveModelImporter)); - public virtual IEnumerable HandledExtensions => new[] { @".zip" }; + public abstract IEnumerable HandledExtensions { get; } protected readonly RealmFileStore Files; @@ -64,12 +65,12 @@ namespace osu.Game.Stores /// /// Fired when the user requests to view the resulting import. /// - public Action>>? PostImport { get; set; } + public Action>>? PresentImport { get; set; } /// /// Set an endpoint for notifications to be posted to. /// - public Action? PostNotification { protected get; set; } + public Action? PostNotification { get; set; } protected RealmArchiveModelImporter(Storage storage, RealmAccess realm) { @@ -78,22 +79,7 @@ namespace osu.Game.Stores Files = new RealmFileStore(realm, storage); } - /// - /// Import one or more items from filesystem . - /// - /// - /// This will be treated as a low priority import if more than one path is specified; use to always import at standard priority. - /// This will post notifications tracking progress. - /// - /// One or more archive locations on disk. - public Task Import(params string[] paths) - { - var notification = new ProgressNotification { State = ProgressNotificationState.Active }; - - PostNotification?.Invoke(notification); - - return Import(notification, paths.Select(p => new ImportTask(p)).ToArray()); - } + public Task Import(params string[] paths) => Import(paths.Select(p => new ImportTask(p)).ToArray()); public Task Import(params ImportTask[] tasks) { @@ -120,7 +106,7 @@ namespace osu.Game.Stores var imported = new List>(); - bool isLowPriorityImport = tasks.Length > low_priority_import_batch_size; + bool isBatchImport = tasks.Length >= minimum_items_considered_batch_import; try { @@ -130,7 +116,7 @@ namespace osu.Game.Stores try { - var model = await Import(task, isLowPriorityImport, notification.CancellationToken).ConfigureAwait(false); + var model = await Import(task, isBatchImport, notification.CancellationToken).ConfigureAwait(false); lock (imported) { @@ -172,12 +158,12 @@ namespace osu.Game.Stores ? $"Imported {imported.First().GetDisplayString()}!" : $"Imported {imported.Count} {HumanisedModelName}s!"; - if (imported.Count > 0 && PostImport != null) + if (imported.Count > 0 && PresentImport != null) { notification.CompletionText += " Click to view."; notification.CompletionClickAction = () => { - PostImport?.Invoke(imported); + PresentImport?.Invoke(imported); return true; }; } @@ -193,16 +179,16 @@ namespace osu.Game.Stores /// Note that this bypasses the UI flow and should only be used for special cases or testing. /// /// The containing data about the to import. - /// Whether this is a low priority import. + /// Whether this import is part of a larger batch. /// An optional cancellation token. /// The imported model, if successful. - public async Task?> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default) + public async Task?> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); Live? import; using (ArchiveReader reader = task.GetReader()) - import = await Import(reader, lowPriority, cancellationToken).ConfigureAwait(false); + import = await importFromArchive(reader, batchImport, cancellationToken).ConfigureAwait(false); // 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. @@ -222,12 +208,15 @@ namespace osu.Game.Stores } /// - /// Silently import an item from an . + /// Create and import a model based off the provided . /// + /// + /// This method also handled queueing the import task on a relevant import thread pool. + /// /// The archive to be imported. - /// Whether this is a low priority import. + /// Whether this import is part of a larger batch. /// An optional cancellation token. - public async Task?> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default) + private async Task?> importFromArchive(ArchiveReader archive, bool batchImport = false, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -250,14 +239,123 @@ namespace osu.Game.Stores return null; } - var scheduledImport = Task.Factory.StartNew(() => Import(model, archive, lowPriority, cancellationToken), + var scheduledImport = Task.Factory.StartNew(() => ImportModel(model, archive, batchImport, cancellationToken), cancellationToken, TaskCreationOptions.HideScheduler, - lowPriority ? import_scheduler_low_priority : import_scheduler); + batchImport ? import_scheduler_batch : import_scheduler); return await scheduledImport.ConfigureAwait(false); } + /// + /// Silently import an item from a . + /// + /// The model to be imported. + /// An optional archive to use for model population. + /// If true, imports will be skipped before they begin, given an existing model matches on hash and filenames. Should generally only be used for large batch imports, as it may defy user expectations when updating an existing model. + /// An optional cancellation token. + public virtual Live? ImportModel(TModel item, ArchiveReader? archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => Realm.Run(realm => + { + cancellationToken.ThrowIfCancellationRequested(); + + TModel? existing; + + if (batchImport && archive != null) + { + // this is a fast bail condition to improve large import performance. + item.Hash = computeHashFast(archive); + + existing = CheckForExisting(item, realm); + + if (existing != null) + { + // bare minimum comparisons + // + // note that this should really be checking filesizes on disk (of existing files) for some degree of sanity. + // or alternatively doing a faster hash check. either of these require database changes and reprocessing of existing files. + if (CanSkipImport(existing, item) && + getFilenames(existing.Files).SequenceEqual(getShortenedFilenames(archive).Select(p => p.shortened).OrderBy(f => f)) && + checkAllFilesExist(existing)) + { + LogForModel(item, @$"Found existing (optimised) {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); + + using (var transaction = realm.BeginWrite()) + { + UndeleteForReuse(existing); + transaction.Commit(); + } + + return existing.ToLive(Realm); + } + + LogForModel(item, @"Found existing (optimised) but failed pre-check."); + } + } + + try + { + // Log output here will be missing a valid hash in non-batch imports. + LogForModel(item, $@"Beginning import from {archive?.Name ?? "unknown"}..."); + + // TODO: do we want to make the transaction this local? not 100% sure, will need further investigation. + using (var transaction = realm.BeginWrite()) + { + if (archive != null) + // TODO: look into rollback of file additions (or delayed commit). + item.Files.AddRange(createFileInfos(archive, Files, realm)); + + item.Hash = ComputeHash(item); + + // TODO: we may want to run this outside of the transaction. + Populate(item, archive, realm, cancellationToken); + + // Populate() may have adjusted file content (see SkinImporter.updateSkinIniMetadata), so regardless of whether a fast check was done earlier, let's + // check for existing items a second time. + // + // If this is ever a performance issue, the fast-check hash can be compared and trigger a skip of this second check if it still matches. + // I don't think it is a huge deal doing a second indexed check, though. + existing = CheckForExisting(item, realm); + + if (existing != null) + { + if (CanReuseExisting(existing, item)) + { + LogForModel(item, @$"Found existing {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); + + UndeleteForReuse(existing); + transaction.Commit(); + + return existing.ToLive(Realm); + } + + LogForModel(item, @"Found existing but failed re-use check."); + + existing.DeletePending = true; + } + + PreImport(item, realm); + + // import to store + realm.Add(item); + + PostImport(item, realm); + + transaction.Commit(); + } + + LogForModel(item, @"Import successfully completed!"); + } + catch (Exception e) + { + if (!(e is TaskCanceledException)) + LogForModel(item, @"Database import or population failed and has been rolled back.", e); + + throw; + } + + return (Live?)item.ToLive(Realm); + }); + /// /// Any file extensions which should be included in hash creation. /// Generally should include all file types which determine the file's uniqueness. @@ -284,19 +382,13 @@ namespace osu.Game.Stores Logger.Log($"{prefix} {message}", LoggingTarget.Database); } - /// - /// Whether the implementation overrides with a custom implementation. - /// Custom hash implementations must bypass the early exit in the import flow (see usage). - /// - protected virtual bool HasCustomHashFunction => false; - /// /// Create a SHA-2 hash from the provided archive based on file content of all files matching . /// /// /// In the case of no matching files, a hash will be generated from the passed archive's . /// - protected virtual string ComputeHash(TModel item) + public string ComputeHash(TModel item) { // for now, concatenate all hashable files in the set to create a unique hash. MemoryStream hashable = new MemoryStream(); @@ -313,113 +405,6 @@ namespace osu.Game.Stores return item.Hash; } - /// - /// Silently import an item from a . - /// - /// The model to be imported. - /// An optional archive to use for model population. - /// Whether this is a low priority import. - /// An optional cancellation token. - public virtual Live? Import(TModel item, ArchiveReader? archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return Realm.Run(realm => - { - cancellationToken.ThrowIfCancellationRequested(); - - bool checkedExisting = false; - TModel? existing = null; - - if (archive != null && !HasCustomHashFunction) - { - // this is a fast bail condition to improve large import performance. - item.Hash = computeHashFast(archive); - - checkedExisting = true; - existing = CheckForExisting(item, realm); - - if (existing != null) - { - // bare minimum comparisons - // - // note that this should really be checking filesizes on disk (of existing files) for some degree of sanity. - // or alternatively doing a faster hash check. either of these require database changes and reprocessing of existing files. - if (CanSkipImport(existing, item) && - getFilenames(existing.Files).SequenceEqual(getShortenedFilenames(archive).Select(p => p.shortened).OrderBy(f => f)) && - checkAllFilesExist(existing)) - { - LogForModel(item, @$"Found existing (optimised) {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); - - using (var transaction = realm.BeginWrite()) - { - UndeleteForReuse(existing); - transaction.Commit(); - } - - return existing.ToLive(Realm); - } - - LogForModel(item, @"Found existing (optimised) but failed pre-check."); - } - } - - try - { - LogForModel(item, @"Beginning import..."); - - // TODO: do we want to make the transaction this local? not 100% sure, will need further investigation. - using (var transaction = realm.BeginWrite()) - { - if (archive != null) - // TODO: look into rollback of file additions (or delayed commit). - item.Files.AddRange(createFileInfos(archive, Files, realm)); - - item.Hash = ComputeHash(item); - - // TODO: we may want to run this outside of the transaction. - Populate(item, archive, realm, cancellationToken); - - if (!checkedExisting) - existing = CheckForExisting(item, realm); - - if (existing != null) - { - if (CanReuseExisting(existing, item)) - { - LogForModel(item, @$"Found existing {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import."); - - UndeleteForReuse(existing); - transaction.Commit(); - - return existing.ToLive(Realm); - } - - LogForModel(item, @"Found existing but failed re-use check."); - - existing.DeletePending = true; - } - - PreImport(item, realm); - - // import to store - realm.Add(item); - - transaction.Commit(); - } - - LogForModel(item, @"Import successfully completed!"); - } - catch (Exception e) - { - if (!(e is TaskCanceledException)) - LogForModel(item, @"Database import or population failed and has been rolled back.", e); - - throw; - } - - return (Live?)item.ToLive(Realm); - }); - } - private string computeHashFast(ArchiveReader reader) { MemoryStream hashable = new MemoryStream(); @@ -493,6 +478,15 @@ namespace osu.Game.Stores { } + /// + /// Perform any final actions before the import has been committed to the database. + /// + /// The model prepared for import. + /// The current realm context. + protected virtual void PostImport(TModel model, Realm realm) + { + } + /// /// Check whether an existing model already exists for a new import item. /// @@ -521,8 +515,7 @@ namespace osu.Game.Stores // for the best or worst, we copy and import files of a new import before checking whether // it is a duplicate. so to check if anything has changed, we can just compare all File IDs. getIDs(existing.Files).SequenceEqual(getIDs(import.Files)) && - getFilenames(existing.Files).SequenceEqual(getFilenames(import.Files)) && - checkAllFilesExist(existing); + getFilenames(existing.Files).SequenceEqual(getFilenames(import.Files)); private bool checkAllFilesExist(TModel model) => model.Files.All(f => Files.Storage.Exists(f.File.GetStoragePath())); @@ -559,6 +552,6 @@ namespace osu.Game.Stores yield return f.Filename; } - public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLower()}"; + public virtual string HumanisedModelName => $"{typeof(TModel).Name.Replace(@"Info", "").ToLowerInvariant()}"; } } diff --git a/osu.Game/Database/RealmExtensions.cs b/osu.Game/Database/RealmExtensions.cs index 551b84f7b6..13c4defb83 100644 --- a/osu.Game/Database/RealmExtensions.cs +++ b/osu.Game/Database/RealmExtensions.cs @@ -4,25 +4,64 @@ using System; using Realms; -#nullable enable - namespace osu.Game.Database { public static class RealmExtensions { + /// + /// Perform a write operation against the provided realm instance. + /// + /// + /// This will automatically start a transaction if not already in one. + /// + /// The realm to operate on. + /// The write operation to run. public static void Write(this Realm realm, Action function) { - using var transaction = realm.BeginWrite(); - function(realm); - transaction.Commit(); + Transaction? transaction = null; + + try + { + if (!realm.IsInTransaction) + transaction = realm.BeginWrite(); + + function(realm); + + transaction?.Commit(); + } + finally + { + transaction?.Dispose(); + } } + /// + /// Perform a write operation against the provided realm instance. + /// + /// + /// This will automatically start a transaction if not already in one. + /// + /// The realm to operate on. + /// The write operation to run. public static T Write(this Realm realm, Func function) { - using var transaction = realm.BeginWrite(); - var result = function(realm); - transaction.Commit(); - return result; + Transaction? transaction = null; + + try + { + if (!realm.IsInTransaction) + transaction = realm.BeginWrite(); + + var result = function(realm); + + transaction?.Commit(); + + return result; + } + finally + { + transaction?.Dispose(); + } } /// diff --git a/osu.Game/Stores/RealmFileStore.cs b/osu.Game/Database/RealmFileStore.cs similarity index 98% rename from osu.Game/Stores/RealmFileStore.cs rename to osu.Game/Database/RealmFileStore.cs index 457d70f29a..ecb152c45c 100644 --- a/osu.Game/Stores/RealmFileStore.cs +++ b/osu.Game/Database/RealmFileStore.cs @@ -9,14 +9,11 @@ using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Testing; -using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Models; using Realms; -#nullable enable - -namespace osu.Game.Stores +namespace osu.Game.Database { /// /// Handles the storing of files to the file system (and database) backing. diff --git a/osu.Game/Database/RealmLive.cs b/osu.Game/Database/RealmLive.cs index ecfececaa4..9c871a3929 100644 --- a/osu.Game/Database/RealmLive.cs +++ b/osu.Game/Database/RealmLive.cs @@ -7,8 +7,6 @@ using osu.Framework.Development; using osu.Framework.Statistics; using Realms; -#nullable enable - namespace osu.Game.Database { /// @@ -106,9 +104,12 @@ namespace osu.Game.Database PerformRead(t => { - var transaction = t.Realm.BeginWrite(); - perform(t); - transaction.Commit(); + using (var transaction = t.Realm.BeginWrite()) + { + perform(t); + transaction.Commit(); + } + RealmLiveStatistics.WRITES.Value++; }); } diff --git a/osu.Game/Database/RealmLiveUnmanaged.cs b/osu.Game/Database/RealmLiveUnmanaged.cs index 1080f3b8c7..5ab66cac7b 100644 --- a/osu.Game/Database/RealmLiveUnmanaged.cs +++ b/osu.Game/Database/RealmLiveUnmanaged.cs @@ -4,8 +4,6 @@ using System; using Realms; -#nullable enable - namespace osu.Game.Database { /// diff --git a/osu.Game/Database/RealmObjectExtensions.cs b/osu.Game/Database/RealmObjectExtensions.cs index 6dc18df9e0..a771aa04df 100644 --- a/osu.Game/Database/RealmObjectExtensions.cs +++ b/osu.Game/Database/RealmObjectExtensions.cs @@ -14,15 +14,13 @@ using osu.Game.Rulesets; using osu.Game.Scoring; using Realms; -#nullable enable - namespace osu.Game.Database { public static class RealmObjectExtensions { private static readonly IMapper write_mapper = new MapperConfiguration(c => { - c.ShouldMapField = fi => false; + c.ShouldMapField = _ => false; c.ShouldMapProperty = pi => pi.SetMethod?.IsPublic == true; c.CreateMap() @@ -72,7 +70,7 @@ namespace osu.Game.Database } }); - c.Internal().ForAllMaps((typeMap, expression) => + c.Internal().ForAllMaps((_, expression) => { expression.ForAllMembers(m => { @@ -89,7 +87,7 @@ namespace osu.Game.Database c.CreateMap() .ConstructUsing(_ => new BeatmapSetInfo(null)) .MaxDepth(2) - .AfterMap((s, d) => + .AfterMap((_, d) => { foreach (var beatmap in d.Beatmaps) beatmap.BeatmapSet = d; @@ -99,7 +97,7 @@ namespace osu.Game.Database // Only hasn't been done yet as we detach at the point of BeatmapInfo less often. c.CreateMap() .MaxDepth(2) - .AfterMap((s, d) => + .AfterMap((_, d) => { for (int i = 0; i < d.BeatmapSet?.Beatmaps.Count; i++) { @@ -123,7 +121,7 @@ namespace osu.Game.Database .ConstructUsing(_ => new BeatmapSetInfo(null)) .MaxDepth(2) .ForMember(b => b.Files, cc => cc.Ignore()) - .AfterMap((s, d) => + .AfterMap((_, d) => { foreach (var beatmap in d.Beatmaps) beatmap.BeatmapSet = d; @@ -137,14 +135,14 @@ namespace osu.Game.Database private static void applyCommonConfiguration(IMapperConfigurationExpression c) { - c.ShouldMapField = fi => false; + c.ShouldMapField = _ => false; // This is specifically to avoid mapping explicit interface implementations. // If we want to limit this further, we can avoid mapping properties with no setter that are not IList<>. // Takes a bit of effort to determine whether this is the case though, see https://stackoverflow.com/questions/951536/how-do-i-tell-whether-a-type-implements-ilist c.ShouldMapProperty = pi => pi.GetMethod?.IsPublic == true; - c.Internal().ForAllMaps((typeMap, expression) => + c.Internal().ForAllMaps((_, expression) => { expression.ForAllMembers(m => { diff --git a/osu.Game/Database/UserLookupCache.cs b/osu.Game/Database/UserLookupCache.cs index 5fdd80892d..87f08d36ae 100644 --- a/osu.Game/Database/UserLookupCache.cs +++ b/osu.Game/Database/UserLookupCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index d1aba2bfe3..35f2d61437 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -1,7 +1,6 @@ // 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 osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -67,7 +66,7 @@ namespace osu.Game.Extensions foreach (var (_, property) in component.GetSettingsSourceProperties()) { - if (!info.Settings.TryGetValue(property.Name.Underscore(), out object settingValue)) + if (!info.Settings.TryGetValue(property.Name.ToSnakeCase(), out object settingValue)) continue; skinnable.CopyAdjustedSetting((IBindable)property.GetValue(component), settingValue); diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs index 13c25e45c8..b10071bb45 100644 --- a/osu.Game/Extensions/ModelExtensions.cs +++ b/osu.Game/Extensions/ModelExtensions.cs @@ -11,8 +11,6 @@ using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Users; -#nullable enable - namespace osu.Game.Extensions { public static class ModelExtensions diff --git a/osu.Game/Extensions/StringDehumanizeExtensions.cs b/osu.Game/Extensions/StringDehumanizeExtensions.cs new file mode 100644 index 0000000000..6f0d7622d3 --- /dev/null +++ b/osu.Game/Extensions/StringDehumanizeExtensions.cs @@ -0,0 +1,94 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +// Based on code from the Humanizer library (https://github.com/Humanizr/Humanizer/blob/606e958cb83afc9be5b36716ac40d4daa9fa73a7/src/Humanizer/InflectorExtensions.cs) +// +// Humanizer is licenced under the MIT License (MIT) +// +// Copyright (c) .NET Foundation and Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Text.RegularExpressions; + +namespace osu.Game.Extensions +{ + /// + /// Class with extension methods used to turn human-readable strings to casing conventions frequently used in code. + /// Often used for communicating with other systems (web API, spectator server). + /// All of the operations in this class are intentionally culture-invariant. + /// + public static class StringDehumanizeExtensions + { + /// + /// Converts the string to "Pascal case" (also known as "upper camel case"). + /// + /// + /// + /// "this is a test string".ToPascalCase() == "ThisIsATestString" + /// + /// + public static string ToPascalCase(this string input) + { + return Regex.Replace(input, "(?:^|_|-| +)(.)", match => match.Groups[1].Value.ToUpperInvariant()); + } + + /// + /// Converts the string to (lower) "camel case". + /// + /// + /// + /// "this is a test string".ToCamelCase() == "thisIsATestString" + /// + /// + public static string ToCamelCase(this string input) + { + string word = input.ToPascalCase(); + return word.Length > 0 ? word.Substring(0, 1).ToLowerInvariant() + word.Substring(1) : word; + } + + /// + /// Converts the string to "snake case". + /// + /// + /// + /// "this is a test string".ToSnakeCase() == "this_is_a_test_string" + /// + /// + public static string ToSnakeCase(this string input) + { + return Regex.Replace( + Regex.Replace( + Regex.Replace(input, @"([\p{Lu}]+)([\p{Lu}][\p{Ll}])", "$1_$2"), @"([\p{Ll}\d])([\p{Lu}])", "$1_$2"), @"[-\s]", "_").ToLowerInvariant(); + } + + /// + /// Converts the string to "kebab case". + /// + /// + /// + /// "this is a test string".ToKebabCase() == "this-is-a-test-string" + /// + /// + public static string ToKebabCase(this string input) + { + return ToSnakeCase(input).Replace('_', '-'); + } + } +} diff --git a/osu.Game/Extensions/TaskExtensions.cs b/osu.Game/Extensions/TaskExtensions.cs index 17f1a491f8..b4a0c02e35 100644 --- a/osu.Game/Extensions/TaskExtensions.cs +++ b/osu.Game/Extensions/TaskExtensions.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Threading; using System.Threading.Tasks; @@ -33,7 +31,7 @@ namespace osu.Game.Extensions { var tcs = new TaskCompletionSource(); - task.ContinueWith(t => + task.ContinueWith(_ => { // the previous task has finished execution or been cancelled, so we can run the provided continuation. diff --git a/osu.Game/Extensions/TypeExtensions.cs b/osu.Game/Extensions/TypeExtensions.cs index 2e93c81758..072b18b0ba 100644 --- a/osu.Game/Extensions/TypeExtensions.cs +++ b/osu.Game/Extensions/TypeExtensions.cs @@ -21,7 +21,7 @@ namespace osu.Game.Extensions /// internal static string GetInvariantInstantiationInfo(this Type type) { - string assemblyQualifiedName = type.AssemblyQualifiedName; + string? assemblyQualifiedName = type.AssemblyQualifiedName; if (assemblyQualifiedName == null) throw new ArgumentException($"{type}'s assembly-qualified name is null. Ensure that it is a concrete type and not a generic type parameter.", nameof(type)); diff --git a/osu.Game/Extensions/WebRequestExtensions.cs b/osu.Game/Extensions/WebRequestExtensions.cs index 50837a648d..a80b79f259 100644 --- a/osu.Game/Extensions/WebRequestExtensions.cs +++ b/osu.Game/Extensions/WebRequestExtensions.cs @@ -16,7 +16,7 @@ namespace osu.Game.Extensions /// public static void AddCursor(this WebRequest webRequest, Cursor cursor) { - cursor?.Properties.ForEach(x => + cursor.Properties.ForEach(x => { webRequest.AddParameter("cursor[" + x.Key + "]", (x.Value as JValue)?.ToString(CultureInfo.InvariantCulture) ?? x.Value.ToString()); }); diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index b09ec1d9b9..2dd96bcb09 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index e0c15dd52a..543bfe2bac 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs index 7aed442800..0dcfa4e9aa 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs b/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs index f01a26a3a8..99af95b5fe 100644 --- a/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs +++ b/osu.Game/Graphics/Backgrounds/SeasonalBackgroundLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -36,15 +38,21 @@ namespace osu.Game.Graphics.Backgrounds private void load(OsuConfigManager config, SessionStatics sessionStatics) { seasonalBackgroundMode = config.GetBindable(OsuSetting.SeasonalBackgroundMode); - seasonalBackgroundMode.BindValueChanged(_ => SeasonalBackgroundChanged?.Invoke()); + seasonalBackgroundMode.BindValueChanged(_ => triggerSeasonalBackgroundChanged()); seasonalBackgrounds = sessionStatics.GetBindable(Static.SeasonalBackgrounds); - seasonalBackgrounds.BindValueChanged(_ => SeasonalBackgroundChanged?.Invoke()); + seasonalBackgrounds.BindValueChanged(_ => triggerSeasonalBackgroundChanged()); apiState.BindTo(api.State); apiState.BindValueChanged(fetchSeasonalBackgrounds, true); } + private void triggerSeasonalBackgroundChanged() + { + if (shouldShowSeasonal) + SeasonalBackgroundChanged?.Invoke(); + } + private void fetchSeasonalBackgrounds(ValueChangedEvent stateChanged) { if (seasonalBackgrounds.Value != null || stateChanged.NewValue != APIState.Online) @@ -62,15 +70,10 @@ namespace osu.Game.Graphics.Backgrounds public SeasonalBackground LoadNextBackground() { - if (seasonalBackgroundMode.Value == SeasonalBackgroundMode.Never - || (seasonalBackgroundMode.Value == SeasonalBackgroundMode.Sometimes && !isInSeason)) - { + if (!shouldShowSeasonal) return null; - } - var backgrounds = seasonalBackgrounds.Value?.Backgrounds; - if (backgrounds == null || !backgrounds.Any()) - return null; + var backgrounds = seasonalBackgrounds.Value.Backgrounds; current = (current + 1) % backgrounds.Count; string url = backgrounds[current].Url; @@ -78,6 +81,20 @@ namespace osu.Game.Graphics.Backgrounds return new SeasonalBackground(url); } + private bool shouldShowSeasonal + { + get + { + if (seasonalBackgroundMode.Value == SeasonalBackgroundMode.Never) + return false; + + if (seasonalBackgroundMode.Value == SeasonalBackgroundMode.Sometimes && !isInSeason) + return false; + + return seasonalBackgrounds.Value?.Backgrounds?.Any() == true; + } + } + private bool isInSeason => seasonalBackgrounds.Value != null && DateTimeOffset.Now < seasonalBackgrounds.Value.EndDate; } diff --git a/osu.Game/Graphics/Backgrounds/SkinBackground.cs b/osu.Game/Graphics/Backgrounds/SkinBackground.cs index 9266e7b17b..e4bf3b94c5 100644 --- a/osu.Game/Graphics/Backgrounds/SkinBackground.cs +++ b/osu.Game/Graphics/Backgrounds/SkinBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Skinning; diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 450c93f37c..b83df45bd7 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Utils; using osuTK; diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index 953731244d..e1998a1d7f 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework.Allocation; @@ -26,7 +28,8 @@ namespace osu.Game.Graphics.Containers public class BeatSyncedContainer : Container { private int lastBeat; - private TimingControlPoint lastTimingPoint; + protected TimingControlPoint LastTimingPoint { get; private set; } + protected EffectControlPoint LastEffectPoint { get; private set; } /// /// The amount of time before a beat we should fire . @@ -84,7 +87,7 @@ namespace osu.Game.Graphics.Containers TimingControlPoint timingPoint; EffectControlPoint effectPoint; - IsBeatSyncedWithTrack = BeatSyncSource.Clock?.IsRunning == true; + IsBeatSyncedWithTrack = BeatSyncSource.Clock?.IsRunning == true && BeatSyncSource.ControlPoints != null; double currentTrackTime; @@ -125,7 +128,7 @@ namespace osu.Game.Graphics.Containers TimeSinceLastBeat = beatLength - TimeUntilNextBeat; - if (timingPoint == lastTimingPoint && beatIndex == lastBeat) + if (ReferenceEquals(timingPoint, LastTimingPoint) && beatIndex == lastBeat) return; // as this event is sometimes used for sound triggers where `BeginDelayedSequence` has no effect, avoid firing it if too far away from the beat. @@ -137,7 +140,8 @@ namespace osu.Game.Graphics.Containers } lastBeat = beatIndex; - lastTimingPoint = timingPoint; + LastTimingPoint = timingPoint; + LastEffectPoint = effectPoint; } } } diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index 9e1af1944c..f34a856707 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs b/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs index 859850e771..f66afb27c4 100644 --- a/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs +++ b/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Graphics.Containers { /// diff --git a/osu.Game/Graphics/Containers/ExpandingContainer.cs b/osu.Game/Graphics/Containers/ExpandingContainer.cs index b50e008362..debc068220 100644 --- a/osu.Game/Graphics/Containers/ExpandingContainer.cs +++ b/osu.Game/Graphics/Containers/ExpandingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index 28afd082c3..7d38478b81 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/Containers/IExpandable.cs b/osu.Game/Graphics/Containers/IExpandable.cs index 593564a2f9..05d569775c 100644 --- a/osu.Game/Graphics/Containers/IExpandable.cs +++ b/osu.Game/Graphics/Containers/IExpandable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/IExpandingContainer.cs b/osu.Game/Graphics/Containers/IExpandingContainer.cs index eb186c96a8..dbd9274ae7 100644 --- a/osu.Game/Graphics/Containers/IExpandingContainer.cs +++ b/osu.Game/Graphics/Containers/IExpandingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 1d286d3487..bf96695fd3 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.Chat; using System; using System.Linq; @@ -11,6 +13,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Framework.Platform; +using osu.Game.Online; using osu.Game.Users; namespace osu.Game.Graphics.Containers @@ -23,7 +26,7 @@ namespace osu.Game.Graphics.Containers } [Resolved(CanBeNull = true)] - private OsuGame game { get; set; } + private ILinkHandler linkHandler { get; set; } [Resolved] private GameHost host { get; set; } @@ -79,8 +82,8 @@ namespace osu.Game.Graphics.Containers { if (action != null) action(); - else if (game != null) - game.HandleLink(link); + else if (linkHandler != null) + linkHandler.HandleLink(link); // fallback to handle cases where OsuGame is not available, ie. tournament client. else if (link.Action == LinkAction.External) host.OpenUrlExternally(link.Argument.ToString()); diff --git a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs index f89f3a5e76..bf8d70a200 100644 --- a/osu.Game/Graphics/Containers/LogoTrackingContainer.cs +++ b/osu.Game/Graphics/Containers/LogoTrackingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 296c600771..a2370a76cb 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig; using Markdig.Extensions.AutoIdentifiers; using Markdig.Extensions.Tables; @@ -25,7 +27,7 @@ namespace osu.Game.Graphics.Containers.Markdown { switch (markdownObject) { - case YamlFrontMatterBlock _: + case YamlFrontMatterBlock: // Don't parse YAML Frontmatter break; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs index 0d67849060..fc7401046f 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index e4685a2935..0c70952222 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs index ce8a9c8f9f..9ad501fdff 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax.Inlines; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs index 82e556f653..3a16eb0a0f 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownLinkText.cs @@ -1,11 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; +using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Overlays; @@ -14,7 +17,7 @@ namespace osu.Game.Graphics.Containers.Markdown public class OsuMarkdownLinkText : MarkdownLinkText { [Resolved(canBeNull: true)] - private OsuGame game { get; set; } + private ILinkHandler linkHandler { get; set; } private readonly string text; private readonly string title; @@ -49,7 +52,7 @@ namespace osu.Game.Graphics.Containers.Markdown }; } - protected override void OnLinkPressed() => game?.HandleLink(Url); + protected override void OnLinkPressed() => linkHandler?.HandleLink(Url); private class OsuMarkdownLinkCompiler : DrawableLinkCompiler { diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs index 8c4c3e1da2..153c4f9f93 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownListItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs index 8fedb189b2..116a8e2872 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index 9935c81537..3ef67df7a9 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs index 28a87c9f21..abbc10a7e2 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs index e0a1ab1220..ee851045f9 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Extensions.Tables; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index ac7d07e283..3863beb133 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Extensions.Tables; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs index a7cd6b3905..db8abfb269 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTextFlowContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs index 5d1e114781..f8e8571557 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index bf397e4251..61ec9dfc24 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 512602d120..e8a0c0cd25 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index ac66fd658a..93205e0d03 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs index 1048fd094c..b604ae73eb 100644 --- a/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListContainer.cs @@ -1,9 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Collections.Specialized; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; namespace osu.Game.Graphics.Containers { @@ -16,11 +23,49 @@ namespace osu.Game.Graphics.Containers protected override ScrollContainer CreateScrollContainer() => new OsuScrollContainer(); + private Sample sampleSwap; + private double sampleLastPlaybackTime; + protected sealed override RearrangeableListItem CreateDrawable(TModel item) => CreateOsuDrawable(item).With(d => { d.DragActive.BindTo(DragActive); }); protected abstract OsuRearrangeableListItem CreateOsuDrawable(TModel item); + + protected override void LoadComplete() + { + base.LoadComplete(); + + Items.CollectionChanged += (_, args) => + { + if (args.Action == NotifyCollectionChangedAction.Move) + playSwapSample(); + }; + } + + private void playSwapSample() + { + if (!DragActive.Value) + return; + + if (Time.Current - sampleLastPlaybackTime <= 35) + return; + + var channel = sampleSwap?.GetChannel(); + if (channel == null) + return; + + channel.Frequency.Value = 0.96 + RNG.NextDouble(0.08); + channel.Play(); + sampleLastPlaybackTime = Time.Current; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleSwap = audio.Samples.Get(@"UI/item-swap"); + sampleLastPlaybackTime = Time.Current; + } } } diff --git a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs index d43c3a608b..e6183ea837 100644 --- a/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs +++ b/osu.Game/Graphics/Containers/OsuRearrangeableListItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 817b8409e6..7e5d5e53d3 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs index b8237832a3..5cdccee01d 100644 --- a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index b501e68ba1..f70abc16dd 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs index 6360e41bef..db265d6d64 100644 --- a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 5c6e315225..17c51129a7 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -258,7 +260,7 @@ namespace osu.Game.Graphics.Containers if (host.Window == null) return; bool coversWholeScreen = Size == Vector2.One && safeArea.SafeAreaPadding.Value.Total == Vector2.Zero; - host.Window.CursorConfineRect = coversWholeScreen ? (RectangleF?)null : ToScreenSpace(DrawRectangle).AABBFloat; + host.Window.CursorConfineRect = coversWholeScreen ? null : ToScreenSpace(DrawRectangle).AABBFloat; } } } diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 6ad538959e..c04a5add89 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs index 4ddaa09be6..94505d2310 100644 --- a/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework; diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 8a0ce287db..7b6fc22cc0 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Extensions; diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 4e555ac1eb..d52fb7c60a 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs index 44afaf77ea..2bb9d7261d 100644 --- a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs +++ b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Graphics.Containers diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 8b87ddaa20..ba85ef0aab 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Cursor/IProvideCursor.cs b/osu.Game/Graphics/Cursor/IProvideCursor.cs index 3a920ba976..9f01e5da6d 100644 --- a/osu.Game/Graphics/Cursor/IProvideCursor.cs +++ b/osu.Game/Graphics/Cursor/IProvideCursor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 03fad00e41..862a10208c 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -1,21 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +#nullable disable + +using System; +using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; -using osu.Game.Configuration; -using System; -using JetBrains.Annotations; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; -using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osu.Framework.Utils; +using osu.Game.Configuration; +using osuTK; namespace osu.Game.Graphics.Cursor { @@ -33,6 +35,7 @@ namespace osu.Game.Graphics.Cursor private Vector2 positionMouseDown; private Sample tapSample; + private Vector2 lastMovePosition; [BackgroundDependencyLoader(true)] private void load([NotNull] OsuConfigManager config, [CanBeNull] ScreenshotManager screenshotManager, AudioManager audio) @@ -45,16 +48,29 @@ namespace osu.Game.Graphics.Cursor tapSample = audio.Samples.Get(@"UI/cursor-tap"); } + protected override void Update() + { + base.Update(); + + if (dragRotationState != DragRotationState.NotDragging + && Vector2.Distance(positionMouseDown, lastMovePosition) > 60) + { + // make the rotation centre point floating. + positionMouseDown = Interpolation.ValueAt(0.04f, positionMouseDown, lastMovePosition, 0, Clock.ElapsedFrameTime); + } + } + protected override bool OnMouseMove(MouseMoveEvent e) { if (dragRotationState != DragRotationState.NotDragging) { - var position = e.MousePosition; - float distance = Vector2Extensions.Distance(position, positionMouseDown); + lastMovePosition = e.MousePosition; + + float distance = Vector2Extensions.Distance(lastMovePosition, positionMouseDown); // don't start rotating until we're moved a minimum distance away from the mouse down location, // else it can have an annoying effect. - if (dragRotationState == DragRotationState.DragStarted && distance > 30) + if (dragRotationState == DragRotationState.DragStarted && distance > 80) dragRotationState = DragRotationState.Rotating; // don't rotate when distance is zero to avoid NaN @@ -69,7 +85,7 @@ namespace osu.Game.Graphics.Cursor if (diff > 180) diff -= 360; degrees = activeCursor.Rotation + diff; - activeCursor.RotateTo(degrees, 600, Easing.OutQuint); + activeCursor.RotateTo(degrees, 120, Easing.OutQuint); } } @@ -109,7 +125,7 @@ namespace osu.Game.Graphics.Cursor if (dragRotationState != DragRotationState.NotDragging) { - activeCursor.RotateTo(0, 600 * (1 + Math.Abs(activeCursor.Rotation / 720)), Easing.OutElasticHalf); + activeCursor.RotateTo(0, 400 * (0.5f + Math.Abs(activeCursor.Rotation / 960)), Easing.OutElasticQuarter); dragRotationState = DragRotationState.NotDragging; } diff --git a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs index 4c7f7957e9..746f1b5d5e 100644 --- a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index 171ad4ee65..fbaefe24b0 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; 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 35d7b4e795..8bf4dfcd24 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/DateTooltip.cs b/osu.Game/Graphics/DateTooltip.cs index 2dca8719e9..77bf78b213 100644 --- a/osu.Game/Graphics/DateTooltip.cs +++ b/osu.Game/Graphics/DateTooltip.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 567a39b4f4..0008d0fcaa 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/ErrorTextFlowContainer.cs b/osu.Game/Graphics/ErrorTextFlowContainer.cs index dafc363973..0d47245e8c 100644 --- a/osu.Game/Graphics/ErrorTextFlowContainer.cs +++ b/osu.Game/Graphics/ErrorTextFlowContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index af497da70f..fc722375ce 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Graphics/InputBlockingContainer.cs b/osu.Game/Graphics/InputBlockingContainer.cs index d8387b1401..66caa57c1a 100644 --- a/osu.Game/Graphics/InputBlockingContainer.cs +++ b/osu.Game/Graphics/InputBlockingContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs index 8714138322..a53b665857 100644 --- a/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs +++ b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.InteropServices; using osu.Framework.Graphics.OpenGL.Vertices; diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 7fd94b57f3..0e411876d3 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Beatmaps; diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs index edb484021c..038ea0f5d7 100644 --- a/osu.Game/Graphics/OsuFont.cs +++ b/osu.Game/Graphics/OsuFont.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics @@ -35,7 +37,10 @@ namespace osu.Game.Graphics /// Whether all characters should be spaced the same distance apart. /// The . public static FontUsage GetFont(Typeface typeface = Typeface.Torus, float size = DEFAULT_FONT_SIZE, FontWeight weight = FontWeight.Medium, bool italics = false, bool fixedWidth = false) - => new FontUsage(GetFamilyString(typeface), size, GetWeightString(typeface, weight), getItalics(italics), fixedWidth); + { + string familyString = GetFamilyString(typeface); + return new FontUsage(familyString, size, GetWeightString(familyString, weight), getItalics(italics), fixedWidth); + } private static bool getItalics(in bool italicsRequested) { @@ -54,16 +59,16 @@ namespace osu.Game.Graphics switch (typeface) { case Typeface.Venera: - return "Venera"; + return @"Venera"; case Typeface.Torus: - return "Torus"; + return @"Torus"; case Typeface.TorusAlternate: - return "Torus-Alternate"; + return @"Torus-Alternate"; case Typeface.Inter: - return "Inter"; + return @"Inter"; } return null; @@ -72,25 +77,17 @@ namespace osu.Game.Graphics /// /// Retrieves the string representation of a . /// - /// The . - /// The . - /// The string representation of in the specified . - public static string GetWeightString(Typeface typeface, FontWeight weight) + /// The font family. + /// The font weight. + /// The string representation of in the specified . + public static string GetWeightString(string family, FontWeight weight) { - if (typeface == Typeface.Torus && weight == FontWeight.Medium) + if ((family == GetFamilyString(Typeface.Torus) || family == GetFamilyString(Typeface.TorusAlternate)) && weight == FontWeight.Medium) // torus doesn't have a medium; fallback to regular. weight = FontWeight.Regular; - return GetWeightString(GetFamilyString(typeface), weight); + return weight.ToString(); } - - /// - /// Retrieves the string representation of a . - /// - /// The family string. - /// The . - /// The string representation of in the specified . - public static string GetWeightString(string family, FontWeight weight) => weight.ToString(); } public static class OsuFontExtensions diff --git a/osu.Game/Graphics/OsuIcon.cs b/osu.Game/Graphics/OsuIcon.cs index e8267edab0..0a099f1fcc 100644 --- a/osu.Game/Graphics/OsuIcon.cs +++ b/osu.Game/Graphics/OsuIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics diff --git a/osu.Game/Graphics/ParticleExplosion.cs b/osu.Game/Graphics/ParticleExplosion.cs index ec1077eb81..c6f9c1343b 100644 --- a/osu.Game/Graphics/ParticleExplosion.cs +++ b/osu.Game/Graphics/ParticleExplosion.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/ParticleSpewer.cs b/osu.Game/Graphics/ParticleSpewer.cs index 369a4b21c7..06c9882d72 100644 --- a/osu.Game/Graphics/ParticleSpewer.cs +++ b/osu.Game/Graphics/ParticleSpewer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 53f7d5791b..2cc9e63c87 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using System.Threading.Tasks; @@ -101,7 +103,9 @@ namespace osu.Game.Graphics framesWaitedEvent.Set(); }, 10, true); - framesWaitedEvent.Wait(); + if (!framesWaitedEvent.Wait(1000)) + throw new TimeoutException("Screenshot data did not arrive in a timely fashion"); + waitDelegate.Cancel(); } } diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index 9c43383a29..dca6b7158b 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index 36fcd39b54..13733bb3ad 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index 76e46513ba..a46ed27b9b 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Sprites diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 2b59ee0282..d2ed71dfc6 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; 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 0be928cf83..3c87b166ac 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index 407bf6a923..f55875ac58 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -72,7 +74,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()); + RemoveRange(Children.Where((_, index) => index >= value.Count()).ToList()); } } } diff --git a/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs b/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs index aa101d7e08..e0efa1d81c 100644 --- a/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; @@ -23,4 +25,4 @@ namespace osu.Game.Graphics.UserInterface TextFlow.Padding = new MarginPadding { Right = 35 }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index d06c227d4b..b6ae4d6dc5 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK; using osu.Framework; diff --git a/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs b/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs index 4e1c612f09..bec78c68d3 100644 --- a/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs b/osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs index 89a4c28c8c..1414979531 100644 --- a/osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/DangerousTriangleButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 69fbd744c9..52ad5c6b80 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Graphics/UserInterface/DownloadButton.cs b/osu.Game/Graphics/UserInterface/DownloadButton.cs index af270f30ae..dfbe6bd44d 100644 --- a/osu.Game/Graphics/UserInterface/DownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/DownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs index 4ecc543ffd..b469c21ab0 100644 --- a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs index 3dc99f2dbe..5a7cf0d73e 100644 --- a/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs index a05c0cfab0..92b0059157 100644 --- a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs +++ b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs index 60cb35b4c4..b2ffb4da7d 100644 --- a/osu.Game/Graphics/UserInterface/ExpandingBar.cs +++ b/osu.Game/Graphics/UserInterface/ExpandingBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osuTK; diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 1730e1478f..ae286f5092 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/FPSCounter.cs b/osu.Game/Graphics/UserInterface/FPSCounter.cs new file mode 100644 index 0000000000..07eb9fa3ca --- /dev/null +++ b/osu.Game/Graphics/UserInterface/FPSCounter.cs @@ -0,0 +1,273 @@ +// Copyright (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.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Platform; +using osu.Framework.Threading; +using osu.Framework.Utils; +using osu.Game.Configuration; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public class FPSCounter : VisibilityContainer, IHasCustomTooltip + { + private OsuSpriteText counterUpdateFrameTime = null!; + private OsuSpriteText counterDrawFPS = null!; + + private Container mainContent = null!; + + private Container background = null!; + + private Container counters = null!; + + private const float idle_background_alpha = 0.4f; + + private readonly BindableBool showFpsDisplay = new BindableBool(true); + + private double displayedFpsCount; + private double displayedFrameTime; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + public FPSCounter() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + InternalChildren = new Drawable[] + { + mainContent = new Container + { + Alpha = 0, + Height = 26, + Children = new Drawable[] + { + background = new Container + { + RelativeSizeAxes = Axes.Both, + CornerRadius = 5, + CornerExponent = 5f, + Masking = true, + Alpha = idle_background_alpha, + Children = new Drawable[] + { + new Box + { + Colour = colours.Gray0, + RelativeSizeAxes = Axes.Both, + }, + } + }, + counters = new Container + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + counterUpdateFrameTime = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(1), + Font = OsuFont.Default.With(fixedWidth: true, size: 16, weight: FontWeight.SemiBold), + Spacing = new Vector2(-1), + Y = -2, + }, + counterDrawFPS = new OsuSpriteText + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(2), + Font = OsuFont.Default.With(fixedWidth: true, size: 13, weight: FontWeight.SemiBold), + Spacing = new Vector2(-2), + Y = 10, + } + } + }, + } + }, + }; + + config.BindWith(OsuSetting.ShowFpsDisplay, showFpsDisplay); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + displayTemporarily(); + + showFpsDisplay.BindValueChanged(showFps => + { + State.Value = showFps.NewValue ? Visibility.Visible : Visibility.Hidden; + if (showFps.NewValue) + displayTemporarily(); + }, true); + + State.BindValueChanged(state => showFpsDisplay.Value = state.NewValue == Visibility.Visible); + } + + protected override void PopIn() => this.FadeIn(100); + + protected override void PopOut() => this.FadeOut(100); + + protected override bool OnHover(HoverEvent e) + { + background.FadeTo(1, 200); + displayTemporarily(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + background.FadeTo(idle_background_alpha, 200); + displayTemporarily(); + base.OnHoverLost(e); + } + + private bool isDisplayed; + + private ScheduledDelegate? fadeOutDelegate; + + private double aimDrawFPS; + private double aimUpdateFPS; + + private void displayTemporarily() + { + if (!isDisplayed) + { + mainContent.FadeTo(1, 300, Easing.OutQuint); + isDisplayed = true; + } + + fadeOutDelegate?.Cancel(); + fadeOutDelegate = null; + + if (!IsHovered) + { + fadeOutDelegate = Scheduler.AddDelayed(() => + { + mainContent.FadeTo(0, 300, Easing.OutQuint); + isDisplayed = false; + }, 2000); + } + } + + [Resolved] + private GameHost gameHost { get; set; } = null!; + + protected override void Update() + { + base.Update(); + + mainContent.Width = Math.Max(mainContent.Width, counters.DrawWidth); + + // Handle the case where the window has become inactive or the user changed the + // frame limiter (we want to show the FPS as it's changing, even if it isn't an outlier). + bool aimRatesChanged = updateAimFPS(); + + // TODO: this is wrong (elapsed clock time, not actual run time). + double newUpdateFrameTime = gameHost.UpdateThread.Clock.ElapsedFrameTime; + double newDrawFrameTime = gameHost.DrawThread.Clock.ElapsedFrameTime; + double newDrawFps = gameHost.DrawThread.Clock.FramesPerSecond; + + const double spike_time_ms = 20; + + bool hasUpdateSpike = displayedFrameTime < spike_time_ms && newUpdateFrameTime > spike_time_ms; + // use elapsed frame time rather then FramesPerSecond to better catch stutter frames. + bool hasDrawSpike = displayedFpsCount > (1000 / spike_time_ms) && newDrawFrameTime > spike_time_ms; + + // note that we use an elapsed time here of 1 intentionally. + // this weights all updates equally. if we passed in the elapsed time, longer frames would be weighted incorrectly lower. + displayedFrameTime = Interpolation.DampContinuously(displayedFrameTime, newUpdateFrameTime, hasUpdateSpike ? 0 : 100, 1); + + if (hasDrawSpike) + // show spike time using raw elapsed value, to account for `FramesPerSecond` being so averaged spike frames don't show. + displayedFpsCount = 1000 / newDrawFrameTime; + else + displayedFpsCount = Interpolation.DampContinuously(displayedFpsCount, newDrawFps, 100, Time.Elapsed); + + updateFpsDisplay(); + updateFrameTimeDisplay(); + + bool hasSignificantChanges = aimRatesChanged + || hasDrawSpike + || hasUpdateSpike + || displayedFpsCount < aimDrawFPS * 0.8 + || 1000 / displayedFrameTime < aimUpdateFPS * 0.8; + + if (hasSignificantChanges) + displayTemporarily(); + } + + private void updateFpsDisplay() + { + counterDrawFPS.Colour = getColour(displayedFpsCount / aimDrawFPS); + counterDrawFPS.Text = $"{displayedFpsCount:#,0}fps"; + } + + private void updateFrameTimeDisplay() + { + counterUpdateFrameTime.Text = displayedFrameTime < 5 + ? $"{displayedFrameTime:N1}ms" + : $"{displayedFrameTime:N0}ms"; + + counterUpdateFrameTime.Colour = getColour((1000 / displayedFrameTime) / aimUpdateFPS); + } + + private bool updateAimFPS() + { + if (gameHost.UpdateThread.Clock.Throttling) + { + double newAimDrawFPS = gameHost.DrawThread.Clock.MaximumUpdateHz; + double newAimUpdateFPS = gameHost.UpdateThread.Clock.MaximumUpdateHz; + + if (aimDrawFPS != newAimDrawFPS || aimUpdateFPS != newAimUpdateFPS) + { + aimDrawFPS = newAimDrawFPS; + aimUpdateFPS = newAimUpdateFPS; + return true; + } + } + else + { + double newAimFPS = gameHost.InputThread.Clock.MaximumUpdateHz; + + if (aimDrawFPS != newAimFPS || aimUpdateFPS != newAimFPS) + { + aimUpdateFPS = aimDrawFPS = newAimFPS; + return true; + } + } + + return false; + } + + private ColourInfo getColour(double performanceRatio) + { + if (performanceRatio < 0.5f) + return Interpolation.ValueAt(performanceRatio, colours.Red, colours.Orange2, 0, 0.5); + + return Interpolation.ValueAt(performanceRatio, colours.Orange2, colours.Lime0, 0.5, 0.9); + } + + public ITooltip GetCustomTooltip() => new FPSCounterTooltip(); + + public object TooltipContent => this; + } +} diff --git a/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs b/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs new file mode 100644 index 0000000000..bf53bff9b4 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/FPSCounterTooltip.cs @@ -0,0 +1,97 @@ +// 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; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; +using osu.Game.Graphics.Containers; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + public class FPSCounterTooltip : CompositeDrawable, ITooltip + { + private OsuTextFlowContainer textFlow = null!; + + [Resolved] + private GameHost gameHost { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.Both; + + CornerRadius = 15; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + Colour = colours.Gray1, + Alpha = 1, + RelativeSizeAxes = Axes.Both, + }, + new OsuTextFlowContainer(cp => + { + cp.Font = OsuFont.Default.With(weight: FontWeight.SemiBold); + }) + { + AutoSizeAxes = Axes.Both, + TextAnchor = Anchor.TopRight, + Margin = new MarginPadding { Left = 5, Vertical = 10 }, + Text = string.Join('\n', gameHost.Threads.Select(t => t.Name)) + }, + textFlow = new OsuTextFlowContainer(cp => + { + cp.Font = OsuFont.Default.With(fixedWidth: true, weight: FontWeight.Regular); + cp.Spacing = new Vector2(-1); + }) + { + Width = 190, + Margin = new MarginPadding { Left = 35, Right = 10, Vertical = 10 }, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.TopRight, + }, + }; + } + + private int lastUpdate; + + protected override void Update() + { + int currentSecond = (int)(Clock.CurrentTime / 100); + + if (currentSecond != lastUpdate) + { + lastUpdate = currentSecond; + + textFlow.Clear(); + + foreach (var thread in gameHost.Threads) + { + var clock = thread.Clock; + + string maximum = clock.Throttling + ? $"/{(clock.MaximumUpdateHz > 0 && clock.MaximumUpdateHz < 10000 ? clock.MaximumUpdateHz.ToString("0") : "∞"),4}" + : string.Empty; + + textFlow.AddParagraph($"{clock.FramesPerSecond:0}{maximum}fps ({clock.ElapsedFrameTime:0.00}ms)"); + } + } + } + + public void SetContent(object content) + { + } + + public void Move(Vector2 pos) + { + Position = pos; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index d3a76a0f1a..fce4221c87 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Input.Events; diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index 1d67c4e033..e16f1ee897 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/GrayButton.cs b/osu.Game/Graphics/UserInterface/GrayButton.cs index 0a2c83d5a8..d95032bce6 100644 --- a/osu.Game/Graphics/UserInterface/GrayButton.cs +++ b/osu.Game/Graphics/UserInterface/GrayButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index ba253a7c71..dab4390ede 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs b/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs index 34ab7626c9..20715309a2 100644 --- a/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs +++ b/osu.Game/Graphics/UserInterface/HoverSampleDebounceComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs index b88f81a143..6358317e9d 100644 --- a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs +++ b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Graphics.UserInterface @@ -20,6 +22,12 @@ namespace osu.Game.Graphics.UserInterface TabSelect, [Description("scrolltotop")] - ScrollToTop + ScrollToTop, + + [Description("dialog-cancel")] + DialogCancel, + + [Description("dialog-ok")] + DialogOk } } diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index 7db1efc75f..dd03e83ab1 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 858f517985..e0b5999c4d 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index 70db26c817..fe634390a2 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs index a75cf0639c..8be50a4b43 100644 --- a/osu.Game/Graphics/UserInterface/LoadingButton.cs +++ b/osu.Game/Graphics/UserInterface/LoadingButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/LoadingLayer.cs b/osu.Game/Graphics/UserInterface/LoadingLayer.cs index 47ba5fce4d..b3655eaab4 100644 --- a/osu.Game/Graphics/UserInterface/LoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/LoadingLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Graphics; @@ -53,12 +55,12 @@ namespace osu.Game.Graphics.UserInterface switch (e) { // blocking scroll can cause weird behaviour when this layer is used within a ScrollContainer. - case ScrollEvent _: + case ScrollEvent: return false; // blocking touch events causes the ISourcedFromTouch versions to not be fired, potentially impeding behaviour of drawables *above* the loading layer that may utilise these. // note that this will not work well if touch handling elements are beneath this loading layer (something to consider for the future). - case TouchEvent _: + case TouchEvent: return false; } diff --git a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs index 8174c4d5fe..864dd0a65e 100644 --- a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs +++ b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Graphics/UserInterface/MenuItemType.cs b/osu.Game/Graphics/UserInterface/MenuItemType.cs index 0269f2cb57..1eb45d6b1c 100644 --- a/osu.Game/Graphics/UserInterface/MenuItemType.cs +++ b/osu.Game/Graphics/UserInterface/MenuItemType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Graphics.UserInterface { public enum MenuItemType diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 8f0fed580f..7a3e54ddf1 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osuTK; @@ -17,7 +19,7 @@ using osu.Game.Overlays; namespace osu.Game.Graphics.UserInterface { - public class Nub : CompositeDrawable, IHasCurrentValue, IHasAccentColour + public class Nub : Container, IHasCurrentValue, IHasAccentColour { public const float HEIGHT = 15; diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 13b42c0f13..f720678a93 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 08514d94c3..291ff644fd 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index da511d8212..bbd8f8ecea 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index e0946fd9e1..cc5ce8f46d 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs b/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs index 921fef7951..c329974e28 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenuSamples.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 23e05c7ccc..ce2a690e92 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs index 528d7d60f8..3d4a8cf359 100644 --- a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index a16adcbd57..a11bffd05d 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index 1da60415ba..9d65d6b8b9 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs index 8a3b77d3c2..93d47792c8 100644 --- a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index b276159558..305b1b6687 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osuTK.Input; diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 21c8dfcfa4..c48627bd21 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using JetBrains.Annotations; @@ -36,8 +38,8 @@ namespace osu.Game.Graphics.UserInterface private T lastSampleValue; protected readonly Nub Nub; - private readonly Box leftBox; - private readonly Box rightBox; + protected readonly Box LeftBox; + protected readonly Box RightBox; private readonly Container nubContainer; public virtual LocalisableString TooltipText { get; private set; } @@ -55,7 +57,7 @@ namespace osu.Game.Graphics.UserInterface set { accentColour = value; - leftBox.Colour = value; + LeftBox.Colour = value; } } @@ -67,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface set { backgroundColour = value; - rightBox.Colour = value; + RightBox.Colour = value; } } @@ -94,7 +96,7 @@ namespace osu.Game.Graphics.UserInterface CornerRadius = 5f, Children = new Drawable[] { - leftBox = new Box + LeftBox = new Box { Height = 5, EdgeSmoothness = new Vector2(0, 0.5f), @@ -102,14 +104,13 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, - rightBox = new Box + RightBox = new Box { Height = 5, EdgeSmoothness = new Vector2(0, 0.5f), RelativeSizeAxes = Axes.None, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Alpha = 0.5f, }, }, }, @@ -135,7 +136,7 @@ namespace osu.Game.Graphics.UserInterface { sample = audio.Samples.Get(@"UI/notch-tick"); AccentColour = colourProvider?.Highlight1 ?? colours.Pink; - BackgroundColour = colourProvider?.Background5 ?? colours.Pink.Opacity(0.5f); + BackgroundColour = colourProvider?.Background5 ?? colours.PinkDarker.Darken(1); } protected override void Update() @@ -163,6 +164,9 @@ namespace osu.Game.Graphics.UserInterface base.OnHoverLost(e); } + protected override bool ShouldHandleAsRelativeDrag(MouseDownEvent e) + => Nub.ReceivePositionalInputAt(e.ScreenSpaceMouseDownPosition); + protected override void OnDragEnd(DragEndEvent e) { updateGlow(); @@ -224,9 +228,9 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); - leftBox.Scale = new Vector2(Math.Clamp( + LeftBox.Scale = new Vector2(Math.Clamp( RangePadding + Nub.DrawPosition.X - Nub.DrawWidth / 2, 0, DrawWidth), 1); - rightBox.Scale = new Vector2(Math.Clamp( + RightBox.Scale = new Vector2(Math.Clamp( DrawWidth - Nub.DrawPosition.X - RangePadding - Nub.DrawWidth / 2, 0, DrawWidth), 1); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 3572ea5c31..3cfe401bb9 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osuTK; diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index c6121dcd17..6e6296c24b 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs index b7e25ae4e7..d9d9a21401 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 6db3068d84..1650d2b274 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs index d73d9f5824..b750abcd2b 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 5c6d087279..7c5d38b91b 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs index a2c6e8532b..adeae4fc8d 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs index 247a003492..7696087195 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPageButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs index 889917c397..a96cc892d4 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelectorPrevNextButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index a218c7bf52..13654fac85 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 0ebf2849fe..e5b0f0cbee 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/UserInterface/ProgressBar.cs b/osu.Game/Graphics/UserInterface/ProgressBar.cs index 50367e600e..774704223b 100644 --- a/osu.Game/Graphics/UserInterface/ProgressBar.cs +++ b/osu.Game/Graphics/UserInterface/ProgressBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index 16555075d1..2f8c8414e2 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 25f19aa0a9..e46e2b31ac 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index d7bd7d7e01..edd705ca00 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index cc0bc2dc46..2c2597f149 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs index 0b76ff658f..f64f455f6b 100644 --- a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Graphics.UserInterface { /// diff --git a/osu.Game/Graphics/UserInterface/SelectionState.cs b/osu.Game/Graphics/UserInterface/SelectionState.cs index c85b2ad3ab..edabf0547b 100644 --- a/osu.Game/Graphics/UserInterface/SelectionState.cs +++ b/osu.Game/Graphics/UserInterface/SelectionState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Graphics.UserInterface { public enum SelectionState diff --git a/osu.Game/Graphics/UserInterface/ShearedButton.cs b/osu.Game/Graphics/UserInterface/ShearedButton.cs index 66c6eedd0c..259c0646f3 100644 --- a/osu.Game/Graphics/UserInterface/ShearedButton.cs +++ b/osu.Game/Graphics/UserInterface/ShearedButton.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs b/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs index 452a1dd394..deb2374e88 100644 --- a/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs +++ b/osu.Game/Graphics/UserInterface/ShearedOverlayHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 0c34a04a65..d7e027b3f9 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs index ee59da7279..0bbcb2b976 100644 --- a/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs +++ b/osu.Game/Graphics/UserInterface/ShearedToggleButton.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - -using System; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -49,7 +46,7 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { - Active.BindDisabledChanged(disabled => Action = disabled ? (Action?)null : Active.Toggle, true); + Active.BindDisabledChanged(disabled => Action = disabled ? null : Active.Toggle, true); Active.BindValueChanged(_ => { updateActiveState(); diff --git a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs index 05dda324d4..ed64a31412 100644 --- a/osu.Game/Graphics/UserInterface/ShowMoreButton.cs +++ b/osu.Game/Graphics/UserInterface/ShowMoreButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs index c01ee1a059..534fcf76e5 100644 --- a/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index b66f371801..d9274bf2cb 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -66,7 +68,7 @@ namespace osu.Game.Graphics.UserInterface AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(star_spacing), - ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(i => CreateStar()) + ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(_ => CreateStar()) } }; } diff --git a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs index 0d7b36e51b..17266e876c 100644 --- a/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/StatefulMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/TernaryState.cs b/osu.Game/Graphics/UserInterface/TernaryState.cs index d4de28044f..effbe624c3 100644 --- a/osu.Game/Graphics/UserInterface/TernaryState.cs +++ b/osu.Game/Graphics/UserInterface/TernaryState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Graphics.UserInterface { /// diff --git a/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs b/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs index 5c623150b7..d2b6ff2dba 100644 --- a/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/TernaryStateMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/TernaryStateRadioMenuItem.cs b/osu.Game/Graphics/UserInterface/TernaryStateRadioMenuItem.cs index 46eda06294..133362d3e6 100644 --- a/osu.Game/Graphics/UserInterface/TernaryStateRadioMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/TernaryStateRadioMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/TernaryStateToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/TernaryStateToggleMenuItem.cs index ce951984fd..ec776f5cc4 100644 --- a/osu.Game/Graphics/UserInterface/TernaryStateToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/TernaryStateToggleMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/TimeSlider.cs b/osu.Game/Graphics/UserInterface/TimeSlider.cs index 82b02f1b48..d45c6614aa 100644 --- a/osu.Game/Graphics/UserInterface/TimeSlider.cs +++ b/osu.Game/Graphics/UserInterface/TimeSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs index f9ff9859dd..6787e17113 100644 --- a/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/ToggleMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; @@ -32,6 +34,6 @@ namespace osu.Game.Graphics.UserInterface { } - public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null; + public override IconUsage? GetIconForState(bool state) => state ? FontAwesome.Solid.Check : null; } } diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs index 5ae6130039..60d1824e5a 100644 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/TriangleButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 1f5d29571d..144b51d3e8 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs index cec319f28e..93852f19c4 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs index a966f61b74..001ccc7f87 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ColourPalette.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs index 8970ef1115..7b9684e3ef 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index dd6a902989..977ef5d7bc 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs index 2353d9e0e8..8c98a3e0a7 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs index 44f09f13eb..bfb009658d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs index b818c394ae..594f132154 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs index ca247ab679..cb032698ef 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs index cba94e314b..50b6834f01 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Game.Overlays.Settings; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index c374d80830..99a1a98d5b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Graphics.UserInterfaceV2 { public class LabelledSwitchButton : LabelledComponent diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs index 82b9fe559f..97bc845766 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs index 5394e5d0aa..f4ae2f0fd7 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs index 1ce4d97fdf..42e1073baf 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs index cb5ff242a1..0833c7eb8b 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorBreadcrumbDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs index 456bde6d1b..1896d7ee4d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorDirectory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs index 481d811adb..7d2b28e803 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs index d9dbf4974b..3e8b7dc209 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using osu.Framework.Allocation; @@ -8,7 +10,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -67,7 +68,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { get { - if (BeatmapModelManager.VIDEO_EXTENSIONS.Contains(File.Extension)) + if (OsuGameBase.VIDEO_EXTENSIONS.Contains(File.Extension)) return FontAwesome.Regular.FileVideo; switch (File.Extension) diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index 0189b30aad..1a8fa435cb 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs index 5368a800bc..12313791f0 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs index 085541b3ef..e468e14f45 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs index cb8c63371d..4477633da1 100644 --- a/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/RoundedButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs index f483e67b27..b5c1c0a854 100644 --- a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/IO/Archives/ArchiveReader.cs b/osu.Game/IO/Archives/ArchiveReader.cs index dab70eaf70..91165261b0 100644 --- a/osu.Game/IO/Archives/ArchiveReader.cs +++ b/osu.Game/IO/Archives/ArchiveReader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using System.Threading; diff --git a/osu.Game/IO/Archives/LegacyByteArrayReader.cs b/osu.Game/IO/Archives/LegacyByteArrayReader.cs index ea8ff3bbe0..e58dbb48ce 100644 --- a/osu.Game/IO/Archives/LegacyByteArrayReader.cs +++ b/osu.Game/IO/Archives/LegacyByteArrayReader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs index dfae58aed7..e26f6af081 100644 --- a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs +++ b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs index 72e5a21079..aee1add2f6 100644 --- a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs +++ b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index ae2b85da51..1fca8aa055 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Buffers; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs b/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs index f5709b5158..8e6c3e5f3d 100644 --- a/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs +++ b/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; diff --git a/osu.Game/IO/FileInfo.cs b/osu.Game/IO/FileInfo.cs index 148afba40d..3d32e7fb6d 100644 --- a/osu.Game/IO/FileInfo.cs +++ b/osu.Game/IO/FileInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Database; namespace osu.Game.IO diff --git a/osu.Game/IO/IFileInfo.cs b/osu.Game/IO/IFileInfo.cs index 080d8e57f5..932ea31e25 100644 --- a/osu.Game/IO/IFileInfo.cs +++ b/osu.Game/IO/IFileInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.IO { /// diff --git a/osu.Game/IO/IStorageResourceProvider.cs b/osu.Game/IO/IStorageResourceProvider.cs index b381ac70b0..1cb6509cac 100644 --- a/osu.Game/IO/IStorageResourceProvider.cs +++ b/osu.Game/IO/IStorageResourceProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Audio; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; diff --git a/osu.Game/IO/Legacy/ILegacySerializable.cs b/osu.Game/IO/Legacy/ILegacySerializable.cs index 0124ea756a..f21e67a34b 100644 --- a/osu.Game/IO/Legacy/ILegacySerializable.cs +++ b/osu.Game/IO/Legacy/ILegacySerializable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.IO.Legacy { public interface ILegacySerializable diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 5423485c95..2d3d5bffd5 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Legacy/SerializationWriter.cs b/osu.Game/IO/Legacy/SerializationWriter.cs index c9fff05bcc..10572a6478 100644 --- a/osu.Game/IO/Legacy/SerializationWriter.cs +++ b/osu.Game/IO/Legacy/SerializationWriter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/LineBufferedReader.cs b/osu.Game/IO/LineBufferedReader.cs index a6b8c9492a..da1cdba73b 100644 --- a/osu.Game/IO/LineBufferedReader.cs +++ b/osu.Game/IO/LineBufferedReader.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.IO; using System.Text; @@ -15,34 +14,31 @@ namespace osu.Game.IO public class LineBufferedReader : IDisposable { private readonly StreamReader streamReader; - private readonly Queue lineBuffer; + + private string? peekedLine; public LineBufferedReader(Stream stream, bool leaveOpen = false) { streamReader = new StreamReader(stream, Encoding.UTF8, true, 1024, leaveOpen); - lineBuffer = new Queue(); } /// /// Reads the next line from the stream without consuming it. /// Subsequent calls to without a will return the same string. /// - public string PeekLine() - { - if (lineBuffer.Count > 0) - return lineBuffer.Peek(); - - string line = streamReader.ReadLine(); - if (line != null) - lineBuffer.Enqueue(line); - return line; - } + public string? PeekLine() => peekedLine ??= streamReader.ReadLine(); /// /// Reads the next line from the stream and consumes it. /// If a line was peeked, that same line will then be consumed and returned. /// - public string ReadLine() => lineBuffer.Count > 0 ? lineBuffer.Dequeue() : streamReader.ReadLine(); + public string? ReadLine() + { + string? line = peekedLine ?? streamReader.ReadLine(); + + peekedLine = null; + return line; + } /// /// Reads the stream to its end and returns the text read. @@ -51,14 +47,13 @@ namespace osu.Game.IO public string ReadToEnd() { string remainingText = streamReader.ReadToEnd(); - if (lineBuffer.Count == 0) + if (peekedLine == null) return remainingText; var builder = new StringBuilder(); // this might not be completely correct due to varying platform line endings - while (lineBuffer.Count > 0) - builder.AppendLine(lineBuffer.Dequeue()); + builder.AppendLine(peekedLine); builder.Append(remainingText); return builder.ToString(); @@ -66,7 +61,7 @@ namespace osu.Game.IO public void Dispose() { - streamReader?.Dispose(); + streamReader.Dispose(); } } } diff --git a/osu.Game/IO/MigratableStorage.cs b/osu.Game/IO/MigratableStorage.cs index e478144294..30e74adca4 100644 --- a/osu.Game/IO/MigratableStorage.cs +++ b/osu.Game/IO/MigratableStorage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; diff --git a/osu.Game/IO/OsuStorage.cs b/osu.Game/IO/OsuStorage.cs index c49365a9de..368ac56850 100644 --- a/osu.Game/IO/OsuStorage.cs +++ b/osu.Game/IO/OsuStorage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using JetBrains.Annotations; @@ -92,6 +94,8 @@ namespace osu.Game.IO error = OsuStorageError.None; Storage lastStorage = UnderlyingStorage; + Logger.Log($"Attempting to use custom storage location {CustomStoragePath}"); + try { Storage userStorage = host.GetStorage(CustomStoragePath); @@ -100,6 +104,7 @@ namespace osu.Game.IO error = OsuStorageError.AccessibleButEmpty; ChangeTargetStorage(userStorage); + Logger.Log($"Storage successfully changed to {CustomStoragePath}."); } catch { @@ -107,6 +112,9 @@ namespace osu.Game.IO ChangeTargetStorage(lastStorage); } + if (error != OsuStorageError.None) + Logger.Log($"Custom storage location could not be used ({error})."); + return error == OsuStorageError.None; } diff --git a/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs b/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs index 1d82a5bc87..65283d0d82 100644 --- a/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs +++ b/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; diff --git a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs index 715c83b07e..176e4e240d 100644 --- a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs +++ b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/IO/Serialization/JsonSerializableExtensions.cs b/osu.Game/IO/Serialization/JsonSerializableExtensions.cs index 68b2110ede..bdf42205d4 100644 --- a/osu.Game/IO/Serialization/JsonSerializableExtensions.cs +++ b/osu.Game/IO/Serialization/JsonSerializableExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.IO.Serialization; diff --git a/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs b/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs index 68cb66d0dc..b51a8473ca 100644 --- a/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs +++ b/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Humanizer; +#nullable disable + using Newtonsoft.Json.Serialization; +using osu.Game.Extensions; namespace osu.Game.IO.Serialization { @@ -10,7 +12,7 @@ namespace osu.Game.IO.Serialization { protected override string ResolvePropertyName(string propertyName) { - return propertyName.Underscore(); + return propertyName.ToSnakeCase(); } } } diff --git a/osu.Game/IO/StableStorage.cs b/osu.Game/IO/StableStorage.cs index 84b7da91fc..41c7495b42 100644 --- a/osu.Game/IO/StableStorage.cs +++ b/osu.Game/IO/StableStorage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -14,7 +16,7 @@ namespace osu.Game.IO /// public class StableStorage : DesktopStorage { - private const string stable_default_songs_path = "Songs"; + public const string STABLE_DEFAULT_SONGS_PATH = "Songs"; private readonly DesktopGameHost host; private readonly Lazy songsPath; @@ -62,7 +64,7 @@ namespace osu.Game.IO } } - return GetFullPath(stable_default_songs_path); + return GetFullPath(STABLE_DEFAULT_SONGS_PATH); } } } diff --git a/osu.Game/IO/WrappedStorage.cs b/osu.Game/IO/WrappedStorage.cs index 7205ea3adb..95ff26db6a 100644 --- a/osu.Game/IO/WrappedStorage.cs +++ b/osu.Game/IO/WrappedStorage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IPC/ArchiveImportIPCChannel.cs b/osu.Game/IPC/ArchiveImportIPCChannel.cs index f381aad39a..02b1f72700 100644 --- a/osu.Game/IPC/ArchiveImportIPCChannel.cs +++ b/osu.Game/IPC/ArchiveImportIPCChannel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.IO; using System.Linq; diff --git a/osu.Game/IPC/IPCTimeoutException.cs b/osu.Game/IPC/IPCTimeoutException.cs new file mode 100644 index 0000000000..d820184468 --- /dev/null +++ b/osu.Game/IPC/IPCTimeoutException.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 System; + +namespace osu.Game.IPC +{ + public class IPCTimeoutException : TimeoutException + { + public IPCTimeoutException(Type channelType) + : base($@"IPC took too long to send message via channel {channelType}") + { + } + } +} diff --git a/osu.Game/IPC/OsuSchemeLinkIPCChannel.cs b/osu.Game/IPC/OsuSchemeLinkIPCChannel.cs new file mode 100644 index 0000000000..33318e329c --- /dev/null +++ b/osu.Game/IPC/OsuSchemeLinkIPCChannel.cs @@ -0,0 +1,49 @@ +// 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.Threading.Tasks; +using osu.Framework.Platform; +using osu.Game.Online; + +namespace osu.Game.IPC +{ + public class OsuSchemeLinkIPCChannel : IpcChannel + { + private readonly ILinkHandler? linkHandler; + + public OsuSchemeLinkIPCChannel(IIpcHost host, ILinkHandler? linkHandler = null) + : base(host) + { + this.linkHandler = linkHandler; + + MessageReceived += msg => + { + Debug.Assert(linkHandler != null); + linkHandler.HandleLink(msg.Link); + return null; + }; + } + + public async Task HandleLinkAsync(string url) + { + if (linkHandler == null) + { + await SendMessageAsync(new OsuSchemeLinkMessage(url)).ConfigureAwait(false); + return; + } + + linkHandler.HandleLink(url); + } + } + + public class OsuSchemeLinkMessage + { + public string Link { get; } + + public OsuSchemeLinkMessage(string link) + { + Link = link; + } + } +} diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index ba129b93e5..14a041b459 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -49,7 +51,7 @@ namespace osu.Game.Input.Bindings protected override void LoadComplete() { - realmSubscription = realm.RegisterForNotifications(queryRealmKeyBindings, (sender, changes, error) => + realmSubscription = realm.RegisterForNotifications(queryRealmKeyBindings, (sender, _, _) => { // The first fire of this is a bit redundant as this is being called in base.LoadComplete, // but this is safest in case the subscription is restored after a context recycle. diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 3da5f3212e..1ee03a6964 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -43,6 +45,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), new KeyBinding(InputKey.F10, GlobalAction.ToggleGameplayMouseButtons), new KeyBinding(InputKey.F12, GlobalAction.TakeScreenshot), + new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.F }, GlobalAction.ToggleFPSDisplay), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), @@ -326,5 +329,8 @@ namespace osu.Game.Input.Bindings [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorTapForBPM))] EditorTapForBPM, + + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ToggleFPSCounter))] + ToggleFPSDisplay, } } diff --git a/osu.Game/Input/Bindings/RealmKeyBinding.cs b/osu.Game/Input/Bindings/RealmKeyBinding.cs index c941319ddb..4af0357535 100644 --- a/osu.Game/Input/Bindings/RealmKeyBinding.cs +++ b/osu.Game/Input/Bindings/RealmKeyBinding.cs @@ -7,8 +7,6 @@ using osu.Framework.Input.Bindings; using osu.Game.Database; using Realms; -#nullable enable - namespace osu.Game.Input.Bindings { [MapTo(nameof(KeyBinding))] diff --git a/osu.Game/Input/ConfineMouseTracker.cs b/osu.Game/Input/ConfineMouseTracker.cs index d2bf953dbc..7e8ace5693 100644 --- a/osu.Game/Input/ConfineMouseTracker.cs +++ b/osu.Game/Input/ConfineMouseTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; diff --git a/osu.Game/Input/GameIdleTracker.cs b/osu.Game/Input/GameIdleTracker.cs index 260be7e5c9..d82cc25851 100644 --- a/osu.Game/Input/GameIdleTracker.cs +++ b/osu.Game/Input/GameIdleTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input; namespace osu.Game.Input diff --git a/osu.Game/Input/Handlers/ReplayInputHandler.cs b/osu.Game/Input/Handlers/ReplayInputHandler.cs index 205a1ea1ac..712e0acb60 100644 --- a/osu.Game/Input/Handlers/ReplayInputHandler.cs +++ b/osu.Game/Input/Handlers/ReplayInputHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index e2f13309cf..45036b3e41 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -78,11 +80,11 @@ namespace osu.Game.Input switch (e) { - case KeyDownEvent _: - case KeyUpEvent _: - case MouseDownEvent _: - case MouseUpEvent _: - case MouseMoveEvent _: + case KeyDownEvent: + case KeyUpEvent: + case MouseDownEvent: + case MouseUpEvent: + case MouseMoveEvent: return updateLastInteractionTime(); default: diff --git a/osu.Game/Input/OsuConfineMouseMode.cs b/osu.Game/Input/OsuConfineMouseMode.cs index a4a1c9eb46..2a93ac1cd6 100644 --- a/osu.Game/Input/OsuConfineMouseMode.cs +++ b/osu.Game/Input/OsuConfineMouseMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Input; diff --git a/osu.Game/Input/OsuUserInputManager.cs b/osu.Game/Input/OsuUserInputManager.cs index 621f1e1fc9..7a9002a004 100644 --- a/osu.Game/Input/OsuUserInputManager.cs +++ b/osu.Game/Input/OsuUserInputManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input; using osuTK.Input; diff --git a/osu.Game/Input/RealmKeyBindingStore.cs b/osu.Game/Input/RealmKeyBindingStore.cs index 20971ffca5..10ad731037 100644 --- a/osu.Game/Input/RealmKeyBindingStore.cs +++ b/osu.Game/Input/RealmKeyBindingStore.cs @@ -10,8 +10,6 @@ using osu.Game.Input.Bindings; using osu.Game.Rulesets; using Realms; -#nullable enable - namespace osu.Game.Input { public class RealmKeyBindingStore diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 1fd677034d..1ee562e122 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -91,4 +91,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/DifficultyMultiplierDisplayStrings.cs b/osu.Game/Localisation/DifficultyMultiplierDisplayStrings.cs index c281d90190..952ca22678 100644 --- a/osu.Game/Localisation/DifficultyMultiplierDisplayStrings.cs +++ b/osu.Game/Localisation/DifficultyMultiplierDisplayStrings.cs @@ -16,4 +16,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs index 82d03dbb5b..de1a5b189c 100644 --- a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs +++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs @@ -274,6 +274,11 @@ namespace osu.Game.Localisation /// public static LocalisableString ToggleSkinEditor => new TranslatableString(getKey(@"toggle_skin_editor"), @"Toggle skin editor"); + /// + /// "Toggle FPS counter" + /// + public static LocalisableString ToggleFPSCounter => new TranslatableString(getKey(@"toggle_fps_counter"), @"Toggle FPS counter"); + /// /// "Previous volume meter" /// diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 1c9aa64df5..38355d9041 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -34,11 +34,6 @@ namespace osu.Game.Localisation /// public static LocalisableString ShowFPS => new TranslatableString(getKey(@"show_fps"), @"Show FPS"); - /// - /// "Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. "2x refresh rate" is recommended." - /// - public static LocalisableString UnlimitedFramesNote => new TranslatableString(getKey(@"unlimited_frames_note"), @"Using unlimited frame limiter can lead to stutters, bad performance and overheating. It will not improve perceived latency. ""2x refresh rate"" is recommended."); - /// /// "Layout" /// diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index c13a1a10cb..6a4e5110e6 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System.ComponentModel; +using JetBrains.Annotations; namespace osu.Game.Localisation { + [UsedImplicitly(ImplicitUseTargetFlags.WithMembers)] public enum Language { [Description(@"English")] diff --git a/osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs b/osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs index 111c068bbd..92cedce3e0 100644 --- a/osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs +++ b/osu.Game/Localisation/MultiplayerTeamResultsScreenStrings.cs @@ -21,4 +21,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs index 0fb85e4a19..d2ff783413 100644 --- a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs +++ b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Globalization; diff --git a/osu.Game/Localisation/TabletSettingsStrings.cs b/osu.Game/Localisation/TabletSettingsStrings.cs index 5bdca09e4a..d62d348df9 100644 --- a/osu.Game/Localisation/TabletSettingsStrings.cs +++ b/osu.Game/Localisation/TabletSettingsStrings.cs @@ -56,4 +56,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} diff --git a/osu.Game/Localisation/ToastStrings.cs b/osu.Game/Localisation/ToastStrings.cs index 52e75425bf..9ceee807e6 100644 --- a/osu.Game/Localisation/ToastStrings.cs +++ b/osu.Game/Localisation/ToastStrings.cs @@ -34,6 +34,16 @@ namespace osu.Game.Localisation /// public static LocalisableString RestartTrack => new TranslatableString(getKey(@"restart_track"), @"Restart track"); + /// + /// "Beatmap saved" + /// + public static LocalisableString BeatmapSaved => new TranslatableString(getKey(@"beatmap_saved"), @"Beatmap saved"); + + /// + /// "Skin saved" + /// + public static LocalisableString SkinSaved => new TranslatableString(getKey(@"skin_saved"), @"Skin saved"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Localisation/UserInterfaceStrings.cs b/osu.Game/Localisation/UserInterfaceStrings.cs index 4be403edb4..a090b8c14c 100644 --- a/osu.Game/Localisation/UserInterfaceStrings.cs +++ b/osu.Game/Localisation/UserInterfaceStrings.cs @@ -104,6 +104,11 @@ namespace osu.Game.Localisation /// public static LocalisableString RandomSelectionAlgorithm => new TranslatableString(getKey(@"random_selection_algorithm"), @"Random selection algorithm"); + /// + /// "Mod select hotkey style" + /// + public static LocalisableString ModSelectHotkeyStyle => new TranslatableString(getKey(@"mod_select_hotkey_style"), @"Mod select hotkey style"); + /// /// "no limit" /// diff --git a/osu.Game/Models/RealmFile.cs b/osu.Game/Models/RealmFile.cs index 9e8da7cdc4..f96b717937 100644 --- a/osu.Game/Models/RealmFile.cs +++ b/osu.Game/Models/RealmFile.cs @@ -5,8 +5,6 @@ using osu.Framework.Testing; using osu.Game.IO; using Realms; -#nullable enable - namespace osu.Game.Models { [ExcludeFromDynamicCompile] diff --git a/osu.Game/Models/RealmNamedFileUsage.cs b/osu.Game/Models/RealmNamedFileUsage.cs index 17e32510a8..c4310c4edb 100644 --- a/osu.Game/Models/RealmNamedFileUsage.cs +++ b/osu.Game/Models/RealmNamedFileUsage.cs @@ -1,14 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using JetBrains.Annotations; using osu.Framework.Testing; using osu.Game.Database; using osu.Game.IO; using Realms; -#nullable enable - namespace osu.Game.Models { [ExcludeFromDynamicCompile] @@ -21,8 +20,8 @@ namespace osu.Game.Models public RealmNamedFileUsage(RealmFile file, string filename) { - File = file; - Filename = filename; + File = file ?? throw new ArgumentNullException(nameof(file)); + Filename = filename ?? throw new ArgumentNullException(nameof(filename)); } [UsedImplicitly] diff --git a/osu.Game/Models/RealmUser.cs b/osu.Game/Models/RealmUser.cs index 18c849cf0a..e20ffc0808 100644 --- a/osu.Game/Models/RealmUser.cs +++ b/osu.Game/Models/RealmUser.cs @@ -15,6 +15,16 @@ namespace osu.Game.Models public string Username { get; set; } = string.Empty; + [Ignored] + public CountryCode CountryCode + { + get => Enum.TryParse(CountryString, out CountryCode country) ? country : CountryCode.Unknown; + set => CountryString = value.ToString(); + } + + [MapTo(nameof(CountryCode))] + public string CountryString { get; set; } = default(CountryCode).ToString(); + public bool IsBot => false; public bool Equals(RealmUser other) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 62ddd49881..7af19f6dd1 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -36,7 +38,7 @@ namespace osu.Game.Online.API public string WebsiteRootUrl { get; } - public int APIVersion => 20220217; // We may want to pull this from the game version eventually. + public int APIVersion => 20220705; // We may want to pull this from the game version eventually. public Exception LastLoginError { get; private set; } @@ -161,7 +163,13 @@ namespace osu.Game.Online.API userReq.Failure += ex => { - if (ex is WebException webException && webException.Message == @"Unauthorized") + if (ex is APIException) + { + LastLoginError = ex; + log.Add("Login failed on local user retrieval!"); + Logout(); + } + else if (ex is WebException webException && webException.Message == @"Unauthorized") { log.Add(@"Login no longer valid"); Logout(); diff --git a/osu.Game/Online/API/APIDownloadRequest.cs b/osu.Game/Online/API/APIDownloadRequest.cs index 11753e05ba..c48372278a 100644 --- a/osu.Game/Online/API/APIDownloadRequest.cs +++ b/osu.Game/Online/API/APIDownloadRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/APIException.cs b/osu.Game/Online/API/APIException.cs index 54d68d8f0d..21a9c761c7 100644 --- a/osu.Game/Online/API/APIException.cs +++ b/osu.Game/Online/API/APIException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/APIMessagesRequest.cs b/osu.Game/Online/API/APIMessagesRequest.cs index 3ad6b1d7c8..5bb3e29621 100644 --- a/osu.Game/Online/API/APIMessagesRequest.cs +++ b/osu.Game/Online/API/APIMessagesRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/APIMod.cs b/osu.Game/Online/API/APIMod.cs index 524f7b7108..900f59290c 100644 --- a/osu.Game/Online/API/APIMod.cs +++ b/osu.Game/Online/API/APIMod.cs @@ -1,15 +1,18 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; -using Humanizer; using MessagePack; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -42,11 +45,11 @@ namespace osu.Game.Online.API var bindable = (IBindable)property.GetValue(mod); if (!bindable.IsDefault) - Settings.Add(property.Name.Underscore(), bindable.GetUnderlyingSettingValue()); + Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue()); } } - public Mod ToMod(Ruleset ruleset) + public Mod ToMod([NotNull] Ruleset ruleset) { Mod resultMod = ruleset.CreateModFromAcronym(Acronym); @@ -60,10 +63,17 @@ namespace osu.Game.Online.API { foreach (var (_, property) in resultMod.GetSettingsSourceProperties()) { - if (!Settings.TryGetValue(property.Name.Underscore(), out object settingValue)) + if (!Settings.TryGetValue(property.Name.ToSnakeCase(), out object settingValue)) continue; - resultMod.CopyAdjustedSetting((IBindable)property.GetValue(resultMod), settingValue); + try + { + resultMod.CopyAdjustedSetting((IBindable)property.GetValue(resultMod), settingValue); + } + catch (Exception ex) + { + Logger.Log($"Failed to copy mod setting value '{settingValue ?? "null"}' to \"{property.Name}\": {ex.Message}"); + } } } diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 451ea117d5..dc6a3fe3d5 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using JetBrains.Annotations; diff --git a/osu.Game/Online/API/APIRequestCompletionState.cs b/osu.Game/Online/API/APIRequestCompletionState.cs index 84c9974dd8..52eb669a7d 100644 --- a/osu.Game/Online/API/APIRequestCompletionState.cs +++ b/osu.Game/Online/API/APIRequestCompletionState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.API { public enum APIRequestCompletionState diff --git a/osu.Game/Online/API/ArchiveDownloadRequest.cs b/osu.Game/Online/API/ArchiveDownloadRequest.cs index 0bf238109e..ff96b39e08 100644 --- a/osu.Game/Online/API/ArchiveDownloadRequest.cs +++ b/osu.Game/Online/API/ArchiveDownloadRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index d3707d977c..07d544260e 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using System.Threading.Tasks; @@ -13,10 +15,12 @@ namespace osu.Game.Online.API { public class DummyAPIAccess : Component, IAPIProvider { + public const int DUMMY_USER_ID = 1001; + public Bindable LocalUser { get; } = new Bindable(new APIUser { Username = @"Dummy", - Id = 1001, + Id = DUMMY_USER_ID, }); public BindableList Friends { get; } = new BindableList(); diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 470d46cd7f..812aa7f09f 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Threading.Tasks; using osu.Framework.Bindables; diff --git a/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs b/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs index a7c63c17f9..df64984c7a 100644 --- a/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs +++ b/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Buffers; using System.Collections.Generic; using System.Text; diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 1feb3076d1..58306c1938 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Net.Http; diff --git a/osu.Game/Online/API/OAuthToken.cs b/osu.Game/Online/API/OAuthToken.cs index f103d0917d..63c88b875b 100644 --- a/osu.Game/Online/API/OAuthToken.cs +++ b/osu.Game/Online/API/OAuthToken.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/OsuJsonWebRequest.cs b/osu.Game/Online/API/OsuJsonWebRequest.cs index 4a45a8b261..2d402edd3f 100644 --- a/osu.Game/Online/API/OsuJsonWebRequest.cs +++ b/osu.Game/Online/API/OsuJsonWebRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/OsuWebRequest.cs b/osu.Game/Online/API/OsuWebRequest.cs index 1d27899473..9a7cf45a2f 100644 --- a/osu.Game/Online/API/OsuWebRequest.cs +++ b/osu.Game/Online/API/OsuWebRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/RegistrationRequest.cs b/osu.Game/Online/API/RegistrationRequest.cs index f650e5c93b..6dc867481a 100644 --- a/osu.Game/Online/API/RegistrationRequest.cs +++ b/osu.Game/Online/API/RegistrationRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/Requests/CommentVoteRequest.cs b/osu.Game/Online/API/Requests/CommentVoteRequest.cs index 06a3b1126e..a835b0365c 100644 --- a/osu.Game/Online/API/Requests/CommentVoteRequest.cs +++ b/osu.Game/Online/API/Requests/CommentVoteRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; using System.Net.Http; diff --git a/osu.Game/Online/API/Requests/CreateChannelRequest.cs b/osu.Game/Online/API/Requests/CreateChannelRequest.cs index 041ad26267..130210b1c3 100644 --- a/osu.Game/Online/API/Requests/CreateChannelRequest.cs +++ b/osu.Game/Online/API/Requests/CreateChannelRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs b/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs index e5761149e7..dea94bfce2 100644 --- a/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs +++ b/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs b/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs index f749b27114..1af61770df 100644 --- a/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs +++ b/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/Cursor.cs b/osu.Game/Online/API/Requests/Cursor.cs index 3de8db770c..c7bb119bd8 100644 --- a/osu.Game/Online/API/Requests/Cursor.cs +++ b/osu.Game/Online/API/Requests/Cursor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index 5254dc3cf8..f190b6e821 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/DownloadReplayRequest.cs b/osu.Game/Online/API/Requests/DownloadReplayRequest.cs index 77174f0bb5..5635c4728e 100644 --- a/osu.Game/Online/API/Requests/DownloadReplayRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadReplayRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Scoring; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index 671f543422..efecc0fc25 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -5,8 +5,6 @@ using osu.Framework.IO.Network; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; -#nullable enable - namespace osu.Game.Online.API.Requests { public class GetBeatmapRequest : APIRequest diff --git a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs index 158ae03b8d..f3690c934d 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs index 22af022659..e118d1bddc 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/GetBeatmapsResponse.cs b/osu.Game/Online/API/Requests/GetBeatmapsResponse.cs index c450c3269c..c91aa5002c 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapsResponse.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapsResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index baa15c70c4..2d2d241b86 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 97799ff66a..82ed42615f 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs index 24dae4adf1..1aa08f2ed8 100644 --- a/osu.Game/Online/API/Requests/GetCommentsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; -using Humanizer; +using osu.Game.Extensions; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Comments; @@ -30,7 +32,7 @@ namespace osu.Game.Online.API.Requests var req = base.CreateWebRequest(); req.AddParameter("commentable_id", commentableId.ToString()); - req.AddParameter("commentable_type", type.ToString().Underscore().ToLowerInvariant()); + req.AddParameter("commentable_type", type.ToString().ToSnakeCase().ToLowerInvariant()); req.AddParameter("page", page.ToString()); req.AddParameter("sort", sort.ToString().ToLowerInvariant()); diff --git a/osu.Game/Online/API/Requests/GetCountriesResponse.cs b/osu.Game/Online/API/Requests/GetCountriesResponse.cs index 6624344b44..117993b98c 100644 --- a/osu.Game/Online/API/Requests/GetCountriesResponse.cs +++ b/osu.Game/Online/API/Requests/GetCountriesResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs index d8a1198627..9d037ab116 100644 --- a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetFriendsRequest.cs b/osu.Game/Online/API/Requests/GetFriendsRequest.cs index 63a221d91a..640ddcbb9e 100644 --- a/osu.Game/Online/API/Requests/GetFriendsRequest.cs +++ b/osu.Game/Online/API/Requests/GetFriendsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetMessagesRequest.cs b/osu.Game/Online/API/Requests/GetMessagesRequest.cs index 651f8a06c5..2f9879c63f 100644 --- a/osu.Game/Online/API/Requests/GetMessagesRequest.cs +++ b/osu.Game/Online/API/Requests/GetMessagesRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/GetNewsRequest.cs b/osu.Game/Online/API/Requests/GetNewsRequest.cs index 992ccc6d59..64bed344bb 100644 --- a/osu.Game/Online/API/Requests/GetNewsRequest.cs +++ b/osu.Game/Online/API/Requests/GetNewsRequest.cs @@ -9,9 +9,9 @@ namespace osu.Game.Online.API.Requests public class GetNewsRequest : APIRequest { private readonly int? year; - private readonly Cursor cursor; + private readonly Cursor? cursor; - public GetNewsRequest(int? year = null, Cursor cursor = null) + public GetNewsRequest(int? year = null, Cursor? cursor = null) { this.year = year; this.cursor = cursor; @@ -20,7 +20,9 @@ namespace osu.Game.Online.API.Requests protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - req.AddCursor(cursor); + + if (cursor != null) + req.AddCursor(cursor); if (year.HasValue) req.AddParameter("year", year.Value.ToString()); diff --git a/osu.Game/Online/API/Requests/GetNewsResponse.cs b/osu.Game/Online/API/Requests/GetNewsResponse.cs index 98f76d105c..b62d83557e 100644 --- a/osu.Game/Online/API/Requests/GetNewsResponse.cs +++ b/osu.Game/Online/API/Requests/GetNewsResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetRankingsRequest.cs b/osu.Game/Online/API/Requests/GetRankingsRequest.cs index ddc3298ca7..f42da69dcc 100644 --- a/osu.Game/Online/API/Requests/GetRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetRankingsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; using osu.Game.Rulesets; diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 8e447390e6..966e69938c 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -33,7 +35,7 @@ namespace osu.Game.Online.API.Requests this.mods = mods ?? Array.Empty(); } - protected override string Target => $@"beatmaps/{beatmapInfo.OnlineID}/scores{createQueryParameters()}"; + protected override string Target => $@"beatmaps/{beatmapInfo.OnlineID}/solo-scores{createQueryParameters()}"; private string createQueryParameters() { diff --git a/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs b/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs index 941b47244a..0ecce90749 100644 --- a/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs index 20856c2768..2d8a8b3b61 100644 --- a/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; using osu.Game.Overlays.Rankings; using osu.Game.Rulesets; @@ -24,7 +26,7 @@ namespace osu.Game.Online.API.Requests var req = base.CreateWebRequest(); req.AddParameter("spotlight", spotlight.ToString()); - req.AddParameter("filter", sort.ToString().ToLower()); + req.AddParameter("filter", sort.ToString().ToLowerInvariant()); return req; } diff --git a/osu.Game/Online/API/Requests/GetSpotlightRankingsResponse.cs b/osu.Game/Online/API/Requests/GetSpotlightRankingsResponse.cs index 2259314a9f..5bc7bd5e08 100644 --- a/osu.Game/Online/API/Requests/GetSpotlightRankingsResponse.cs +++ b/osu.Game/Online/API/Requests/GetSpotlightRankingsResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs index 6fafb3933c..93a63afcaa 100644 --- a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetTopUsersRequest.cs b/osu.Game/Online/API/Requests/GetTopUsersRequest.cs index dbbd2119db..7f05cd5eab 100644 --- a/osu.Game/Online/API/Requests/GetTopUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetTopUsersRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.API.Requests { public class GetTopUsersRequest : APIRequest diff --git a/osu.Game/Online/API/Requests/GetTopUsersResponse.cs b/osu.Game/Online/API/Requests/GetTopUsersResponse.cs index b37b8b3499..6e0e8f11ae 100644 --- a/osu.Game/Online/API/Requests/GetTopUsersResponse.cs +++ b/osu.Game/Online/API/Requests/GetTopUsersResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/GetUpdatesRequest.cs b/osu.Game/Online/API/Requests/GetUpdatesRequest.cs index 488bb8bbf4..ce2689d262 100644 --- a/osu.Game/Online/API/Requests/GetUpdatesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUpdatesRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/GetUpdatesResponse.cs b/osu.Game/Online/API/Requests/GetUpdatesResponse.cs index 4ac806bedc..61f6a8664d 100644 --- a/osu.Game/Online/API/Requests/GetUpdatesResponse.cs +++ b/osu.Game/Online/API/Requests/GetUpdatesResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index 205fdc9f2b..d723786f23 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using Humanizer; +#nullable disable + using System.Collections.Generic; +using osu.Game.Extensions; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests @@ -20,7 +22,7 @@ namespace osu.Game.Online.API.Requests this.type = type; } - protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}"; + protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().ToSnakeCase()}"; } public enum BeatmapSetType diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index 67d3ad26b0..3d0ee23080 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index bef3df42fb..e5e65415f7 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs index bccc3bc0c3..c27a83b695 100644 --- a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; using osu.Game.Rulesets; +using osu.Game.Users; namespace osu.Game.Online.API.Requests { @@ -10,21 +13,21 @@ namespace osu.Game.Online.API.Requests { public readonly UserRankingsType Type; - private readonly string country; + private readonly CountryCode countryCode; - public GetUserRankingsRequest(RulesetInfo ruleset, UserRankingsType type = UserRankingsType.Performance, int page = 1, string country = null) + public GetUserRankingsRequest(RulesetInfo ruleset, UserRankingsType type = UserRankingsType.Performance, int page = 1, CountryCode countryCode = CountryCode.Unknown) : base(ruleset, page) { Type = type; - this.country = country; + this.countryCode = countryCode; } protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - if (country != null) - req.AddParameter("country", country); + if (countryCode != CountryCode.Unknown) + req.AddParameter("country", countryCode.ToString()); return req; } diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index 79f0549d4a..82cf0a508a 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 28da5222f9..7dcf75950e 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; @@ -43,7 +45,7 @@ namespace osu.Game.Online.API.Requests Ruleset = ruleset; } - protected override string Target => Lookup != null ? $@"users/{Lookup}/{Ruleset?.ShortName}?key={lookupType.ToString().ToLower()}" : $@"me/{Ruleset?.ShortName}"; + protected override string Target => Lookup != null ? $@"users/{Lookup}/{Ruleset?.ShortName}?key={lookupType.ToString().ToLowerInvariant()}" : $@"me/{Ruleset?.ShortName}"; private enum LookupType { diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 7250929f11..8ef797f799 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; @@ -8,7 +10,7 @@ using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests { - public class GetUserScoresRequest : PaginatedAPIRequest> + public class GetUserScoresRequest : PaginatedAPIRequest> { private readonly long userId; private readonly ScoreType type; diff --git a/osu.Game/Online/API/Requests/GetUsersRequest.cs b/osu.Game/Online/API/Requests/GetUsersRequest.cs index 969d7fdba3..bbaf241384 100644 --- a/osu.Game/Online/API/Requests/GetUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetUsersRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetUsersResponse.cs b/osu.Game/Online/API/Requests/GetUsersResponse.cs index 022050de5c..b49bef589a 100644 --- a/osu.Game/Online/API/Requests/GetUsersResponse.cs +++ b/osu.Game/Online/API/Requests/GetUsersResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetWikiRequest.cs b/osu.Game/Online/API/Requests/GetWikiRequest.cs index 09571ab0a8..7c84e1f790 100644 --- a/osu.Game/Online/API/Requests/GetWikiRequest.cs +++ b/osu.Game/Online/API/Requests/GetWikiRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Extensions; using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; @@ -9,15 +11,16 @@ namespace osu.Game.Online.API.Requests { public class GetWikiRequest : APIRequest { - private readonly string path; + public readonly string Path; + private readonly Language language; public GetWikiRequest(string path, Language language = Language.en) { - this.path = path; + Path = path; this.language = language; } - protected override string Target => $"wiki/{language.ToCultureCode()}/{path}"; + protected override string Target => $"wiki/{language.ToCultureCode()}/{Path}"; } } diff --git a/osu.Game/Online/API/Requests/JoinChannelRequest.cs b/osu.Game/Online/API/Requests/JoinChannelRequest.cs index 33eab7e355..30b8fafd57 100644 --- a/osu.Game/Online/API/Requests/JoinChannelRequest.cs +++ b/osu.Game/Online/API/Requests/JoinChannelRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/LeaveChannelRequest.cs b/osu.Game/Online/API/Requests/LeaveChannelRequest.cs index 7dfc9a0aed..4e77055e67 100644 --- a/osu.Game/Online/API/Requests/LeaveChannelRequest.cs +++ b/osu.Game/Online/API/Requests/LeaveChannelRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/ListChannelsRequest.cs b/osu.Game/Online/API/Requests/ListChannelsRequest.cs index 9660695c14..6f8fb427dc 100644 --- a/osu.Game/Online/API/Requests/ListChannelsRequest.cs +++ b/osu.Game/Online/API/Requests/ListChannelsRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index b24669e6d5..afdc8a47f4 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs index 3d719de958..4af1f58180 100644 --- a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs +++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Globalization; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/PaginationParameters.cs b/osu.Game/Online/API/Requests/PaginationParameters.cs index 3593a4fe83..6dacb009bd 100644 --- a/osu.Game/Online/API/Requests/PaginationParameters.cs +++ b/osu.Game/Online/API/Requests/PaginationParameters.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.API.Requests { /// diff --git a/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs index 9fdc3382aa..1438c9c436 100644 --- a/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs +++ b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.IO.Network; using System.Net.Http; diff --git a/osu.Game/Online/API/Requests/PostMessageRequest.cs b/osu.Game/Online/API/Requests/PostMessageRequest.cs index 5d508a4cdf..7b20bd9ad5 100644 --- a/osu.Game/Online/API/Requests/PostMessageRequest.cs +++ b/osu.Game/Online/API/Requests/PostMessageRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/ResponseWithCursor.cs b/osu.Game/Online/API/Requests/ResponseWithCursor.cs index d52e999722..66e8094442 100644 --- a/osu.Game/Online/API/Requests/ResponseWithCursor.cs +++ b/osu.Game/Online/API/Requests/ResponseWithCursor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index f5795141c5..3fee81cf33 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -7,8 +7,6 @@ using osu.Game.Beatmaps; using osu.Game.Extensions; using osu.Game.Rulesets; -#nullable enable - namespace osu.Game.Online.API.Requests.Responses { public class APIBeatmap : IBeatmapInfo, IBeatmapOnlineInfo @@ -71,6 +69,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"count_sliders")] public int SliderCount { get; set; } + [JsonProperty(@"count_spinners")] + public int SpinnerCount { get; set; } + [JsonProperty(@"version")] public string DifficultyName { get; set; } = string.Empty; @@ -80,6 +81,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"max_combo")] public int? MaxCombo { get; set; } + [JsonProperty(@"last_updated")] + public DateTimeOffset LastUpdated { get; set; } + public double BPM { get; set; } #region Implementation of IBeatmapInfo diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 79c65fa79e..238f41e53d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -9,8 +9,6 @@ using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Models; -#nullable enable - namespace osu.Game.Online.API.Requests.Responses { public class APIBeatmapSet : IBeatmapSetOnlineInfo, IBeatmapSetInfo diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs index 56005e15f8..38c727396a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using System; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs index 1ff7523ba6..2355de8f3c 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogEntry.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs index 778e8754fe..0728fc1c7e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogIndex.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs b/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs index 024e1ce048..071f9f8517 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChangelogUser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses diff --git a/osu.Game/Online/API/Requests/Responses/APIChatChannel.cs b/osu.Game/Online/API/Requests/Responses/APIChatChannel.cs index fc3b2a8e31..a04dc89986 100644 --- a/osu.Game/Online/API/Requests/Responses/APIChatChannel.cs +++ b/osu.Game/Online/API/Requests/Responses/APIChatChannel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs index d596ddc560..583def8eda 100644 --- a/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIKudosuHistory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APINewsPost.cs b/osu.Game/Online/API/Requests/Responses/APINewsPost.cs index ced08f0bf2..ff12a83af2 100644 --- a/osu.Game/Online/API/Requests/Responses/APINewsPost.cs +++ b/osu.Game/Online/API/Requests/Responses/APINewsPost.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using System; using System.Net; diff --git a/osu.Game/Online/API/Requests/Responses/APINewsSidebar.cs b/osu.Game/Online/API/Requests/Responses/APINewsSidebar.cs index b8d6469a1d..a94dfbd923 100644 --- a/osu.Game/Online/API/Requests/Responses/APINewsSidebar.cs +++ b/osu.Game/Online/API/Requests/Responses/APINewsSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs b/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs index a9d66f3d6a..4a877f392a 100644 --- a/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs +++ b/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Online/API/Requests/Responses/APIRankHistory.cs b/osu.Game/Online/API/Requests/Responses/APIRankHistory.cs index 064badcccb..b3af2e1a3e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRankHistory.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRankHistory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index 8695d09570..2def18926f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; -using Humanizer; using Newtonsoft.Json; +using osu.Game.Extensions; using osu.Game.Scoring; namespace osu.Game.Online.API.Requests.Responses @@ -19,7 +21,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty] private string type { - set => Type = (RecentActivityType)Enum.Parse(typeof(RecentActivityType), value.Pascalize()); + set => Type = (RecentActivityType)Enum.Parse(typeof(RecentActivityType), value.ToPascalCase()); } public RecentActivityType Type; diff --git a/osu.Game/Online/API/Requests/Responses/APIScore.cs b/osu.Game/Online/API/Requests/Responses/APIScore.cs index d8f4ba835d..f236607761 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScore.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -86,7 +88,7 @@ namespace osu.Game.Online.API.Requests.Responses /// public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null) { - var ruleset = rulesets.GetRuleset(RulesetID) ?? throw new InvalidOperationException(); + var ruleset = rulesets.GetRuleset(RulesetID) ?? throw new InvalidOperationException($"Ruleset with ID of {RulesetID} not found locally"); var rulesetInstance = ruleset.CreateInstance(); diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs index d3c9ba0c7e..494826f534 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -14,11 +16,11 @@ namespace osu.Game.Online.API.Requests.Responses public int? Position; [JsonProperty(@"score")] - public APIScore Score; + public SoloScoreInfo Score; public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null) { - var score = Score.CreateScoreInfo(rulesets, beatmap); + var score = Score.ToScoreInfo(rulesets, beatmap); score.Position = Position; return score; } diff --git a/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs b/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs index 283ebf2411..4ef39be5e5 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; @@ -9,9 +11,9 @@ namespace osu.Game.Online.API.Requests.Responses public class APIScoresCollection { [JsonProperty(@"scores")] - public List Scores; + public List Scores; - [JsonProperty(@"userScore")] + [JsonProperty(@"user_score")] public APIScoreWithPosition UserScore; } } diff --git a/osu.Game/Online/API/Requests/Responses/APISeasonalBackgrounds.cs b/osu.Game/Online/API/Requests/Responses/APISeasonalBackgrounds.cs index 8e395f7397..c70dcc0e0b 100644 --- a/osu.Game/Online/API/Requests/Responses/APISeasonalBackgrounds.cs +++ b/osu.Game/Online/API/Requests/Responses/APISeasonalBackgrounds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs index 4f63ebe3df..6eb51a0fb3 100644 --- a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs +++ b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs index 5af7d6a01c..76d1941d9d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUpdateStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; 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 41f486c709..5f843e9a7b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -32,8 +34,19 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"previous_usernames")] public string[] PreviousUsernames; + private CountryCode? countryCode; + + public CountryCode CountryCode + { + get => countryCode ??= (Enum.TryParse(country?.Code, out CountryCode result) ? result : default); + set => countryCode = value; + } + +#pragma warning disable 649 + [CanBeNull] [JsonProperty(@"country")] - public Country Country; + private Country country; +#pragma warning restore 649 public readonly Bindable Status = new Bindable(); @@ -254,5 +267,13 @@ namespace osu.Game.Online.API.Requests.Responses public int OnlineID => Id; public bool Equals(APIUser other) => this.MatchesOnlineID(other); + +#pragma warning disable 649 + private class Country + { + [JsonProperty(@"code")] + public string Code; + } +#pragma warning restore 649 } } diff --git a/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs b/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs index cfba9118c2..65001dd6cf 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIUserContainer.cs b/osu.Game/Online/API/Requests/Responses/APIUserContainer.cs index 9eb4a2a4e3..b2d544c71f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserContainer.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses diff --git a/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs b/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs index 1226c88c08..6eb3c8b8a4 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs index 19c581bf95..6d5fd59f9c 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.API.Requests.Responses diff --git a/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs b/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs index a298a8625a..30433ab8cd 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserScoreAggregate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs b/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs index 957396b17a..ea2457bf1b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs +++ b/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 13379a40a6..500c0566e6 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using System; diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index 8436381090..ae8b850723 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs new file mode 100644 index 0000000000..bfc8b4102a --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs @@ -0,0 +1,156 @@ +// Copyright (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 Newtonsoft.Json.Converters; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; + +namespace osu.Game.Online.API.Requests.Responses +{ + [Serializable] + public class SoloScoreInfo : IHasOnlineID + { + [JsonProperty("replay")] + public bool HasReplay { get; set; } + + [JsonProperty("beatmap_id")] + public int BeatmapID { get; set; } + + [JsonProperty("ruleset_id")] + public int RulesetID { get; set; } + + [JsonProperty("build_id")] + public int? BuildID { get; set; } + + [JsonProperty("passed")] + public bool Passed { get; set; } + + [JsonProperty("total_score")] + public int TotalScore { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty("user_id")] + public int UserID { get; set; } + + // TODO: probably want to update this column to match user stats (short)? + [JsonProperty("max_combo")] + public int MaxCombo { get; set; } + + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty("rank")] + public ScoreRank Rank { get; set; } + + [JsonProperty("started_at")] + public DateTimeOffset? StartedAt { get; set; } + + [JsonProperty("ended_at")] + public DateTimeOffset EndedAt { get; set; } + + [JsonProperty("mods")] + public APIMod[] Mods { get; set; } = Array.Empty(); + + [JsonIgnore] + [JsonProperty("created_at")] + public DateTimeOffset CreatedAt { get; set; } + + [JsonIgnore] + [JsonProperty("updated_at")] + public DateTimeOffset UpdatedAt { get; set; } + + [JsonIgnore] + [JsonProperty("deleted_at")] + public DateTimeOffset? DeletedAt { get; set; } + + [JsonProperty("statistics")] + public Dictionary Statistics { get; set; } = new Dictionary(); + + #region osu-web API additions (not stored to database). + + [JsonProperty("id")] + public long? ID { get; set; } + + [JsonProperty("user")] + public APIUser? User { get; set; } + + [JsonProperty("beatmap")] + public APIBeatmap? Beatmap { get; set; } + + [JsonProperty("beatmapset")] + public APIBeatmapSet? BeatmapSet + { + set + { + // in the deserialisation case we need to ferry this data across. + // the order of properties returned by the API guarantees that the beatmap is populated by this point. + if (!(Beatmap is APIBeatmap apiBeatmap)) + throw new InvalidOperationException("Beatmap set metadata arrived before beatmap metadata in response"); + + apiBeatmap.BeatmapSet = value; + } + } + + [JsonProperty("pp")] + public double? PP { get; set; } + + #endregion + + public override string ToString() => $"score_id: {ID} user_id: {UserID}"; + + /// + /// Create a from an API score instance. + /// + /// A ruleset store, used to populate a ruleset instance in the returned score. + /// An optional beatmap, copied into the returned score (for cases where the API does not populate the beatmap). + /// + public ScoreInfo ToScoreInfo(RulesetStore rulesets, BeatmapInfo? beatmap = null) + { + var ruleset = rulesets.GetRuleset(RulesetID) ?? throw new InvalidOperationException($"Ruleset with ID of {RulesetID} not found locally"); + + var rulesetInstance = ruleset.CreateInstance(); + + var mods = Mods.Select(apiMod => apiMod.ToMod(rulesetInstance)).ToArray(); + + var scoreInfo = ToScoreInfo(mods); + + scoreInfo.Ruleset = ruleset; + if (beatmap != null) scoreInfo.BeatmapInfo = beatmap; + + return scoreInfo; + } + + /// + /// Create a from an API score instance. + /// + /// The mod instances, resolved from a ruleset. + /// + public ScoreInfo ToScoreInfo(Mod[] mods) => new ScoreInfo + { + OnlineID = OnlineID, + User = User ?? new APIUser { Id = UserID }, + BeatmapInfo = new BeatmapInfo { OnlineID = BeatmapID }, + Ruleset = new RulesetInfo { OnlineID = RulesetID }, + Passed = Passed, + TotalScore = TotalScore, + Accuracy = Accuracy, + MaxCombo = MaxCombo, + Rank = Rank, + Statistics = Statistics, + Date = EndedAt, + Hash = HasReplay ? "online" : string.Empty, // TODO: temporary? + Mods = mods, + PP = PP, + }; + + public long OnlineID => ID ?? -1; + } +} diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index 736024b08b..c303c410ec 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -1,9 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; -using Humanizer; using JetBrains.Annotations; using osu.Framework.IO.Network; using osu.Game.Extensions; @@ -84,7 +85,7 @@ namespace osu.Game.Online.API.Requests req.AddParameter("q", query); if (General != null && General.Any()) - req.AddParameter("c", string.Join('.', General.Select(e => e.ToString().Underscore()))); + req.AddParameter("c", string.Join('.', General.Select(e => e.ToString().ToSnakeCase()))); if (ruleset.OnlineID >= 0) req.AddParameter("m", ruleset.OnlineID.ToString()); @@ -110,7 +111,8 @@ namespace osu.Game.Online.API.Requests req.AddParameter("nsfw", ExplicitContent == SearchExplicit.Show ? "true" : "false"); - req.AddCursor(cursor); + if (cursor != null) + req.AddCursor(cursor); return req; } diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs index 3c4fb11ed1..abc30e18ea 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/BeatmapDownloadTracker.cs b/osu.Game/Online/BeatmapDownloadTracker.cs index 9f795f007a..19708cc07d 100644 --- a/osu.Game/Online/BeatmapDownloadTracker.cs +++ b/osu.Game/Online/BeatmapDownloadTracker.cs @@ -8,8 +8,6 @@ using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.API; -#nullable enable - namespace osu.Game.Online { public class BeatmapDownloadTracker : DownloadTracker @@ -42,7 +40,7 @@ namespace osu.Game.Online // Used to interact with manager classes that don't support interface types. Will eventually be replaced. var beatmapSetInfo = new BeatmapSetInfo { OnlineID = TrackedItem.OnlineID }; - realmSubscription = realm.RegisterForNotifications(r => r.All().Where(s => s.OnlineID == TrackedItem.OnlineID && !s.DeletePending), (items, changes, ___) => + realmSubscription = realm.RegisterForNotifications(r => r.All().Where(s => s.OnlineID == TrackedItem.OnlineID && !s.DeletePending), (items, _, _) => { if (items.Any()) Schedule(() => UpdateState(DownloadState.LocallyAvailable)); diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index a37d3084f0..f51ea3e8d6 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.ObjectModel; diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index c96e7c4cd3..ec84b0643d 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -131,12 +133,14 @@ namespace osu.Game.Online.Chat ?? JoinChannel(new Channel(user)); } - private void currentChannelChanged(ValueChangedEvent e) + private void currentChannelChanged(ValueChangedEvent channel) { - bool isSelectorChannel = e.NewValue is ChannelListing.ChannelListingChannel; + bool isSelectorChannel = channel.NewValue is ChannelListing.ChannelListingChannel; if (!isSelectorChannel) - JoinChannel(e.NewValue); + JoinChannel(channel.NewValue); + + Logger.Log($"Current channel changed to {channel.NewValue}"); } /// @@ -445,9 +449,17 @@ namespace osu.Game.Online.Chat return channel; case ChannelType.PM: + Logger.Log($"Attempting to join PM channel {channel}"); + var createRequest = new CreateChannelRequest(channel); + createRequest.Failure += e => + { + Logger.Log($"Failed to join PM channel {channel} ({e.Message})"); + }; createRequest.Success += resChannel => { + Logger.Log($"Joined PM channel {channel} ({resChannel.ChannelID})"); + if (resChannel.ChannelID.HasValue) { channel.Id = resChannel.ChannelID.Value; @@ -461,9 +473,19 @@ namespace osu.Game.Online.Chat break; default: + Logger.Log($"Attempting to join public channel {channel}"); + var req = new JoinChannelRequest(channel); - req.Success += () => joinChannel(channel, fetchInitialMessages); - req.Failure += ex => LeaveChannel(channel); + req.Success += () => + { + Logger.Log($"Joined public channel {channel}"); + joinChannel(channel, fetchInitialMessages); + }; + req.Failure += e => + { + Logger.Log($"Failed to join public channel {channel} ({e.Message})"); + LeaveChannel(channel); + }; api.Queue(req); return channel; } diff --git a/osu.Game/Online/Chat/ChannelType.cs b/osu.Game/Online/Chat/ChannelType.cs index bd628e90c4..a864e20830 100644 --- a/osu.Game/Online/Chat/ChannelType.cs +++ b/osu.Game/Online/Chat/ChannelType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Chat { public enum ChannelType diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index 3b0d049528..44e66c1a69 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Online/Chat/ErrorMessage.cs b/osu.Game/Online/Chat/ErrorMessage.cs index 87a65fb3f1..9cd91a0927 100644 --- a/osu.Game/Online/Chat/ErrorMessage.cs +++ b/osu.Game/Online/Chat/ErrorMessage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Chat { public class ErrorMessage : InfoMessage diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index 20d8459132..e557b9933e 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Online/Chat/IChannelPostTarget.cs b/osu.Game/Online/Chat/IChannelPostTarget.cs index 5697e918f0..bd8648189a 100644 --- a/osu.Game/Online/Chat/IChannelPostTarget.cs +++ b/osu.Game/Online/Chat/IChannelPostTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; namespace osu.Game.Online.Chat diff --git a/osu.Game/Online/Chat/InfoMessage.cs b/osu.Game/Online/Chat/InfoMessage.cs index e97245df45..d98c67de34 100644 --- a/osu.Game/Online/Chat/InfoMessage.cs +++ b/osu.Game/Online/Chat/InfoMessage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/Chat/LocalEchoMessage.cs b/osu.Game/Online/Chat/LocalEchoMessage.cs index 8a39515575..b226fe6cad 100644 --- a/osu.Game/Online/Chat/LocalEchoMessage.cs +++ b/osu.Game/Online/Chat/LocalEchoMessage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Chat { public class LocalEchoMessage : LocalMessage diff --git a/osu.Game/Online/Chat/LocalMessage.cs b/osu.Game/Online/Chat/LocalMessage.cs index 027edbcca5..5736f5cabf 100644 --- a/osu.Game/Online/Chat/LocalMessage.cs +++ b/osu.Game/Online/Chat/LocalMessage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Chat { /// diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index ad004e2881..86562341eb 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index b18daea453..7a040d9446 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -6,8 +6,6 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -#nullable enable - namespace osu.Game.Online.Chat { public static class MessageFormatter diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs index fbc5ef79ef..3fc6a008e8 100644 --- a/osu.Game/Online/Chat/MessageNotifier.cs +++ b/osu.Game/Online/Chat/MessageNotifier.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; diff --git a/osu.Game/Online/Chat/NowPlayingCommand.cs b/osu.Game/Online/Chat/NowPlayingCommand.cs index 2bf35d7973..6a25ceb919 100644 --- a/osu.Game/Online/Chat/NowPlayingCommand.cs +++ b/osu.Game/Online/Chat/NowPlayingCommand.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index bbfffea6fd..76fcb80eb4 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Online/DevelopmentEndpointConfiguration.cs b/osu.Game/Online/DevelopmentEndpointConfiguration.cs index 69531dbe1b..3171d15fc2 100644 --- a/osu.Game/Online/DevelopmentEndpointConfiguration.cs +++ b/osu.Game/Online/DevelopmentEndpointConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online { public class DevelopmentEndpointConfiguration : EndpointConfiguration @@ -12,6 +14,7 @@ namespace osu.Game.Online APIClientID = "5"; SpectatorEndpointUrl = $"{APIEndpointUrl}/spectator"; MultiplayerEndpointUrl = $"{APIEndpointUrl}/multiplayer"; + MetadataEndpointUrl = $"{APIEndpointUrl}/metadata"; } } } diff --git a/osu.Game/Online/DownloadTracker.cs b/osu.Game/Online/DownloadTracker.cs index 357c64b6a3..85af9abb33 100644 --- a/osu.Game/Online/DownloadTracker.cs +++ b/osu.Game/Online/DownloadTracker.cs @@ -4,8 +4,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; -#nullable enable - namespace osu.Game.Online { public abstract class DownloadTracker : Component diff --git a/osu.Game/Online/EndpointConfiguration.cs b/osu.Game/Online/EndpointConfiguration.cs index e347d3c653..f3bcced630 100644 --- a/osu.Game/Online/EndpointConfiguration.cs +++ b/osu.Game/Online/EndpointConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online { /// @@ -37,5 +39,10 @@ namespace osu.Game.Online /// The endpoint for the SignalR multiplayer server. /// public string MultiplayerEndpointUrl { get; set; } + + /// + /// The endpoint for the SignalR metadata server. + /// + public string MetadataEndpointUrl { get; set; } } } diff --git a/osu.Game/Online/HubClientConnector.cs b/osu.Game/Online/HubClientConnector.cs index 261724e315..6bfe09e911 100644 --- a/osu.Game/Online/HubClientConnector.cs +++ b/osu.Game/Online/HubClientConnector.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Net; @@ -66,26 +64,26 @@ namespace osu.Game.Online this.preferMessagePack = preferMessagePack; apiState.BindTo(api.State); - apiState.BindValueChanged(state => connectIfPossible(), true); + apiState.BindValueChanged(_ => Task.Run(connectIfPossible), true); } - public void Reconnect() + public Task Reconnect() { Logger.Log($"{clientName} reconnecting...", LoggingTarget.Network); - Task.Run(connectIfPossible); + return Task.Run(connectIfPossible); } - private void connectIfPossible() + private async Task connectIfPossible() { switch (apiState.Value) { case APIState.Failing: case APIState.Offline: - Task.Run(() => disconnect(true)); + await disconnect(true); break; case APIState.Online: - Task.Run(connect); + await connect(); break; } } @@ -146,7 +144,7 @@ namespace osu.Game.Online /// private async Task handleErrorAndDelay(Exception exception, CancellationToken cancellationToken) { - Logger.Log($"{clientName} connection error: {exception}", LoggingTarget.Network); + Logger.Log($"{clientName} connect attempt failed: {exception.Message}", LoggingTarget.Network); await Task.Delay(5000, cancellationToken).ConfigureAwait(false); } diff --git a/osu.Game/Online/IHubClientConnector.cs b/osu.Game/Online/IHubClientConnector.cs index b168e4669f..53c4897e73 100644 --- a/osu.Game/Online/IHubClientConnector.cs +++ b/osu.Game/Online/IHubClientConnector.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; using osu.Framework.Bindables; using osu.Game.Online.API; @@ -34,6 +33,6 @@ namespace osu.Game.Online /// /// Reconnect if already connected. /// - void Reconnect(); + Task Reconnect(); } } diff --git a/osu.Game/Online/ILinkHandler.cs b/osu.Game/Online/ILinkHandler.cs new file mode 100644 index 0000000000..1b8fad4bd9 --- /dev/null +++ b/osu.Game/Online/ILinkHandler.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.Game.Online.Chat; + +namespace osu.Game.Online +{ + /// + /// Handle an arbitrary URL. Displays via in-game overlays where possible. + /// Methods can be called from a non-thread-safe non-game-loaded state. + /// + [Cached] + public interface ILinkHandler + { + /// + /// Handle an arbitrary URL. Displays via in-game overlays where possible. + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The URL to load. + void HandleLink(string url); + + /// + /// Handle a specific . + /// This can be called from a non-thread-safe non-game-loaded state. + /// + /// The link to load. + void HandleLink(LinkDetails link); + } +} diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 4d41230799..35bdc4e31f 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index c94a6d3361..58b1ea62aa 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index c75e98cdaa..a7b6bd044d 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -179,11 +181,11 @@ namespace osu.Game.Online.Leaderboards Masking = true, Children = new Drawable[] { - new UpdateableFlag(user.Country) + new UpdateableFlag(user.CountryCode) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Size = new Vector2(30f, 20f), + Size = new Vector2(28, 20), }, new DateLabel(Score.Date) { @@ -424,10 +426,10 @@ namespace osu.Game.Online.Leaderboards items.Add(new OsuMenuItem("Use these mods", MenuItemType.Highlighted, () => songSelect.Mods.Value = Score.Mods)); if (Score.Files.Count > 0) + { items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage).Export(Score))); - - if (!isOnlineScope) items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); + } return items.ToArray(); } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs b/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs index c26e9e6802..53a4719050 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScoreTooltip.cs @@ -14,8 +14,6 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -#nullable enable - namespace osu.Game.Online.Leaderboards { public class LeaderboardScoreTooltip : VisibilityContainer, ITooltip diff --git a/osu.Game/Online/Leaderboards/LeaderboardState.cs b/osu.Game/Online/Leaderboards/LeaderboardState.cs index 6b07500a98..abc0ef4f19 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardState.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Leaderboards { public enum LeaderboardState diff --git a/osu.Game/Online/Leaderboards/UpdateableRank.cs b/osu.Game/Online/Leaderboards/UpdateableRank.cs index 8f74fd84fe..e4f5f72886 100644 --- a/osu.Game/Online/Leaderboards/UpdateableRank.cs +++ b/osu.Game/Online/Leaderboards/UpdateableRank.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Scoring; diff --git a/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs index 3db497bd6a..2d2d82821c 100644 --- a/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Online/Leaderboards/UserTopScoreContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using osu.Framework.Bindables; @@ -46,7 +48,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = @"your personal best".ToUpper(), + Text = @"your personal best".ToUpperInvariant(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, scoreContainer = new Container diff --git a/osu.Game/Online/Metadata/BeatmapUpdates.cs b/osu.Game/Online/Metadata/BeatmapUpdates.cs new file mode 100644 index 0000000000..a0cf616c70 --- /dev/null +++ b/osu.Game/Online/Metadata/BeatmapUpdates.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; +using MessagePack; + +namespace osu.Game.Online.Metadata +{ + /// + /// Describes a set of beatmaps which have been updated in some way. + /// + [MessagePackObject] + [Serializable] + public class BeatmapUpdates + { + [Key(0)] + public int[] BeatmapSetIDs { get; set; } + + [Key(1)] + public int LastProcessedQueueID { get; set; } + + public BeatmapUpdates(int[] beatmapSetIDs, int lastProcessedQueueID) + { + BeatmapSetIDs = beatmapSetIDs; + LastProcessedQueueID = lastProcessedQueueID; + } + } +} diff --git a/osu.Game/Online/Metadata/IMetadataClient.cs b/osu.Game/Online/Metadata/IMetadataClient.cs new file mode 100644 index 0000000000..ad1e7ebbaf --- /dev/null +++ b/osu.Game/Online/Metadata/IMetadataClient.cs @@ -0,0 +1,12 @@ +// 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.Tasks; + +namespace osu.Game.Online.Metadata +{ + public interface IMetadataClient + { + Task BeatmapSetsUpdated(BeatmapUpdates updates); + } +} diff --git a/osu.Game/Online/Metadata/IMetadataServer.cs b/osu.Game/Online/Metadata/IMetadataServer.cs new file mode 100644 index 0000000000..994f60f877 --- /dev/null +++ b/osu.Game/Online/Metadata/IMetadataServer.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 System.Threading.Tasks; + +namespace osu.Game.Online.Metadata +{ + /// + /// Metadata server is responsible for keeping the osu! client up-to-date with any changes. + /// + public interface IMetadataServer + { + /// + /// Get any changes since a specific point in the queue. + /// Should be used to allow the client to catch up with any changes after being closed or disconnected. + /// + /// The last processed queue ID. + /// + Task GetChangesSince(int queueId); + } +} diff --git a/osu.Game/Online/Metadata/MetadataClient.cs b/osu.Game/Online/Metadata/MetadataClient.cs new file mode 100644 index 0000000000..60867da2d7 --- /dev/null +++ b/osu.Game/Online/Metadata/MetadataClient.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 System; +using System.Linq; +using System.Threading.Tasks; +using osu.Framework.Graphics; + +namespace osu.Game.Online.Metadata +{ + public abstract class MetadataClient : Component, IMetadataClient, IMetadataServer + { + public abstract Task BeatmapSetsUpdated(BeatmapUpdates updates); + + public abstract Task GetChangesSince(int queueId); + + public Action? ChangedBeatmapSetsArrived; + + protected Task ProcessChanges(int[] beatmapSetIDs) + { + ChangedBeatmapSetsArrived?.Invoke(beatmapSetIDs.Distinct().ToArray()); + return Task.CompletedTask; + } + } +} diff --git a/osu.Game/Online/Metadata/OnlineMetadataClient.cs b/osu.Game/Online/Metadata/OnlineMetadataClient.cs new file mode 100644 index 0000000000..95228c380f --- /dev/null +++ b/osu.Game/Online/Metadata/OnlineMetadataClient.cs @@ -0,0 +1,120 @@ +// 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.Threading.Tasks; +using Microsoft.AspNetCore.SignalR.Client; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Logging; +using osu.Game.Configuration; +using osu.Game.Online.API; + +namespace osu.Game.Online.Metadata +{ + public class OnlineMetadataClient : MetadataClient + { + private readonly string endpoint; + + private IHubClientConnector? connector; + + private Bindable lastQueueId = null!; + + private HubConnection? connection => connector?.CurrentConnection; + + public OnlineMetadataClient(EndpointConfiguration endpoints) + { + endpoint = endpoints.MetadataEndpointUrl; + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, OsuConfigManager config) + { + // Importantly, we are intentionally not using MessagePack here to correctly support derived class serialization. + // More information on the limitations / reasoning can be found in osu-server-spectator's initialisation code. + connector = api.GetHubConnector(nameof(OnlineMetadataClient), endpoint); + + if (connector != null) + { + connector.ConfigureConnection = connection => + { + // this is kind of SILLY + // https://github.com/dotnet/aspnetcore/issues/15198 + connection.On(nameof(IMetadataClient.BeatmapSetsUpdated), ((IMetadataClient)this).BeatmapSetsUpdated); + }; + + connector.IsConnected.BindValueChanged(isConnectedChanged, true); + } + + lastQueueId = config.GetBindable(OsuSetting.LastProcessedMetadataId); + } + + private bool catchingUp; + + private void isConnectedChanged(ValueChangedEvent connected) + { + if (!connected.NewValue) + return; + + if (lastQueueId.Value >= 0) + { + catchingUp = true; + + Task.Run(async () => + { + try + { + while (true) + { + Logger.Log($"Requesting catch-up from {lastQueueId.Value}"); + var catchUpChanges = await GetChangesSince(lastQueueId.Value); + + lastQueueId.Value = catchUpChanges.LastProcessedQueueID; + + if (catchUpChanges.BeatmapSetIDs.Length == 0) + { + Logger.Log($"Catch-up complete at {lastQueueId.Value}"); + break; + } + + await ProcessChanges(catchUpChanges.BeatmapSetIDs); + } + } + finally + { + catchingUp = false; + } + }); + } + } + + public override async Task BeatmapSetsUpdated(BeatmapUpdates updates) + { + Logger.Log($"Received beatmap updates {updates.BeatmapSetIDs.Length} updates with last id {updates.LastProcessedQueueID}"); + + // If we're still catching up, avoid updating the last ID as it will interfere with catch-up efforts. + if (!catchingUp) + lastQueueId.Value = updates.LastProcessedQueueID; + + await ProcessChanges(updates.BeatmapSetIDs); + } + + public override Task GetChangesSince(int queueId) + { + if (connector?.IsConnected.Value != true) + return Task.FromCanceled(default); + + Logger.Log($"Requesting any changes since last known queue id {queueId}"); + + Debug.Assert(connection != null); + + return connection.InvokeAsync(nameof(IMetadataServer.GetChangesSince), queueId); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + connector?.Dispose(); + } + } +} diff --git a/osu.Game/Online/Multiplayer/Countdown/CountdownChangedEvent.cs b/osu.Game/Online/Multiplayer/Countdown/CountdownChangedEvent.cs index b067f3b235..649e3c8389 100644 --- a/osu.Game/Online/Multiplayer/Countdown/CountdownChangedEvent.cs +++ b/osu.Game/Online/Multiplayer/Countdown/CountdownChangedEvent.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using MessagePack; namespace osu.Game.Online.Multiplayer.Countdown diff --git a/osu.Game/Online/Multiplayer/Countdown/StartMatchCountdownRequest.cs b/osu.Game/Online/Multiplayer/Countdown/StartMatchCountdownRequest.cs index 08eab26090..d0de69d3f4 100644 --- a/osu.Game/Online/Multiplayer/Countdown/StartMatchCountdownRequest.cs +++ b/osu.Game/Online/Multiplayer/Countdown/StartMatchCountdownRequest.cs @@ -4,8 +4,6 @@ using System; using MessagePack; -#nullable enable - namespace osu.Game.Online.Multiplayer.Countdown { /// diff --git a/osu.Game/Online/Multiplayer/Countdown/StopCountdownRequest.cs b/osu.Game/Online/Multiplayer/Countdown/StopCountdownRequest.cs index 20a0e32734..bd0c381c0b 100644 --- a/osu.Game/Online/Multiplayer/Countdown/StopCountdownRequest.cs +++ b/osu.Game/Online/Multiplayer/Countdown/StopCountdownRequest.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using MessagePack; namespace osu.Game.Online.Multiplayer.Countdown diff --git a/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs b/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs index 4ec5019a07..7f5c0f0a05 100644 --- a/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs +++ b/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using MessagePack; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 2f454ea835..995bac1af5 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Threading.Tasks; using osu.Game.Online.API; diff --git a/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs index 0a618c8f5c..68bf3cfaec 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index 073d512f90..a2608f1564 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Threading.Tasks; using osu.Game.Online.API; diff --git a/osu.Game/Online/Multiplayer/IMultiplayerServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerServer.cs index d3a070af6d..cc7a474ce7 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerServer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/InvalidPasswordException.cs b/osu.Game/Online/Multiplayer/InvalidPasswordException.cs index 0441aea287..305c41e69b 100644 --- a/osu.Game/Online/Multiplayer/InvalidPasswordException.cs +++ b/osu.Game/Online/Multiplayer/InvalidPasswordException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs b/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs index 69b6d4bc13..ab513e71ee 100644 --- a/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs +++ b/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/InvalidStateException.cs b/osu.Game/Online/Multiplayer/InvalidStateException.cs index 77a3533dd3..ba3b84ffe4 100644 --- a/osu.Game/Online/Multiplayer/InvalidStateException.cs +++ b/osu.Game/Online/Multiplayer/InvalidStateException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/MatchRoomState.cs b/osu.Game/Online/Multiplayer/MatchRoomState.cs index 30d948f878..cae3aaf7d0 100644 --- a/osu.Game/Online/Multiplayer/MatchRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchRoomState.cs @@ -5,8 +5,6 @@ using System; using MessagePack; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; -#nullable enable - namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/MatchServerEvent.cs b/osu.Game/Online/Multiplayer/MatchServerEvent.cs index 4ce55e424d..20bf9e5141 100644 --- a/osu.Game/Online/Multiplayer/MatchServerEvent.cs +++ b/osu.Game/Online/Multiplayer/MatchServerEvent.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using MessagePack; using osu.Game.Online.Multiplayer.Countdown; diff --git a/osu.Game/Online/Multiplayer/MatchStartCountdown.cs b/osu.Game/Online/Multiplayer/MatchStartCountdown.cs index 6c1cdd97d3..5d3365c947 100644 --- a/osu.Game/Online/Multiplayer/MatchStartCountdown.cs +++ b/osu.Game/Online/Multiplayer/MatchStartCountdown.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using MessagePack; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs index a26a2b3fc2..4e425490ec 100644 --- a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/ChangeTeamRequest.cs @@ -3,8 +3,6 @@ using MessagePack; -#nullable enable - namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { [MessagePackObject] diff --git a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs index f952dbc1b5..4ecdfb882f 100644 --- a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/MultiplayerTeam.cs @@ -4,8 +4,6 @@ using System; using MessagePack; -#nullable enable - namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { [Serializable] diff --git a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs index 91d1aa43d4..3758429643 100644 --- a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusRoomState.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using MessagePack; -#nullable enable - namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { [MessagePackObject] diff --git a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs index 96a4e2ea99..ac3b9724cc 100644 --- a/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchTypes/TeamVersus/TeamVersusUserState.cs @@ -3,8 +3,6 @@ using MessagePack; -#nullable enable - namespace osu.Game.Online.Multiplayer.MatchTypes.TeamVersus { public class TeamVersusUserState : MatchUserState diff --git a/osu.Game/Online/Multiplayer/MatchUserRequest.cs b/osu.Game/Online/Multiplayer/MatchUserRequest.cs index 888b55e428..7fc1790434 100644 --- a/osu.Game/Online/Multiplayer/MatchUserRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchUserRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using MessagePack; using osu.Game.Online.Multiplayer.Countdown; diff --git a/osu.Game/Online/Multiplayer/MatchUserState.cs b/osu.Game/Online/Multiplayer/MatchUserState.cs index 665b64a8b4..92e8c501ed 100644 --- a/osu.Game/Online/Multiplayer/MatchUserState.cs +++ b/osu.Game/Online/Multiplayer/MatchUserState.cs @@ -5,8 +5,6 @@ using System; using MessagePack; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; -#nullable enable - namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index c95f3fa579..603bd10c38 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; @@ -23,7 +21,6 @@ using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Utils; -using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Online.Multiplayer { @@ -93,7 +90,7 @@ namespace osu.Game.Online.Multiplayer /// /// The joined . /// - public virtual MultiplayerRoom? Room + public virtual MultiplayerRoom? Room // virtual for moq { get { @@ -152,7 +149,7 @@ namespace osu.Game.Online.Multiplayer // clean up local room state on server disconnect. if (!connected.NewValue && Room != null) { - Logger.Log("Connection to multiplayer server was lost.", LoggingTarget.Runtime, LogLevel.Important); + Logger.Log("Clearing room due to multiplayer server connection loss.", LoggingTarget.Runtime, LogLevel.Important); LeaveRoom(); } })); @@ -415,7 +412,7 @@ namespace osu.Game.Online.Multiplayer UserJoined?.Invoke(user); RoomUpdated?.Invoke(); - }); + }, false); } Task IMultiplayerClient.UserLeft(MultiplayerRoomUser user) => diff --git a/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs b/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs index cda313bd0a..2083aa4e28 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClientExtensions.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using System.Threading.Tasks; diff --git a/osu.Game/Online/Multiplayer/MultiplayerCountdown.cs b/osu.Game/Online/Multiplayer/MultiplayerCountdown.cs index dbf2ab667b..621f9236fd 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerCountdown.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerCountdown.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using MessagePack; using osu.Game.Online.Multiplayer.Countdown; diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs index e215498ff9..fb05c03256 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using MessagePack; diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index 5c086066e6..356acb427c 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using MessagePack; using osu.Game.Online.Rooms; diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomState.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomState.cs index 48f25d7ca2..8e28d958a7 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomState.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomState.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index 50e539e8a6..681a839b89 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Online/Multiplayer/MultiplayerUserState.cs b/osu.Game/Online/Multiplayer/MultiplayerUserState.cs index d1369a7970..0f7dc6b8cd 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerUserState.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerUserState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Multiplayer { public enum MultiplayerUserState diff --git a/osu.Game/Online/Multiplayer/NotHostException.cs b/osu.Game/Online/Multiplayer/NotHostException.cs index 051cde45a0..9f789f1e81 100644 --- a/osu.Game/Online/Multiplayer/NotHostException.cs +++ b/osu.Game/Online/Multiplayer/NotHostException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs b/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs index 0e9902f002..c749e4615a 100644 --- a/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs +++ b/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index a3423d4189..190d150502 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; @@ -87,7 +85,13 @@ namespace osu.Game.Online.Multiplayer catch (HubException exception) { if (exception.GetHubExceptionMessage() == HubClientConnector.SERVER_SHUTDOWN_MESSAGE) - connector?.Reconnect(); + { + Debug.Assert(connector != null); + + await connector.Reconnect(); + return await JoinRoom(roomId, password); + } + throw; } } diff --git a/osu.Game/Online/Multiplayer/QueueMode.cs b/osu.Game/Online/Multiplayer/QueueMode.cs index 3d113c028e..a7bc4ae00a 100644 --- a/osu.Game/Online/Multiplayer/QueueMode.cs +++ b/osu.Game/Online/Multiplayer/QueueMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 4955aa9058..7af1ac9d5d 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Online/Placeholders/ClickablePlaceholder.cs b/osu.Game/Online/Placeholders/ClickablePlaceholder.cs index 054a4a3c39..7f9e16399e 100644 --- a/osu.Game/Online/Placeholders/ClickablePlaceholder.cs +++ b/osu.Game/Online/Placeholders/ClickablePlaceholder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index d03b3d8ffc..6a4065208e 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Online/Placeholders/MessagePlaceholder.cs b/osu.Game/Online/Placeholders/MessagePlaceholder.cs index 1676ba6cf2..451a4cba85 100644 --- a/osu.Game/Online/Placeholders/MessagePlaceholder.cs +++ b/osu.Game/Online/Placeholders/MessagePlaceholder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Online/Placeholders/Placeholder.cs b/osu.Game/Online/Placeholders/Placeholder.cs index f58282bbd9..3a05ce1365 100644 --- a/osu.Game/Online/Placeholders/Placeholder.cs +++ b/osu.Game/Online/Placeholders/Placeholder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index 5eddb3b49d..d54b8ca75d 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Threading.Tasks; diff --git a/osu.Game/Online/ProductionEndpointConfiguration.cs b/osu.Game/Online/ProductionEndpointConfiguration.cs index e44dad1db5..316452280d 100644 --- a/osu.Game/Online/ProductionEndpointConfiguration.cs +++ b/osu.Game/Online/ProductionEndpointConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online { public class ProductionEndpointConfiguration : EndpointConfiguration @@ -10,8 +12,9 @@ namespace osu.Game.Online WebsiteRootUrl = APIEndpointUrl = @"https://osu.ppy.sh"; APIClientSecret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; APIClientID = "5"; - SpectatorEndpointUrl = "https://spectator2.ppy.sh/spectator"; - MultiplayerEndpointUrl = "https://spectator2.ppy.sh/multiplayer"; + SpectatorEndpointUrl = "https://spectator.ppy.sh/spectator"; + MultiplayerEndpointUrl = "https://spectator.ppy.sh/multiplayer"; + MetadataEndpointUrl = "https://spectator.ppy.sh/metadata"; } } } diff --git a/osu.Game/Online/Rooms/APICreatedRoom.cs b/osu.Game/Online/Rooms/APICreatedRoom.cs index d1062b2306..ca1179efeb 100644 --- a/osu.Game/Online/Rooms/APICreatedRoom.cs +++ b/osu.Game/Online/Rooms/APICreatedRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/APILeaderboard.cs b/osu.Game/Online/Rooms/APILeaderboard.cs index c487123906..170cf3684b 100644 --- a/osu.Game/Online/Rooms/APILeaderboard.cs +++ b/osu.Game/Online/Rooms/APILeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/Rooms/APIScoreToken.cs b/osu.Game/Online/Rooms/APIScoreToken.cs index 6b559876de..58a633f3cf 100644 --- a/osu.Game/Online/Rooms/APIScoreToken.cs +++ b/osu.Game/Online/Rooms/APIScoreToken.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/BeatmapAvailability.cs b/osu.Game/Online/Rooms/BeatmapAvailability.cs index a83327aad5..f2b981c075 100644 --- a/osu.Game/Online/Rooms/BeatmapAvailability.cs +++ b/osu.Game/Online/Rooms/BeatmapAvailability.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using MessagePack; using Newtonsoft.Json; diff --git a/osu.Game/Online/Rooms/CreateRoomRequest.cs b/osu.Game/Online/Rooms/CreateRoomRequest.cs index f058eb9ba8..b22780490b 100644 --- a/osu.Game/Online/Rooms/CreateRoomRequest.cs +++ b/osu.Game/Online/Rooms/CreateRoomRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs b/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs index d4303e77df..65731b2b68 100644 --- a/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs +++ b/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API; diff --git a/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs b/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs index 67e2a2b27f..6b5ed2d024 100644 --- a/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/GetRoomRequest.cs b/osu.Game/Online/Rooms/GetRoomRequest.cs index 853873901e..237d427509 100644 --- a/osu.Game/Online/Rooms/GetRoomRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/GetRoomsRequest.cs b/osu.Game/Online/Rooms/GetRoomsRequest.cs index e45365797a..afab83b5be 100644 --- a/osu.Game/Online/Rooms/GetRoomsRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomsRequest.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; -using Humanizer; using osu.Framework.IO.Network; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Screens.OnlinePlay.Lounge.Components; @@ -25,7 +27,7 @@ namespace osu.Game.Online.Rooms var req = base.CreateWebRequest(); if (status != RoomStatusFilter.Open) - req.AddParameter("mode", status.ToString().Underscore().ToLowerInvariant()); + req.AddParameter("mode", status.ToString().ToSnakeCase().ToLowerInvariant()); if (!string.IsNullOrEmpty(category)) req.AddParameter("category", category); diff --git a/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs b/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs index bd9f254e1a..1e50155623 100644 --- a/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs +++ b/osu.Game/Online/Rooms/IndexPlaylistScoresRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/Rooms/IndexScoresParams.cs b/osu.Game/Online/Rooms/IndexScoresParams.cs index 3df8c8e753..253caa13a1 100644 --- a/osu.Game/Online/Rooms/IndexScoresParams.cs +++ b/osu.Game/Online/Rooms/IndexScoresParams.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Online/Rooms/IndexedMultiplayerScores.cs b/osu.Game/Online/Rooms/IndexedMultiplayerScores.cs index 2008d1aa52..459602f1b4 100644 --- a/osu.Game/Online/Rooms/IndexedMultiplayerScores.cs +++ b/osu.Game/Online/Rooms/IndexedMultiplayerScores.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Online/Rooms/ItemAttemptsCount.cs b/osu.Game/Online/Rooms/ItemAttemptsCount.cs index 298603d778..71f50b9898 100644 --- a/osu.Game/Online/Rooms/ItemAttemptsCount.cs +++ b/osu.Game/Online/Rooms/ItemAttemptsCount.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/JoinRoomRequest.cs b/osu.Game/Online/Rooms/JoinRoomRequest.cs index 2a3480c992..0a687312e7 100644 --- a/osu.Game/Online/Rooms/JoinRoomRequest.cs +++ b/osu.Game/Online/Rooms/JoinRoomRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API; diff --git a/osu.Game/Online/Rooms/MatchType.cs b/osu.Game/Online/Rooms/MatchType.cs index 278f0693eb..fd2f583f83 100644 --- a/osu.Game/Online/Rooms/MatchType.cs +++ b/osu.Game/Online/Rooms/MatchType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index 388a02f798..c45f703b05 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Online/Rooms/MultiplayerScore.cs b/osu.Game/Online/Rooms/MultiplayerScore.cs index 85327be037..6f597e5b10 100644 --- a/osu.Game/Online/Rooms/MultiplayerScore.cs +++ b/osu.Game/Online/Rooms/MultiplayerScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -77,7 +79,7 @@ namespace osu.Game.Online.Rooms TotalScore = TotalScore, MaxCombo = MaxCombo, BeatmapInfo = beatmap, - Ruleset = rulesets.GetRuleset(playlistItem.RulesetID) ?? throw new InvalidOperationException(), + Ruleset = rulesets.GetRuleset(playlistItem.RulesetID) ?? throw new InvalidOperationException($"Ruleset with ID of {playlistItem.RulesetID} not found locally"), Statistics = Statistics, User = User, Accuracy = Accuracy, diff --git a/osu.Game/Online/Rooms/MultiplayerScores.cs b/osu.Game/Online/Rooms/MultiplayerScores.cs index 3f970b2f8e..4c13579b3e 100644 --- a/osu.Game/Online/Rooms/MultiplayerScores.cs +++ b/osu.Game/Online/Rooms/MultiplayerScores.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Online/Rooms/MultiplayerScoresAround.cs b/osu.Game/Online/Rooms/MultiplayerScoresAround.cs index a99439312a..eca242bb0c 100644 --- a/osu.Game/Online/Rooms/MultiplayerScoresAround.cs +++ b/osu.Game/Online/Rooms/MultiplayerScoresAround.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index 4ca6d79b19..2fd8445980 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; @@ -99,7 +101,7 @@ namespace osu.Game.Online.Rooms // handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow). realmSubscription?.Dispose(); - realmSubscription = realm.RegisterForNotifications(r => filteredBeatmaps(), (items, changes, ___) => + realmSubscription = realm.RegisterForNotifications(_ => filteredBeatmaps(), (_, changes, _) => { if (changes == null) return; diff --git a/osu.Game/Online/Rooms/PartRoomRequest.cs b/osu.Game/Online/Rooms/PartRoomRequest.cs index 2f036abc8c..da4e9a44c5 100644 --- a/osu.Game/Online/Rooms/PartRoomRequest.cs +++ b/osu.Game/Online/Rooms/PartRoomRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API; diff --git a/osu.Game/Online/Rooms/PlaylistAggregateScore.cs b/osu.Game/Online/Rooms/PlaylistAggregateScore.cs index 61e0951cd5..85e7b29a05 100644 --- a/osu.Game/Online/Rooms/PlaylistAggregateScore.cs +++ b/osu.Game/Online/Rooms/PlaylistAggregateScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/PlaylistExtensions.cs b/osu.Game/Online/Rooms/PlaylistExtensions.cs index 34c93bd9e0..cd52a3c6e6 100644 --- a/osu.Game/Online/Rooms/PlaylistExtensions.cs +++ b/osu.Game/Online/Rooms/PlaylistExtensions.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using System.Linq; using Humanizer; diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 12091bae88..2213311c67 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using JetBrains.Annotations; @@ -74,7 +72,7 @@ namespace osu.Game.Online.Rooms /// In many cases, this will *not* contain any usable information apart from OnlineID. /// [JsonIgnore] - public IBeatmapInfo Beatmap { get; set; } = null!; + public IBeatmapInfo Beatmap { get; private set; } [JsonIgnore] public IBindable Valid => valid; @@ -83,6 +81,7 @@ namespace osu.Game.Online.Rooms [JsonConstructor] private PlaylistItem() + : this(new APIBeatmap()) { } diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 1933267efd..3a24fa02a8 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using Newtonsoft.Json; diff --git a/osu.Game/Online/Rooms/RoomAvailability.cs b/osu.Game/Online/Rooms/RoomAvailability.cs index 3aea0e5948..fada111826 100644 --- a/osu.Game/Online/Rooms/RoomAvailability.cs +++ b/osu.Game/Online/Rooms/RoomAvailability.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/RoomCategory.cs b/osu.Game/Online/Rooms/RoomCategory.cs index bca4d78359..ba17fb2121 100644 --- a/osu.Game/Online/Rooms/RoomCategory.cs +++ b/osu.Game/Online/Rooms/RoomCategory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/RoomStatus.cs b/osu.Game/Online/Rooms/RoomStatus.cs index 87c5aa3fda..4b890b00b7 100644 --- a/osu.Game/Online/Rooms/RoomStatus.cs +++ b/osu.Game/Online/Rooms/RoomStatus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs index 01f3ae368b..9aa6424592 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs index 686d4f4033..c37b93ea1b 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs index 83f1acf52a..9eb61a82ec 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs b/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs index ba3e3c6349..affb2846a2 100644 --- a/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs +++ b/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs index 39193be1af..f4cadc3fde 100644 --- a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Scoring; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/SubmitScoreRequest.cs b/osu.Game/Online/Rooms/SubmitScoreRequest.cs index b263262d2b..d681938da5 100644 --- a/osu.Game/Online/Rooms/SubmitScoreRequest.cs +++ b/osu.Game/Online/Rooms/SubmitScoreRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/ScoreDownloadTracker.cs b/osu.Game/Online/ScoreDownloadTracker.cs index ed1c566dbe..680bb16264 100644 --- a/osu.Game/Online/ScoreDownloadTracker.cs +++ b/osu.Game/Online/ScoreDownloadTracker.cs @@ -9,8 +9,6 @@ using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Scoring; -#nullable enable - namespace osu.Game.Online { public class ScoreDownloadTracker : DownloadTracker @@ -50,7 +48,7 @@ namespace osu.Game.Online realmSubscription = realm.RegisterForNotifications(r => r.All().Where(s => ((s.OnlineID > 0 && s.OnlineID == TrackedItem.OnlineID) || (!string.IsNullOrEmpty(s.Hash) && s.Hash == TrackedItem.Hash)) - && !s.DeletePending), (items, changes, ___) => + && !s.DeletePending), (items, _, _) => { if (items.Any()) Schedule(() => UpdateState(DownloadState.LocallyAvailable)); diff --git a/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs b/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs index ab04e046d3..a999cb47f8 100644 --- a/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs +++ b/osu.Game/Online/SignalRDerivedTypeWorkaroundJsonConverter.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable using System; using System.Linq; using Newtonsoft.Json; diff --git a/osu.Game/Online/SignalRUnionWorkaroundResolver.cs b/osu.Game/Online/SignalRUnionWorkaroundResolver.cs index c96f93df78..e58cd83477 100644 --- a/osu.Game/Online/SignalRUnionWorkaroundResolver.cs +++ b/osu.Game/Online/SignalRUnionWorkaroundResolver.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Online/SignalRWorkaroundTypes.cs b/osu.Game/Online/SignalRWorkaroundTypes.cs index d1f0ba725f..29e01e13ae 100644 --- a/osu.Game/Online/SignalRWorkaroundTypes.cs +++ b/osu.Game/Online/SignalRWorkaroundTypes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Online/Solo/CreateSoloScoreRequest.cs b/osu.Game/Online/Solo/CreateSoloScoreRequest.cs index 0d2bea1f2a..8c92b32915 100644 --- a/osu.Game/Online/Solo/CreateSoloScoreRequest.cs +++ b/osu.Game/Online/Solo/CreateSoloScoreRequest.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Globalization; using System.Net.Http; using osu.Framework.IO.Network; +using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Rooms; @@ -11,13 +14,13 @@ namespace osu.Game.Online.Solo { public class CreateSoloScoreRequest : APIRequest { - private readonly int beatmapId; + private readonly BeatmapInfo beatmapInfo; private readonly int rulesetId; private readonly string versionHash; - public CreateSoloScoreRequest(int beatmapId, int rulesetId, string versionHash) + public CreateSoloScoreRequest(BeatmapInfo beatmapInfo, int rulesetId, string versionHash) { - this.beatmapId = beatmapId; + this.beatmapInfo = beatmapInfo; this.rulesetId = rulesetId; this.versionHash = versionHash; } @@ -27,10 +30,11 @@ namespace osu.Game.Online.Solo var req = base.CreateWebRequest(); req.Method = HttpMethod.Post; req.AddParameter("version_hash", versionHash); + req.AddParameter("beatmap_hash", beatmapInfo.MD5Hash); req.AddParameter("ruleset_id", rulesetId.ToString(CultureInfo.InvariantCulture)); return req; } - protected override string Target => $@"beatmaps/{beatmapId}/solo/scores"; + protected override string Target => $@"beatmaps/{beatmapInfo.OnlineID}/solo/scores"; } } diff --git a/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs b/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs index 77fd7b813b..f387e61901 100644 --- a/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs +++ b/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.Rooms; using osu.Game.Scoring; diff --git a/osu.Game/Online/Solo/SubmittableScore.cs b/osu.Game/Online/Solo/SubmittableScore.cs index 9b6da1844a..31f0cb1dfb 100644 --- a/osu.Game/Online/Solo/SubmittableScore.cs +++ b/osu.Game/Online/Solo/SubmittableScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using JetBrains.Annotations; diff --git a/osu.Game/Online/Spectator/FrameDataBundle.cs b/osu.Game/Online/Spectator/FrameDataBundle.cs index a4c4972989..97ae468875 100644 --- a/osu.Game/Online/Spectator/FrameDataBundle.cs +++ b/osu.Game/Online/Spectator/FrameDataBundle.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using MessagePack; diff --git a/osu.Game/Online/Spectator/FrameHeader.cs b/osu.Game/Online/Spectator/FrameHeader.cs index adfcbcd95a..b6dcd8aaa5 100644 --- a/osu.Game/Online/Spectator/FrameHeader.cs +++ b/osu.Game/Online/Spectator/FrameHeader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using MessagePack; diff --git a/osu.Game/Online/Spectator/ISpectatorClient.cs b/osu.Game/Online/Spectator/ISpectatorClient.cs index 3acc9b2282..ccba280001 100644 --- a/osu.Game/Online/Spectator/ISpectatorClient.cs +++ b/osu.Game/Online/Spectator/ISpectatorClient.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; namespace osu.Game.Online.Spectator diff --git a/osu.Game/Online/Spectator/ISpectatorServer.cs b/osu.Game/Online/Spectator/ISpectatorServer.cs index af0196862a..25785f60a4 100644 --- a/osu.Game/Online/Spectator/ISpectatorServer.cs +++ b/osu.Game/Online/Spectator/ISpectatorServer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; namespace osu.Game.Online.Spectator diff --git a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs index 0f77f723db..030ca724c4 100644 --- a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs +++ b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; @@ -58,13 +56,20 @@ namespace osu.Game.Online.Spectator try { - await connection.SendAsync(nameof(ISpectatorServer.BeginPlaySession), state); + await connection.InvokeAsync(nameof(ISpectatorServer.BeginPlaySession), state); } catch (HubException exception) { if (exception.GetHubExceptionMessage() == HubClientConnector.SERVER_SHUTDOWN_MESSAGE) - connector?.Reconnect(); - throw; + { + Debug.Assert(connector != null); + + await connector.Reconnect(); + await BeginPlayingInternal(state); + } + + // Exceptions can occur if, for instance, the locally played beatmap doesn't have a server-side counterpart. + // For now, let's ignore these so they don't cause unobserved exceptions to appear to the user (and sentry). } } @@ -75,7 +80,7 @@ namespace osu.Game.Online.Spectator Debug.Assert(connection != null); - return connection.SendAsync(nameof(ISpectatorServer.SendFrameData), bundle); + return connection.InvokeAsync(nameof(ISpectatorServer.SendFrameData), bundle); } protected override Task EndPlayingInternal(SpectatorState state) @@ -85,7 +90,7 @@ namespace osu.Game.Online.Spectator Debug.Assert(connection != null); - return connection.SendAsync(nameof(ISpectatorServer.EndPlaySession), state); + return connection.InvokeAsync(nameof(ISpectatorServer.EndPlaySession), state); } protected override Task WatchUserInternal(int userId) @@ -95,7 +100,7 @@ namespace osu.Game.Online.Spectator Debug.Assert(connection != null); - return connection.SendAsync(nameof(ISpectatorServer.StartWatchingUser), userId); + return connection.InvokeAsync(nameof(ISpectatorServer.StartWatchingUser), userId); } protected override Task StopWatchingUserInternal(int userId) @@ -105,7 +110,7 @@ namespace osu.Game.Online.Spectator Debug.Assert(connection != null); - return connection.SendAsync(nameof(ISpectatorServer.EndWatchingUser), userId); + return connection.InvokeAsync(nameof(ISpectatorServer.EndWatchingUser), userId); } } } diff --git a/osu.Game/Online/Spectator/SpectatedUserState.cs b/osu.Game/Online/Spectator/SpectatedUserState.cs index 0f0a3068b8..edf0859a33 100644 --- a/osu.Game/Online/Spectator/SpectatedUserState.cs +++ b/osu.Game/Online/Spectator/SpectatedUserState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Online.Spectator { public enum SpectatedUserState diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 9bf49364f3..68c8b57019 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; @@ -190,7 +188,10 @@ namespace osu.Game.Online.Spectator } if (frame is IConvertibleReplayFrame convertible) + { + Debug.Assert(currentBeatmap != null); pendingFrames.Enqueue(convertible.ToLegacy(currentBeatmap)); + } if (pendingFrames.Count > max_pending_frames) purgePendingFrames(); @@ -296,17 +297,21 @@ namespace osu.Game.Online.Spectator lastSend = tcs.Task; - SendFramesInternal(bundle).ContinueWith(t => Schedule(() => + SendFramesInternal(bundle).ContinueWith(t => { + // Handle exception outside of `Schedule` to ensure it doesn't go unovserved. bool wasSuccessful = t.Exception == null; - // If the last bundle send wasn't successful, try again without dequeuing. - if (wasSuccessful) - pendingFrameBundles.Dequeue(); + return Schedule(() => + { + // If the last bundle send wasn't successful, try again without dequeuing. + if (wasSuccessful) + pendingFrameBundles.Dequeue(); - tcs.SetResult(wasSuccessful); - sendNextBundleIfRequired(); - })); + tcs.SetResult(wasSuccessful); + sendNextBundleIfRequired(); + }); + }); } } } diff --git a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs index a1e8715c8f..87f25874c5 100644 --- a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs +++ b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Online/Spectator/SpectatorState.cs b/osu.Game/Online/Spectator/SpectatorState.cs index 64e5f8b3a1..766b274e63 100644 --- a/osu.Game/Online/Spectator/SpectatorState.cs +++ b/osu.Game/Online/Spectator/SpectatorState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 1f9a1ce938..69d02b95ff 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -22,6 +24,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Screens; using osu.Framework.Threading; @@ -37,6 +40,7 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; using osu.Game.Localisation; +using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Overlays; @@ -67,7 +71,7 @@ namespace osu.Game /// The full osu! experience. Builds on top of to add menus and binding logic /// for initial components that are generally retrieved via DI. /// - public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo, IPerformFromScreenRunner, IOverlayManager + public class OsuGame : OsuGameBase, IKeyBindingHandler, ILocalUserPlayInfo, IPerformFromScreenRunner, IOverlayManager, ILinkHandler { /// /// The amount of global offset to apply when a left/right anchored overlay is displayed (ie. settings or notifications). @@ -153,7 +157,9 @@ namespace osu.Game protected SettingsOverlay Settings; - private FirstRunSetupOverlay firstRunOverlay; + protected FirstRunSetupOverlay FirstRunOverlay { get; private set; } + + private FPSCounter fpsCounter; private VolumeOverlay volume; @@ -228,7 +234,7 @@ namespace osu.Game /// /// Unregisters a blocking that was not created by itself. /// - private void unregisterBlockingOverlay(OverlayContainer overlayContainer) + private void unregisterBlockingOverlay(OverlayContainer overlayContainer) => Schedule(() => { externalOverlays.Remove(overlayContainer); @@ -236,7 +242,7 @@ namespace osu.Game focusedOverlays.Remove(focusedOverlayContainer); overlayContainer.Expire(); - } + }); #endregion @@ -483,6 +489,7 @@ namespace osu.Game /// public void PresentBeatmap(IBeatmapSetInfo beatmap, Predicate difficultyCriteria = null) { + Logger.Log($"Beginning {nameof(PresentBeatmap)} with beatmap {beatmap}"); Live databasedSet = null; if (beatmap.OnlineID > 0) @@ -519,6 +526,7 @@ namespace osu.Game } else { + Logger.Log($"Completing {nameof(PresentBeatmap)} with beatmap {beatmap} ruleset {selection.Ruleset}"); Ruleset.Value = selection.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(selection); } @@ -531,6 +539,8 @@ namespace osu.Game /// public void PresentScore(IScoreInfo score, ScorePresentType presentType = ScorePresentType.Results) { + Logger.Log($"Beginning {nameof(PresentScore)} with score {score}"); + // The given ScoreInfo may have missing properties if it was retrieved from online data. Re-retrieve it from the database // to ensure all the required data for presenting a replay are present. ScoreInfo databasedScoreInfo = null; @@ -565,6 +575,8 @@ namespace osu.Game PerformFromScreen(screen => { + Logger.Log($"{nameof(PresentScore)} updating beatmap ({databasedBeatmap}) and ruleset ({databasedScore.ScoreInfo.Ruleset} to match score"); + Ruleset.Value = databasedScore.ScoreInfo.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); @@ -609,7 +621,6 @@ namespace osu.Game { beatmap.OldValue?.CancelAsyncLoad(); beatmap.NewValue?.BeginAsyncLoad(); - Logger.Log($"Game-wide working beatmap updated to {beatmap.NewValue}"); } private void modsChanged(ValueChangedEvent> mods) @@ -635,6 +646,12 @@ namespace osu.Game Add(performFromMainMenuTask = new PerformFromMenuRunner(action, validScreens, () => ScreenStack.CurrentScreen)); } + public override void AttemptExit() + { + // Using PerformFromScreen gives the user a chance to interrupt the exit process if needed. + PerformFromScreen(menu => menu.Exit()); + } + /// /// Wait for the game (and target component) to become loaded and then run an action. /// @@ -672,27 +689,29 @@ namespace osu.Game { base.LoadComplete(); - foreach (var language in Enum.GetValues(typeof(Language)).OfType()) + var languages = Enum.GetValues(typeof(Language)).OfType(); + + var mappings = languages.Select(language => { #if DEBUG if (language == Language.debug) - { - Localisation.AddLanguage(Language.debug.ToString(), new DebugLocalisationStore()); - continue; - } + return new LocaleMapping("debug", new DebugLocalisationStore()); #endif string cultureCode = language.ToCultureCode(); try { - Localisation.AddLanguage(cultureCode, new ResourceManagerLocalisationStore(cultureCode)); + return new LocaleMapping(new ResourceManagerLocalisationStore(cultureCode)); } catch (Exception ex) { Logger.Error(ex, $"Could not load localisations for language \"{cultureCode}\""); + return null; } - } + }).Where(m => m != null); + + Localisation.AddLocaleMappings(mappings); // 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. @@ -703,13 +722,13 @@ namespace osu.Game SkinManager.PostNotification = n => Notifications.Post(n); BeatmapManager.PostNotification = n => Notifications.Post(n); - BeatmapManager.PostImport = items => PresentBeatmap(items.First().Value); + BeatmapManager.PresentImport = items => PresentBeatmap(items.First().Value); BeatmapDownloader.PostNotification = n => Notifications.Post(n); ScoreDownloader.PostNotification = n => Notifications.Post(n); ScoreManager.PostNotification = n => Notifications.Post(n); - ScoreManager.PostImport = items => PresentScore(items.First().Value); + ScoreManager.PresentImport = items => PresentScore(items.First().Value); // make config aware of how to lookup skins for on-screen display purposes. // if this becomes a more common thing, tracked settings should be reconsidered to allow local DI. @@ -797,6 +816,13 @@ namespace osu.Game ScreenStack.ScreenPushed += screenPushed; ScreenStack.ScreenExited += screenExited; + loadComponentSingleFile(fpsCounter = new FPSCounter + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding(5), + }, topMostOverlayContent.Add); + if (!args?.Any(a => a == @"--no-version-overlay") ?? true) loadComponentSingleFile(versionManager = new VersionManager { Depth = int.MinValue }, ScreenContainer.Add); @@ -845,7 +871,7 @@ namespace osu.Game loadComponentSingleFile(CreateUpdateManager(), Add, true); // overlay elements - loadComponentSingleFile(firstRunOverlay = new FirstRunSetupOverlay(), overlayContent.Add, true); + loadComponentSingleFile(FirstRunOverlay = new FirstRunSetupOverlay(), overlayContent.Add, true); loadComponentSingleFile(new ManageCollectionsDialog(), overlayContent.Add, true); loadComponentSingleFile(beatmapListing = new BeatmapListingOverlay(), overlayContent.Add, true); loadComponentSingleFile(dashboard = new DashboardOverlay(), overlayContent.Add, true); @@ -896,7 +922,7 @@ namespace osu.Game Add(new MusicKeyBindingHandler()); // side overlays which cancel each other. - var singleDisplaySideOverlays = new OverlayContainer[] { Settings, Notifications, firstRunOverlay }; + var singleDisplaySideOverlays = new OverlayContainer[] { Settings, Notifications, FirstRunOverlay }; foreach (var overlay in singleDisplaySideOverlays) { @@ -921,7 +947,7 @@ namespace osu.Game } // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { firstRunOverlay, chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay }; + var singleDisplayOverlays = new OverlayContainer[] { FirstRunOverlay, chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay }; foreach (var overlay in singleDisplayOverlays) { @@ -1097,6 +1123,10 @@ namespace osu.Game switch (e.Action) { + case GlobalAction.ToggleFPSDisplay: + fpsCounter.ToggleVisibility(); + return true; + case GlobalAction.ToggleSkinEditor: skinEditor.ToggleVisibility(); return true; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 5dbdf6f602..6a5c6835ba 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -1,9 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; using System.Threading; @@ -16,9 +17,10 @@ using osu.Framework.Development; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Performance; using osu.Framework.Graphics.Textures; using osu.Framework.Input; +using osu.Framework.Input.Handlers; +using osu.Framework.Input.Handlers.Midi; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; @@ -37,15 +39,19 @@ using osu.Game.IO; using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.Chat; +using osu.Game.Online.Metadata; using osu.Game.Online.Multiplayer; using osu.Game.Online.Spectator; using osu.Game.Overlays; +using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections; using osu.Game.Resources; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; +using File = System.IO.File; using RuntimeInfo = osu.Framework.RuntimeInfo; namespace osu.Game @@ -57,6 +63,8 @@ namespace osu.Game /// public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider { + public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; + public const string OSU_PROTOCOL = "osu://"; public const string CLIENT_STREAM_NAME = @"lazer"; @@ -81,7 +89,7 @@ namespace osu.Game public virtual bool UseDevelopmentServer => DebugUtils.IsDebugBuild; internal EndpointConfiguration CreateEndpoints() => - UseDevelopmentServer ? (EndpointConfiguration)new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration(); + UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration(); public virtual Version AssemblyVersion => Assembly.GetEntryAssembly()?.GetName().Version ?? new Version(); @@ -159,9 +167,10 @@ namespace osu.Game /// /// Mods available for the current . /// - public readonly Bindable>> AvailableMods = new Bindable>>(); + public readonly Bindable>> AvailableMods = new Bindable>>(new Dictionary>()); private BeatmapDifficultyCache difficultyCache; + private BeatmapUpdater beatmapUpdater; private UserLookupCache userCache; private BeatmapLookupCache beatmapCache; @@ -172,6 +181,8 @@ namespace osu.Game private MultiplayerClient multiplayerClient; + private MetadataClient metadataClient; + private RealmAccess realm; protected override Container Content => content; @@ -180,8 +191,6 @@ namespace osu.Game private DependencyContainer dependencies; - private Bindable fpsDisplayVisible; - private readonly BindableNumber globalTrackVolumeAdjust = new BindableNumber(global_track_volume_adjust); /// @@ -233,32 +242,10 @@ namespace osu.Game Decoder.RegisterDependencies(RulesetStore); - // Backup is taken here rather than in EFToRealmMigrator to avoid recycling realm contexts - // after initial usages below. It can be moved once a direction is established for handling re-subscription. - // See https://github.com/ppy/osu/pull/16547 for more discussion. - if (EFContextFactory != null) - { - const string backup_folder = "backups"; - - string migration = $"before_final_migration_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"; - - EFContextFactory.CreateBackup(Path.Combine(backup_folder, $"client.{migration}.db")); - realm.CreateBackup(Path.Combine(backup_folder, $"client.{migration}.realm")); - - using (var source = Storage.GetStream("collection.db")) - { - if (source != null) - { - using (var destination = Storage.CreateFileSafely(Path.Combine(backup_folder, $"collection.{migration}.db"))) - source.CopyTo(destination); - } - } - } - dependencies.CacheAs(Storage); var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); - largeStore.AddStore(Host.CreateTextureLoaderStore(new OnlineStore())); + largeStore.AddTextureSource(Host.CreateTextureLoaderStore(new OnlineStore())); dependencies.Cache(largeStore); dependencies.CacheAs(this); @@ -277,21 +264,32 @@ namespace osu.Game dependencies.CacheAs(API ??= new APIAccess(LocalConfig, endpoints, VersionHash)); - dependencies.CacheAs(spectatorClient = new OnlineSpectatorClient(endpoints)); - dependencies.CacheAs(multiplayerClient = new OnlineMultiplayerClient(endpoints)); - var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); + dependencies.Cache(difficultyCache = new BeatmapDifficultyCache()); + // ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup() - dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, realm, Scheduler, () => difficultyCache, LocalConfig)); - dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, realm, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, performOnlineLookups: true)); + dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, realm, Scheduler, API, difficultyCache, LocalConfig)); + + dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, realm, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, difficultyCache, performOnlineLookups: true)); dependencies.Cache(BeatmapDownloader = new BeatmapModelDownloader(BeatmapManager, API)); dependencies.Cache(ScoreDownloader = new ScoreModelDownloader(ScoreManager, API)); - dependencies.Cache(difficultyCache = new BeatmapDifficultyCache()); + // Add after all the above cache operations as it depends on them. AddInternal(difficultyCache); + // TODO: OsuGame or OsuGameBase? + beatmapUpdater = new BeatmapUpdater(BeatmapManager, difficultyCache, API, Storage); + + dependencies.CacheAs(spectatorClient = new OnlineSpectatorClient(endpoints)); + dependencies.CacheAs(multiplayerClient = new OnlineMultiplayerClient(endpoints)); + dependencies.CacheAs(metadataClient = new OnlineMetadataClient(endpoints)); + + AddInternal(new BeatmapOnlineChangeIngest(beatmapUpdater, realm, metadataClient)); + + BeatmapManager.ProcessBeatmap = set => beatmapUpdater.Process(set); + dependencies.Cache(userCache = new UserLookupCache()); AddInternal(userCache); @@ -328,8 +326,10 @@ namespace osu.Game // add api components to hierarchy. if (API is APIAccess apiAccess) AddInternal(apiAccess); + AddInternal(spectatorClient); AddInternal(multiplayerClient); + AddInternal(metadataClient); AddInternal(rulesetConfigCache); @@ -403,19 +403,6 @@ namespace osu.Game AddFont(Resources, @"Fonts/Venera/Venera-Black"); } - protected override void LoadComplete() - { - base.LoadComplete(); - - // 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 += visible => { FrameStatistics.Value = visible.NewValue ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; - fpsDisplayVisible.TriggerChange(); - - FrameStatistics.ValueChanged += e => fpsDisplayVisible.Value = e.NewValue != FrameStatisticsMode.None; - } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -435,14 +422,15 @@ namespace osu.Game /// /// Use to programatically exit the game as if the user was triggering via alt-f4. - /// Will keep persisting until an exit occurs (exit may be blocked multiple times). + /// By default, will keep persisting until an exit occurs (exit may be blocked multiple times). + /// May be interrupted (see 's override). /// - public void GracefullyExit() + public virtual void AttemptExit() { if (!OnExiting()) Exit(); else - Scheduler.AddDelayed(GracefullyExit, 2000); + Scheduler.AddDelayed(AttemptExit, 2000); } public bool Migrate(string path) @@ -457,12 +445,13 @@ namespace osu.Game Scheduler.Add(() => { - realmBlocker = realm.BlockAllOperations(); + realmBlocker = realm.BlockAllOperations("migration"); readyToRun.Set(); }, false); - readyToRun.Wait(); + if (!readyToRun.Wait(30000)) + throw new TimeoutException("Attempting to block for migration took too long."); bool? cleanupSucceded = (Storage as OsuStorage)?.Migrate(Host.GetStorage(path)); @@ -483,10 +472,29 @@ namespace osu.Game protected override Storage CreateStorage(GameHost host, Storage defaultStorage) => new OsuStorage(host, defaultStorage); - private void onBeatmapChanged(ValueChangedEvent valueChangedEvent) + /// + /// Creates an input settings subsection for an . + /// + /// Should be overriden per-platform to provide settings for platform-specific handlers. + public virtual SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler) + { + switch (handler) + { + case MidiHandler: + return new InputSection.HandlerSection(handler); + + // return null for handlers that shouldn't have settings. + default: + return null; + } + } + + private void onBeatmapChanged(ValueChangedEvent beatmap) { if (IsLoaded && !ThreadSafety.IsUpdateThread) throw new InvalidOperationException("Global beatmap bindable must be changed from update thread."); + + Logger.Log($"Game-wide working beatmap updated to {beatmap.NewValue}"); } private void onRulesetChanged(ValueChangedEvent r) @@ -511,21 +519,36 @@ namespace osu.Game if (instance == null) { // reject the change if the ruleset is not available. - Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First(); + revertRulesetChange(); return; } var dict = new Dictionary>(); - foreach (ModType type in Enum.GetValues(typeof(ModType))) + try { - dict[type] = instance.GetModsFor(type).ToList(); + foreach (ModType type in Enum.GetValues(typeof(ModType))) + { + dict[type] = instance.GetModsFor(type) + // Rulesets should never return null mods, but let's be defensive just in case. + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + .Where(mod => mod != null) + .ToList(); + } + } + catch (Exception e) + { + Logger.Error(e, $"Could not load mods for \"{instance.RulesetInfo.Name}\" ruleset. Current ruleset has been rolled back."); + revertRulesetChange(); + return; } if (!SelectedMods.Disabled) SelectedMods.Value = Array.Empty(); AvailableMods.Value = dict; + + void revertRulesetChange() => Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First(); } private int allowableExceptions; @@ -550,17 +573,18 @@ namespace osu.Game base.Dispose(isDisposing); RulesetStore?.Dispose(); - BeatmapManager?.Dispose(); LocalConfig?.Dispose(); + beatmapUpdater?.Dispose(); + realm?.Dispose(); if (Host != null) Host.ExceptionThrown -= onExceptionThrown; } - ControlPointInfo IBeatSyncProvider.ControlPoints => Beatmap.Value.Beatmap.ControlPointInfo; + ControlPointInfo IBeatSyncProvider.ControlPoints => Beatmap.Value.BeatmapLoaded ? Beatmap.Value.Beatmap.ControlPointInfo : null; IClock IBeatSyncProvider.Clock => Beatmap.Value.TrackLoaded ? Beatmap.Value.Track : (IClock)null; - ChannelAmplitudes? IBeatSyncProvider.Amplitudes => Beatmap.Value.TrackLoaded ? Beatmap.Value.Track.CurrentAmplitudes : (ChannelAmplitudes?)null; + ChannelAmplitudes? IBeatSyncProvider.Amplitudes => Beatmap.Value.TrackLoaded ? Beatmap.Value.Track.CurrentAmplitudes : null; } } diff --git a/osu.Game/OsuGameBase_Importing.cs b/osu.Game/OsuGameBase_Importing.cs index d712da3553..e34e48f21d 100644 --- a/osu.Game/OsuGameBase_Importing.cs +++ b/osu.Game/OsuGameBase_Importing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs index 2e52ca74f3..2b372c18eb 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs index 6aef358b2e..299a41f45b 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index f4f958e4a4..2120f351a2 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading.Tasks; diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 780a79f8f9..f8070788c2 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index f6ddb135ec..1936ad533a 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index a96aff2a5d..c51ed07c38 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs index 1f9a63e3b9..13da9d335c 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingCardSizeTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs index e4628e3723..2ca369d459 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -141,7 +143,7 @@ namespace osu.Game.Overlays.BeatmapListing } public void Search(string query) - => searchControl.Query.Value = query; + => Schedule(() => searchControl.Query.Value = query); protected override void LoadComplete() { @@ -159,13 +161,13 @@ namespace osu.Game.Overlays.BeatmapListing queueUpdateSearch(true); }); - searchControl.General.CollectionChanged += (_, __) => queueUpdateSearch(); + searchControl.General.CollectionChanged += (_, _) => queueUpdateSearch(); searchControl.Ruleset.BindValueChanged(_ => queueUpdateSearch()); searchControl.Category.BindValueChanged(_ => queueUpdateSearch()); searchControl.Genre.BindValueChanged(_ => queueUpdateSearch()); searchControl.Language.BindValueChanged(_ => queueUpdateSearch()); - searchControl.Extra.CollectionChanged += (_, __) => queueUpdateSearch(); - searchControl.Ranks.CollectionChanged += (_, __) => queueUpdateSearch(); + searchControl.Extra.CollectionChanged += (_, _) => queueUpdateSearch(); + searchControl.Ranks.CollectionChanged += (_, _) => queueUpdateSearch(); searchControl.Played.BindValueChanged(_ => queueUpdateSearch()); searchControl.ExplicitContent.BindValueChanged(_ => queueUpdateSearch()); diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index 3568fe9e4f..ccab810612 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index eeaa31a013..86cf3b5588 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index 4c77a736ac..454f381c60 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index 4c831543fe..8ae39aeaca 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs index 51dad100c2..c01aa9a1c4 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs index 461a06a634..cca75e9548 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchMultipleSelectionFilterRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs index e2c84c537c..526c14511e 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs index b39934b56f..118ddfb060 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions; diff --git a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs index ff43170207..cc131ffc27 100644 --- a/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs +++ b/osu.Game/Overlays/BeatmapListing/FilterTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions; diff --git a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs index b52df6234f..b3e12d00a6 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs index 80482b32a0..10fea6d5b2 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs index e54632acd8..d307cd09eb 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs index 34ff5b9840..ebcbef1ad9 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs index 08855284cb..7746eb50d7 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs index 7ffa0282b7..d52f923158 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs index 3b04ac01ca..0c379b3825 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs index 871b3c162b..ff6e62b274 100644 --- a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs +++ b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 3476968ded..cfa53009ef 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 9131f6f74c..2341997626 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 8f848edf24..a8bbb9fe1c 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs b/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs index b6e768d632..d893ef80d8 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapAvailability.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs index a75fc8e888..52fed99431 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs @@ -10,8 +10,6 @@ using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -#nullable enable - namespace osu.Game.Overlays.BeatmapSet { public abstract class BeatmapBadge : CompositeDrawable diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 031442814d..b27d9b3f1e 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework; @@ -154,7 +156,7 @@ namespace osu.Game.Overlays.BeatmapSet { base.LoadComplete(); - ruleset.ValueChanged += r => updateDisplay(); + ruleset.ValueChanged += _ => updateDisplay(); // done here so everything can bind in intialization and get the first trigger Beatmap.TriggerChange(); @@ -272,8 +274,10 @@ namespace osu.Game.Overlays.BeatmapSet Alpha = 0.5f } }, - icon = new DifficultyIcon(beatmapInfo, shouldShowTooltip: false) + icon = new DifficultyIcon(beatmapInfo) { + ShowTooltip = false, + Current = { Value = new StarDifficulty(beatmapInfo.StarRating, 0) }, Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(size - tile_icon_padding * 2), diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 6564ca3d41..0f5eb18c4e 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Rulesets; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs index e8cdc6913b..e9acca5bcd 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs index 102cddfa92..02da7812d1 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index e0fc7482f6..c9e97d5f2f 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs index e6d433f7bc..797b6716e7 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 28100e5fff..f7c8aa44ad 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs index 99b0b2ed3b..25d11bd6d7 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index 74417b0ac6..c2de96f245 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs index 63b7a0a062..e840d0e82c 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 751299161d..8fc8927c4b 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index dfc8d5e680..6db54db811 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs index 2a20d22b61..18dcfc0385 100644 --- a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs @@ -5,8 +5,6 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Resources.Localisation.Web; -#nullable enable - namespace osu.Game.Overlays.BeatmapSet { public class ExplicitContentBeatmapBadge : BeatmapBadge diff --git a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs index 20ee11c7f6..a0ee0a18ec 100644 --- a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs @@ -5,8 +5,6 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Resources.Localisation.Web; -#nullable enable - namespace osu.Game.Overlays.BeatmapSet { public class FeaturedArtistBeatmapBadge : BeatmapBadge diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 3ef52d718d..666ceff6cb 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs index 25aed4c980..8311368da3 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardModSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index 607355b7bf..db7d04f597 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Screens.Select.Leaderboards; using osu.Game.Graphics.UserInterface; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs index f1b9f98528..317b369d8f 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataSection.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataSection.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -20,11 +23,14 @@ namespace osu.Game.Overlays.BeatmapSet private readonly MetadataType type; private TextFlowContainer textFlow; + private readonly Action searchAction; + private const float transition_duration = 250; - public MetadataSection(MetadataType type) + public MetadataSection(MetadataType type, Action searchAction = null) { this.type = type; + this.searchAction = searchAction; Alpha = 0; @@ -89,7 +95,12 @@ namespace osu.Game.Overlays.BeatmapSet for (int i = 0; i <= tags.Length - 1; i++) { - loaded.AddLink(tags[i], LinkAction.SearchBeatmapSet, tags[i]); + string tag = tags[i]; + + if (searchAction != null) + loaded.AddLink(tag, () => searchAction(tag)); + else + loaded.AddLink(tag, LinkAction.SearchBeatmapSet, tag); if (i != tags.Length - 1) loaded.AddText(" "); @@ -98,7 +109,11 @@ namespace osu.Game.Overlays.BeatmapSet break; case MetadataType.Source: - loaded.AddLink(text, LinkAction.SearchBeatmapSet, text); + if (searchAction != null) + loaded.AddLink(text, () => searchAction(text)); + else + loaded.AddLink(text, LinkAction.SearchBeatmapSet, text); + break; default: diff --git a/osu.Game/Overlays/BeatmapSet/MetadataType.cs b/osu.Game/Overlays/BeatmapSet/MetadataType.cs index f992dca0ef..924e020641 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataType.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 0ae8a8bef5..06bf9e1d50 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index 82ca3e030f..47690bab1f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Screens.Select.Leaderboards; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index d1a0960a08..b83b4d6b26 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 86e72e9faa..c46c5cde43 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System.Collections.Generic; @@ -21,6 +23,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Localisation; using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics.Cursor; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.BeatmapSet.Scores @@ -36,8 +39,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly FillFlowContainer backgroundFlow; - private Color4 highAccuracyColour; - public ScoreTable() { RelativeSizeAxes = Axes.X; @@ -55,12 +56,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }); } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - highAccuracyColour = colours.GreenLight; - } - /// /// The statistics that appear in the table, in order of appearance. /// @@ -156,27 +151,20 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Current = scoreManager.GetBindableTotalScoreString(score), Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium) }, - new OsuSpriteText + new StatisticText(score.Accuracy, 1, showTooltip: false) { Margin = new MarginPadding { Right = horizontal_inset }, Text = score.DisplayAccuracy, - Font = OsuFont.GetFont(size: text_size), - Colour = score.Accuracy == 1 ? highAccuracyColour : Color4.White }, - new UpdateableFlag(score.User.Country) + new UpdateableFlag(score.User.CountryCode) { - Size = new Vector2(19, 13), - ShowPlaceholderOnNull = false, + Size = new Vector2(19, 14), + ShowPlaceholderOnUnknown = false, }, username, - new OsuSpriteText - { - Text = score.MaxCombo.ToLocalisableString(@"0\x"), - Font = OsuFont.GetFont(size: text_size), #pragma warning disable 618 - Colour = score.MaxCombo == score.BeatmapInfo.MaxCombo ? highAccuracyColour : Color4.White + new StatisticText(score.MaxCombo, score.BeatmapInfo.MaxCombo, @"0\x"), #pragma warning restore 618 - } }; var availableStatistics = score.GetStatisticsForDisplay().ToDictionary(tuple => tuple.Result); @@ -186,23 +174,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores if (!availableStatistics.TryGetValue(result.result, out var stat)) stat = new HitResultDisplayStatistic(result.result, 0, null, result.displayName); - content.Add(new OsuSpriteText - { - Text = stat.MaxCount == null ? stat.Count.ToLocalisableString(@"N0") : (LocalisableString)$"{stat.Count}/{stat.MaxCount}", - Font = OsuFont.GetFont(size: text_size), - Colour = stat.Count == 0 ? Color4.Gray : Color4.White - }); + content.Add(new StatisticText(stat.Count, stat.MaxCount, @"N0") { Colour = stat.Count == 0 ? Color4.Gray : Color4.White }); } if (showPerformancePoints) { Debug.Assert(score.PP != null); - - content.Add(new OsuSpriteText - { - Text = score.PP.ToLocalisableString(@"N0"), - Font = OsuFont.GetFont(size: text_size) - }); + content.Add(new StatisticText(score.PP.Value, format: @"N0")); } content.Add(new ScoreboardTime(score.Date, text_size) @@ -241,5 +219,31 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Colour = colourProvider.Foreground1; } } + + private class StatisticText : OsuSpriteText, IHasTooltip + { + private readonly double count; + private readonly double? maxCount; + private readonly bool showTooltip; + + public LocalisableString TooltipText => maxCount == null || !showTooltip ? string.Empty : $"{count}/{maxCount}"; + + public StatisticText(double count, double? maxCount = null, string format = null, bool showTooltip = true) + { + this.count = count; + this.maxCount = maxCount; + this.showTooltip = showTooltip; + + Text = count.ToLocalisableString(format); + Font = OsuFont.GetFont(size: text_size); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + if (count == maxCount) + Colour = colours.GreenLight; + } + } } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index b6079b36ab..c17bb70bc2 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs index 5018fb8c70..72aa221432 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Extensions; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 5f24a6549d..e50fc356eb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using System.Threading; @@ -85,7 +87,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores MD5Hash = apiBeatmap.MD5Hash }; - scoreManager.OrderByTotalScoreAsync(value.Scores.Select(s => s.CreateScoreInfo(rulesets, beatmapInfo)).ToArray(), loadCancellationSource.Token) + scoreManager.OrderByTotalScoreAsync(value.Scores.Select(s => s.ToScoreInfo(rulesets, beatmapInfo)).ToArray(), loadCancellationSource.Token) .ContinueWith(task => Schedule(() => { if (loadCancellationSource.IsCancellationRequested) @@ -99,7 +101,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores scoreTable.Show(); var userScore = value.UserScore; - var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets, beatmapInfo); + var userScoreInfo = userScore?.Score.ToScoreInfo(rulesets, beatmapInfo); topScoresContainer.Add(new DrawableTopScore(topScore)); @@ -215,7 +217,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores scope.BindValueChanged(_ => getScores()); ruleset.BindValueChanged(_ => getScores()); - modSelector.SelectedMods.CollectionChanged += (_, __) => getScores(); + modSelector.SelectedMods.CollectionChanged += (_, _) => getScores(); Beatmap.BindValueChanged(onBeatmapChanged); user.BindValueChanged(onUserChanged, true); @@ -242,8 +244,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores modSelector.DeselectAll(); else getScores(); - - modSelector.FadeTo(userIsSupporter ? 1 : 0); } private void getScores() @@ -260,7 +260,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; } - if (scope.Value != BeatmapLeaderboardScope.Global && !userIsSupporter) + if ((scope.Value != BeatmapLeaderboardScope.Global || modSelector.SelectedMods.Count > 0) && !userIsSupporter) { Scores = null; notSupporterPlaceholder.Show(); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index f528f54cdf..3b5ab811ae 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 5c3906cb39..2eaa03a05d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; @@ -116,9 +118,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Size = new Vector2(19, 13), + Size = new Vector2(19, 14), Margin = new MarginPadding { Top = 3 }, // makes spacing look more even - ShowPlaceholderOnNull = false, + ShowPlaceholderOnUnknown = false, }, } } @@ -139,7 +141,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores set { avatar.User = value.User; - flag.Country = value.User.Country; + flag.CountryCode = value.User.CountryCode; achievedOn.Date = value.Date; usernameText.Clear(); diff --git a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs index 9c5378a967..44b3acea5f 100644 --- a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs +++ b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs @@ -5,8 +5,6 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Resources.Localisation.Web; -#nullable enable - namespace osu.Game.Overlays.BeatmapSet { public class SpotlightBeatmapBadge : BeatmapBadge diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index fed3d7ddaa..cbcef9fcec 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index bd63c997df..823d0023cf 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index 0d383c374f..5b83f0e62e 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index c65eefdee4..575f1a398a 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Changelog/ChangelogContent.cs b/osu.Game/Overlays/Changelog/ChangelogContent.cs index 49dd9bb835..1e49efb10e 100644 --- a/osu.Game/Overlays/Changelog/ChangelogContent.cs +++ b/osu.Game/Overlays/Changelog/ChangelogContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Changelog/ChangelogEntry.cs b/osu.Game/Overlays/Changelog/ChangelogEntry.cs index da062ca617..fdeba3f304 100644 --- a/osu.Game/Overlays/Changelog/ChangelogEntry.cs +++ b/osu.Game/Overlays/Changelog/ChangelogEntry.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Net; using System.Text.RegularExpressions; diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 49a33ee5d6..6ce6b82c8f 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 9b74a8da6d..e848f26587 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs index 93486274fc..e4f240f0e7 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSingleBuild.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index e84eee15be..d84ed3c807 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs index aa36a5c8fd..1db2d2f172 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs index cb144defbf..974b283ccf 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Humanizer; using osu.Framework.Localisation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index ab97ae950d..7e0d5e9432 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Threading; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs index 47a2d234d1..b3814ca90c 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelList.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs index 9ab0c2792a..c18e9e11fa 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs index 65b9c4a79b..46d70b2d67 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemCloseButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs index 5018c8cd64..2ead841f58 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItemMentionPill.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs index 139c091f03..dee7730e2c 100644 --- a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs +++ b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 13f66089d9..4c425d3d4c 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -26,33 +26,6 @@ namespace osu.Game.Overlays.Chat { public class ChatLine : CompositeDrawable { - protected virtual float TextSize => 20; - - protected virtual float Spacing => 15; - - protected virtual float TimestampWidth => 60; - - protected virtual float UsernameWidth => 130; - - private Color4 usernameColour; - - private OsuSpriteText timestamp; - - public ChatLine(Message message) - { - Message = message; - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - } - - [Resolved(CanBeNull = true)] - private ChannelManager chatManager { get; set; } - - private Message message; - private OsuSpriteText username; - - public LinkFlowContainer ContentFlow { get; private set; } - public Message Message { get => message; @@ -69,13 +42,45 @@ namespace osu.Game.Overlays.Chat } } + public LinkFlowContainer ContentFlow { get; private set; } = null!; + + protected virtual float TextSize => 20; + + protected virtual float Spacing => 15; + + protected virtual float TimestampWidth => 60; + + protected virtual float UsernameWidth => 130; + + private Color4 usernameColour; + + private OsuSpriteText timestamp = null!; + + private Message message = null!; + + private OsuSpriteText username = null!; + + private Container? highlight; + private bool senderHasColour => !string.IsNullOrEmpty(message.Sender.Colour); + private bool messageHasColour => Message.IsAction && senderHasColour; + [Resolved] - private OsuColour colours { get; set; } + private ChannelManager? chatManager { get; set; } + + [Resolved] + private OsuColour colours { get; set; } = null!; + + public ChatLine(Message message) + { + Message = message; + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + } [BackgroundDependencyLoader] - private void load() + private void load(OverlayColourProvider? colourProvider) { usernameColour = senderHasColour ? Color4Extensions.FromHex(message.Sender.Colour) @@ -108,6 +113,7 @@ namespace osu.Game.Overlays.Chat Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), MaxWidth = TimestampWidth, + Colour = colourProvider?.Background1 ?? Colour4.White, }, new MessageSender(message.Sender) { @@ -123,16 +129,8 @@ namespace osu.Game.Overlays.Chat ContentFlow = new LinkFlowContainer(t => { t.Shadow = false; - - if (Message.IsAction) - { - t.Font = OsuFont.GetFont(italics: true); - - if (senderHasColour) - t.Colour = Color4Extensions.FromHex(message.Sender.Colour); - } - - t.Font = t.Font.With(size: TextSize); + t.Font = t.Font.With(size: TextSize, italics: Message.IsAction); + t.Colour = messageHasColour ? Color4Extensions.FromHex(message.Sender.Colour) : colourProvider?.Content1 ?? Colour4.White; }) { AutoSizeAxes = Axes.Y, @@ -151,8 +149,6 @@ namespace osu.Game.Overlays.Chat FinishTransforms(true); } - private Container highlight; - /// /// Performs a highlight animation on this . /// @@ -250,21 +246,25 @@ namespace osu.Game.Overlays.Chat { private readonly APIUser sender; - private Action startChatAction; + private Action startChatAction = null!; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; public MessageSender(APIUser sender) { this.sender = sender; } - [BackgroundDependencyLoader(true)] - private void load(UserProfileOverlay profile, ChannelManager chatManager) + [BackgroundDependencyLoader] + private void load(UserProfileOverlay? profile, ChannelManager? chatManager, ChatOverlay? chatOverlay) { Action = () => profile?.ShowUser(sender); - startChatAction = () => chatManager?.OpenPrivateChannel(sender); + startChatAction = () => + { + chatManager?.OpenPrivateChannel(sender); + chatOverlay?.Show(); + }; } public MenuItem[] ContextMenuItems diff --git a/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs b/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs index 79f22b51f7..ad9ae412da 100644 --- a/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs +++ b/osu.Game/Overlays/Chat/ChatOverlayTopBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Chat/ChatTextBar.cs b/osu.Game/Overlays/Chat/ChatTextBar.cs index 5100959eeb..73314c2e44 100644 --- a/osu.Game/Overlays/Chat/ChatTextBar.cs +++ b/osu.Game/Overlays/Chat/ChatTextBar.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Chat/ChatTextBox.cs b/osu.Game/Overlays/Chat/ChatTextBox.cs index 1ee0e8445f..ae8816b009 100644 --- a/osu.Game/Overlays/Chat/ChatTextBox.cs +++ b/osu.Game/Overlays/Chat/ChatTextBox.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Chat/DaySeparator.cs b/osu.Game/Overlays/Chat/DaySeparator.cs index 9ae35b0c38..be0b53785c 100644 --- a/osu.Game/Overlays/Chat/DaySeparator.cs +++ b/osu.Game/Overlays/Chat/DaySeparator.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -81,7 +80,7 @@ namespace osu.Game.Overlays.Chat { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Text = time.ToLocalTime().ToString("dd MMMM yyyy").ToUpper(), + Text = time.ToLocalTime().ToLocalisableString(@"dd MMMM yyyy").ToUpper(), Font = OsuFont.Torus.With(size: TextSize, weight: FontWeight.SemiBold), Colour = colourProvider?.Content1 ?? Colour4.White, }, diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index c3a341bca4..c05f456a96 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs index dbae091fb0..f0d39346e0 100644 --- a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs +++ b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Overlays/Chat/Listing/ChannelListing.cs b/osu.Game/Overlays/Chat/Listing/ChannelListing.cs index 8a5bc18cbf..44255eb754 100644 --- a/osu.Game/Overlays/Chat/Listing/ChannelListing.cs +++ b/osu.Game/Overlays/Chat/Listing/ChannelListing.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs b/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs index 2a21d30a4a..ffeab3b380 100644 --- a/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs +++ b/osu.Game/Overlays/Chat/Listing/ChannelListingItem.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index f04bf76c18..c491c0c695 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; @@ -20,6 +18,7 @@ using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; +using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat; using osu.Game.Overlays.Chat.ChannelList; @@ -102,23 +101,10 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.X, Height = top_bar_height, }, - channelList = new ChannelList - { - RelativeSizeAxes = Axes.Y, - Width = side_bar_width, - Padding = new MarginPadding { Top = top_bar_height }, - }, new Container { RelativeSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Padding = new MarginPadding - { - Top = top_bar_height, - Left = side_bar_width, - Bottom = chat_bar_height, - }, + Padding = new MarginPadding { Top = top_bar_height }, Children = new Drawable[] { new Box @@ -126,24 +112,50 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background4, }, - currentChannelContainer = new Container + new OnlineViewContainer("Sign in to chat") { RelativeSizeAxes = Axes.Both, - }, - loading = new LoadingLayer(true), - channelListing = new ChannelListing - { - RelativeSizeAxes = Axes.Both, - }, - }, - }, - textBar = new ChatTextBar - { - RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Padding = new MarginPadding { Left = side_bar_width }, - }, + Children = new Drawable[] + { + channelList = new ChannelList + { + RelativeSizeAxes = Axes.Y, + Width = side_bar_width, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Padding = new MarginPadding + { + Left = side_bar_width, + Bottom = chat_bar_height, + }, + Children = new Drawable[] + { + currentChannelContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, + loading = new LoadingLayer(true), + channelListing = new ChannelListing + { + RelativeSizeAxes = Axes.Both, + }, + }, + }, + textBar = new ChatTextBar + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Padding = new MarginPadding { Left = side_bar_width }, + }, + } + } + } + } }; } diff --git a/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs b/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs index 48f34e8f59..46a455cbb3 100644 --- a/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.Containers; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs index 2f7f16dd6f..d24a0cd27b 100644 --- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs index 4bb5b9d66d..42aca2f4a3 100644 --- a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs index 4908e29b7d..6f3841d52e 100644 --- a/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ShowMoreRepliesButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs index 04e7e25cc5..845a630d97 100644 --- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Humanizer; using osu.Framework.Bindables; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/Comments/CancellableCommentEditor.cs b/osu.Game/Overlays/Comments/CancellableCommentEditor.cs index 74c221bd82..853171ea4a 100644 --- a/osu.Game/Overlays/Comments/CancellableCommentEditor.cs +++ b/osu.Game/Overlays/Comments/CancellableCommentEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 3ff4cfad4a..e2a7e78356 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; @@ -115,7 +117,7 @@ namespace osu.Game.Overlays.Comments } }); - textBox.OnCommit += (u, v) => + textBox.OnCommit += (_, _) => { if (commitButton.IsBlocked.Value) return; diff --git a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs index 3971a61363..e94a1b0147 100644 --- a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs +++ b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax; using Markdig.Syntax.Inlines; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index a28b13fc12..4a836e0e62 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Online.API; @@ -249,8 +251,8 @@ namespace osu.Game.Overlays.Comments if (bundle.HasMore) { int loadedTopLevelComments = 0; - pinnedContent.Children.OfType().ForEach(p => loadedTopLevelComments++); - content.Children.OfType().ForEach(p => loadedTopLevelComments++); + pinnedContent.Children.OfType().ForEach(_ => loadedTopLevelComments++); + content.Children.OfType().ForEach(_ => loadedTopLevelComments++); moreButton.Current.Value = bundle.TopLevelCount - loadedTopLevelComments; moreButton.IsLoading = false; diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index e7d9e72dcc..5684841c37 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs index b1ca39c3bf..84d1f67486 100644 --- a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs +++ b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs b/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs index 8c40d79f7a..2c7ed4f5b3 100644 --- a/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 3ec91c8e63..296320ec1b 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs index 65172aa57c..186b892c4d 100644 --- a/osu.Game/Overlays/Comments/HeaderButton.cs +++ b/osu.Game/Overlays/Comments/HeaderButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index 221a745189..218d8383f6 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 093cdce66e..7a4b83cc48 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index 23f67a06cb..aae4932c22 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 2c8db14950..370181a0cb 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs index 765f037d70..bfd356193d 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; @@ -143,7 +145,7 @@ namespace osu.Game.Overlays.Dashboard.Friends controlBackground.Colour = colourProvider.Background5; apiFriends.BindTo(api.Friends); - apiFriends.BindCollectionChanged((_, __) => Schedule(() => Users = apiFriends.ToList()), true); + apiFriends.BindCollectionChanged((_, _) => Schedule(() => Users = apiFriends.ToList()), true); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs b/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs index 7275cdff7c..fc6158e747 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendOnlineStreamControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs b/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs index 4abece9a8d..3bb42ec953 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Overlays.Dashboard.Friends { public class FriendStream diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs index 11dcb93e6f..7e2ec3f442 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs index 853c94d8ae..21bc5b8203 100644 --- a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs +++ b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs b/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs index fb4b938183..25ddb9e704 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; diff --git a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs index 7fee5f4668..466e36c1a9 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs index c781aa0cfb..e9c7af3339 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs index 9276e6ce80..1e4ba2ef05 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs index 249b355be3..258fd56dd7 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs index 4e50cce890..743bd5440f 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs index 382bc00b1d..8f140facef 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs index 331fff0aea..c6917b41fb 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs index 154813dea1..9ff12623e0 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Dashboard/Home/HomePanel.cs b/osu.Game/Overlays/Dashboard/Home/HomePanel.cs index ce053cd4ec..099e16cd55 100644 --- a/osu.Game/Overlays/Dashboard/Home/HomePanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/HomePanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs index 0d166eb858..8f5c942b6e 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs index 77cfbc90b0..9b66e5524b 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs index c1d5a87ef5..4456a292a5 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs index d6a3a69fe0..e384c3e6e5 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs index f6e966957e..9b1d77a8c2 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/ShowMoreNewsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/DashboardOverlay.cs b/osu.Game/Overlays/DashboardOverlay.cs index 79d972bdcc..d919022dbb 100644 --- a/osu.Game/Overlays/DashboardOverlay.cs +++ b/osu.Game/Overlays/DashboardOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Overlays.Dashboard; using osu.Game.Overlays.Dashboard.Friends; diff --git a/osu.Game/Overlays/Dialog/ConfirmDialog.cs b/osu.Game/Overlays/Dialog/ConfirmDialog.cs index 58ce84e13a..8be865ee16 100644 --- a/osu.Game/Overlays/Dialog/ConfirmDialog.cs +++ b/osu.Game/Overlays/Dialog/ConfirmDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 5959fe656c..864120cc49 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Dialog/PopupDialogButton.cs b/osu.Game/Overlays/Dialog/PopupDialogButton.cs index 76ee438d6d..e1cc31da82 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.UserInterface; @@ -8,7 +10,8 @@ namespace osu.Game.Overlays.Dialog { public class PopupDialogButton : DialogButton { - public PopupDialogButton() + public PopupDialogButton(HoverSampleSet sampleSet = HoverSampleSet.Button) + : base(sampleSet) { Height = 50; BackgroundColour = Color4Extensions.FromHex(@"150e14"); diff --git a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs index 754003c1c1..f23a40b7ab 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Dialog { @@ -13,5 +16,10 @@ namespace osu.Game.Overlays.Dialog { ButtonColour = colours.Blue; } + + public PopupDialogCancelButton() + : base(HoverSampleSet.DialogCancel) + { + } } } diff --git a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs index 6239c5e409..bd7cb4ed33 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogDangerousButton.cs @@ -1,10 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osu.Game.Audio.Effects; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -47,6 +53,33 @@ namespace osu.Game.Overlays.Dialog { } + private Sample tickSample; + private Sample confirmSample; + private double lastTickPlaybackTime; + private AudioFilter lowPassFilter = null!; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + tickSample = audio.Samples.Get(@"UI/dialog-dangerous-tick"); + confirmSample = audio.Samples.Get(@"UI/dialog-dangerous-select"); + + AddInternal(lowPassFilter = new AudioFilter(audio.SampleMixer)); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Progress.BindValueChanged(progressChanged); + } + + protected override void Confirm() + { + lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); + confirmSample?.Play(); + base.Confirm(); + } + protected override bool OnMouseDown(MouseDownEvent e) { BeginConfirm(); @@ -56,7 +89,28 @@ namespace osu.Game.Overlays.Dialog protected override void OnMouseUp(MouseUpEvent e) { if (!e.HasAnyButtonPressed) + { + lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF); AbortConfirm(); + } + } + + private void progressChanged(ValueChangedEvent progress) + { + if (progress.NewValue < progress.OldValue) return; + + if (Clock.CurrentTime - lastTickPlaybackTime < 30) return; + + lowPassFilter.CutoffTo((int)(progress.NewValue * AudioFilter.MAX_LOWPASS_CUTOFF * 0.5)); + + var channel = tickSample.GetChannel(); + + channel.Frequency.Value = 1 + progress.NewValue * 0.5f; + channel.Volume.Value = 0.5f + progress.NewValue / 2f; + + channel.Play(); + + lastTickPlaybackTime = Clock.CurrentTime; } } } diff --git a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs index 6c2bf6f1e6..3496627c89 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Dialog { @@ -13,5 +16,10 @@ namespace osu.Game.Overlays.Dialog { ButtonColour = colours.Pink; } + + public PopupDialogOkButton() + : base(HoverSampleSet.DialogOk) + { + } } } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 5a69562e82..493cd66258 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Dialog; @@ -47,43 +49,54 @@ namespace osu.Game.Overlays public void Push(PopupDialog dialog) { - if (dialog == CurrentDialog || dialog.State.Value != Visibility.Visible) return; - - var lastDialog = CurrentDialog; + if (dialog == CurrentDialog || dialog.State.Value == Visibility.Hidden) return; // Immediately update the externally accessible property as this may be used for checks even before // a DialogOverlay instance has finished loading. + var lastDialog = CurrentDialog; CurrentDialog = dialog; - Scheduler.Add(() => + Schedule(() => { // if any existing dialog is being displayed, dismiss it before showing a new one. lastDialog?.Hide(); - dialog.State.ValueChanged += state => onDialogOnStateChanged(dialog, state.NewValue); - dialogContainer.Add(dialog); + // if the new dialog is hidden before added to the dialogContainer, bypass any further operations. + if (dialog.State.Value == Visibility.Hidden) + { + dismiss(); + return; + } + + dialogContainer.Add(dialog); Show(); - }, false); + + dialog.State.BindValueChanged(state => + { + if (state.NewValue != Visibility.Hidden) return; + + // Trigger the demise of the dialog as soon as it hides. + dialog.Delay(PopupDialog.EXIT_DURATION).Expire(); + + dismiss(); + }); + }); + + void dismiss() + { + if (dialog != CurrentDialog) return; + + // Handle the case where the dialog is the currently displayed dialog. + // In this scenario, the overlay itself should also be hidden. + Hide(); + CurrentDialog = null; + } } public override bool IsPresent => Scheduler.HasPendingTasks || dialogContainer.Children.Count > 0; protected override bool BlockNonPositionalInput => true; - private void onDialogOnStateChanged(VisibilityContainer dialog, Visibility v) - { - if (v != Visibility.Hidden) return; - - // handle the dialog being dismissed. - dialog.Delay(PopupDialog.EXIT_DURATION).Expire(); - - if (dialog == CurrentDialog) - { - Hide(); - CurrentDialog = null; - } - } - protected override void PopIn() { base.PopIn(); @@ -95,7 +108,8 @@ namespace osu.Game.Overlays base.PopOut(); lowPassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF, 100, Easing.InCubic); - if (CurrentDialog?.State.Value == Visibility.Visible) + // PopOut gets called initially, but we only want to hide dialog when we have been loaded and are present. + if (IsLoaded && CurrentDialog?.State.Value == Visibility.Visible) CurrentDialog.Hide(); } diff --git a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs index b043f05bd8..cef1f1c869 100644 --- a/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs +++ b/osu.Game/Overlays/FirstRunSetup/FirstRunSetupScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs b/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs index ee2db1f3d4..95ebb256c4 100644 --- a/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs +++ b/osu.Game/Overlays/FirstRunSetup/ProgressRoundedButton.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs index ddcee7c040..82f49e0aef 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBeatmaps.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs index 1a88e6a842..9573b4859f 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenBehaviour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index 62b517d982..43d68653ad 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs index f09a26a527..58bfced3ed 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenUIScale.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs index 420d630857..cb1e96d2f2 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs @@ -1,12 +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.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Configuration; +using osu.Framework.Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; using osu.Framework.Localisation; +using osu.Framework.Threading; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Localisation; +using osuTK; namespace osu.Game.Overlays.FirstRunSetup { @@ -18,13 +30,175 @@ namespace osu.Game.Overlays.FirstRunSetup { Content.Children = new Drawable[] { - new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: CONTENT_FONT_SIZE)) + new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + RowDimensions = new[] + { + // Avoid height changes when changing language. + new Dimension(GridSizeMode.AutoSize, minSize: 100), + }, + Content = new[] + { + new Drawable[] + { + new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: CONTENT_FONT_SIZE)) + { + Text = FirstRunSetupOverlayStrings.WelcomeDescription, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }, + }, + } + }, + new LanguageSelectionFlow { - Text = FirstRunSetupOverlayStrings.WelcomeDescription, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y - }, + } }; } + + private class LanguageSelectionFlow : FillFlowContainer + { + private Bindable frameworkLocale = null!; + + private ScheduledDelegate? updateSelectedDelegate; + + [BackgroundDependencyLoader] + private void load(FrameworkConfigManager frameworkConfig) + { + Direction = FillDirection.Full; + Spacing = new Vector2(5); + + ChildrenEnumerable = Enum.GetValues(typeof(Language)) + .Cast() + .Select(l => new LanguageButton(l) + { + Action = () => frameworkLocale.Value = l.ToCultureCode() + }); + + frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); + frameworkLocale.BindValueChanged(locale => + { + if (!LanguageExtensions.TryParseCultureCode(locale.NewValue, out var language)) + language = Language.en; + + // Changing language may cause a short period of blocking the UI thread while the new glyphs are loaded. + // Scheduling ensures the button animation plays smoothly after any blocking operation completes. + // Note that a delay is required (the alternative would be a double-schedule; delay feels better). + updateSelectedDelegate?.Cancel(); + updateSelectedDelegate = Scheduler.AddDelayed(() => updateSelectedStates(language), 50); + }, true); + } + + private void updateSelectedStates(Language language) + { + foreach (var c in Children.OfType()) + c.Selected = c.Language == language; + } + + private class LanguageButton : OsuClickableContainer + { + public readonly Language Language; + + private Box backgroundBox = null!; + + private OsuSpriteText text = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + private bool selected; + + public bool Selected + { + get => selected; + set + { + if (selected == value) + return; + + selected = value; + + if (IsLoaded) + updateState(); + } + } + + public LanguageButton(Language language) + { + Language = language; + + Size = new Vector2(160, 50); + Masking = true; + CornerRadius = 10; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + backgroundBox = new Box + { + Alpha = 0, + Colour = colourProvider.Background5, + RelativeSizeAxes = Axes.Both, + }, + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = colourProvider.Light1, + Text = Language.GetDescription(), + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + } + + protected override bool OnHover(HoverEvent e) + { + if (!selected) + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (!selected) + updateState(); + base.OnHoverLost(e); + } + + private void updateState() + { + if (selected) + { + const double selected_duration = 1000; + + backgroundBox.FadeTo(1, selected_duration, Easing.OutQuint); + backgroundBox.FadeColour(colourProvider.Background2, selected_duration, Easing.OutQuint); + text.FadeColour(colourProvider.Content1, selected_duration, Easing.OutQuint); + text.ScaleTo(1.2f, selected_duration, Easing.OutQuint); + } + else + { + const double duration = 500; + + backgroundBox.FadeTo(IsHovered ? 1 : 0, duration, Easing.OutQuint); + backgroundBox.FadeColour(colourProvider.Background5, duration, Easing.OutQuint); + text.FadeColour(colourProvider.Light1, duration, Easing.OutQuint); + text.ScaleTo(1, duration, Easing.OutQuint); + } + } + } + } } } diff --git a/osu.Game/Overlays/FirstRunSetupOverlay.cs b/osu.Game/Overlays/FirstRunSetupOverlay.cs index a5bece0832..8c9ca7e35b 100644 --- a/osu.Game/Overlays/FirstRunSetupOverlay.cs +++ b/osu.Game/Overlays/FirstRunSetupOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 58c41c4a4b..63a9ebc750 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index cb6275bd7c..dd03206eab 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/IDialogOverlay.cs b/osu.Game/Overlays/IDialogOverlay.cs index 1c6a84cd64..6ddb71d5e3 100644 --- a/osu.Game/Overlays/IDialogOverlay.cs +++ b/osu.Game/Overlays/IDialogOverlay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Overlays/INamedOverlayComponent.cs b/osu.Game/Overlays/INamedOverlayComponent.cs index ca0aea041e..e9d01a55e3 100644 --- a/osu.Game/Overlays/INamedOverlayComponent.cs +++ b/osu.Game/Overlays/INamedOverlayComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; namespace osu.Game.Overlays diff --git a/osu.Game/Overlays/INotificationOverlay.cs b/osu.Game/Overlays/INotificationOverlay.cs index 1d8e33ea3a..b9ac466229 100644 --- a/osu.Game/Overlays/INotificationOverlay.cs +++ b/osu.Game/Overlays/INotificationOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Overlays.Notifications; diff --git a/osu.Game/Overlays/IOverlayManager.cs b/osu.Game/Overlays/IOverlayManager.cs index 940ee2d8db..0318b2b3a0 100644 --- a/osu.Game/Overlays/IOverlayManager.cs +++ b/osu.Game/Overlays/IOverlayManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 502f0cd22e..0042f4607d 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -21,19 +21,19 @@ namespace osu.Game.Overlays.Login { public class LoginForm : FillFlowContainer { - private TextBox username; - private TextBox password; - private ShakeContainer shakeSignIn; + private TextBox username = null!; + private TextBox password = null!; + private ShakeContainer shakeSignIn = null!; - [Resolved(CanBeNull = true)] - private IAPIProvider api { get; set; } + [Resolved] + private IAPIProvider api { get; set; } = null!; - public Action RequestHide; + public Action? RequestHide; private void performLogin() { if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) - api?.Login(username.Text, password.Text); + api.Login(username.Text, password.Text); else shakeSignIn.Shake(); } @@ -47,6 +47,7 @@ namespace osu.Game.Overlays.Login RelativeSizeAxes = Axes.X; ErrorTextFlowContainer errorText; + LinkFlowContainer forgottenPaswordLink; Children = new Drawable[] { @@ -54,7 +55,7 @@ namespace osu.Game.Overlays.Login { PlaceholderText = UsersStrings.LoginUsername.ToLower(), RelativeSizeAxes = Axes.X, - Text = api?.ProvidedUsername ?? string.Empty, + Text = api.ProvidedUsername, TabbableContentContainer = this }, password = new OsuPasswordTextBox @@ -78,6 +79,12 @@ namespace osu.Game.Overlays.Login LabelText = "Stay signed in", Current = config.GetBindable(OsuSetting.SavePassword), }, + forgottenPaswordLink = new LinkFlowContainer + { + Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, new Container { RelativeSizeAxes = Axes.X, @@ -101,15 +108,17 @@ namespace osu.Game.Overlays.Login Text = "Register", Action = () => { - RequestHide(); + RequestHide?.Invoke(); accountCreation.Show(); } } }; - password.OnCommit += (sender, newText) => performLogin(); + forgottenPaswordLink.AddLink(LayoutStrings.PopupLoginLoginForgot, $"{api.WebsiteRootUrl}/home/password-reset"); - if (api?.LastLoginError?.Message is string error) + password.OnCommit += (_, _) => performLogin(); + + if (api.LastLoginError?.Message is string error) errorText.AddErrors(new[] { error }); } diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 481abd48ab..1d8926b991 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Login/UserAction.cs b/osu.Game/Overlays/Login/UserAction.cs index d216670a28..7a18e38109 100644 --- a/osu.Game/Overlays/Login/UserAction.cs +++ b/osu.Game/Overlays/Login/UserAction.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -21,4 +23,4 @@ namespace osu.Game.Overlays.Login [Description(@"Sign out")] SignOut, } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index 5c3a41aec9..73ccfb3443 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index 9b2d7ca1ee..2362b2ad88 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index e15625a4b3..9b856014f9 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 3cf7befb45..1c007c913e 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osuTK; @@ -110,7 +112,7 @@ namespace osu.Game.Overlays.MedalSplash s.Font = s.Font.With(size: 16); }); - medalContainer.OnLoadComplete += d => + medalContainer.OnLoadComplete += _ => { unlocked.Position = new Vector2(0f, medalContainer.DrawSize.Y / 2 + 10); infoFlow.Position = new Vector2(0f, unlocked.Position.Y + 90); diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index 8288d34c95..61fca9e091 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs index 4ccec0dd87..c8d55c213a 100644 --- a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs +++ b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs index 34c4458a21..8cedd6b374 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -44,8 +46,8 @@ namespace osu.Game.Overlays.Mods && !ModUtils.CheckCompatibleSet(selectedMods.Value.Append(Mod)); } - protected override Colour4 BackgroundColour => incompatible.Value ? (Colour4)ColourProvider.Background6 : base.BackgroundColour; - protected override Colour4 ForegroundColour => incompatible.Value ? (Colour4)ColourProvider.Background5 : base.ForegroundColour; + protected override Colour4 BackgroundColour => incompatible.Value ? ColourProvider.Background6 : base.BackgroundColour; + protected override Colour4 ForegroundColour => incompatible.Value ? ColourProvider.Background5 : base.ForegroundColour; protected override void UpdateState() { diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs index d8117c8f00..3f44e82d50 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs new file mode 100644 index 0000000000..4f3c18fc43 --- /dev/null +++ b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Mods; +using osuTK.Input; + +namespace osu.Game.Overlays.Mods.Input +{ + /// + /// Uses bindings from stable 1:1. + /// + public class ClassicModHotkeyHandler : IModHotkeyHandler + { + private static readonly Dictionary mod_type_lookup = new Dictionary + { + [Key.Q] = new[] { typeof(ModEasy) }, + [Key.W] = new[] { typeof(ModNoFail) }, + [Key.E] = new[] { typeof(ModHalfTime) }, + [Key.A] = new[] { typeof(ModHardRock) }, + [Key.S] = new[] { typeof(ModSuddenDeath), typeof(ModPerfect) }, + [Key.D] = new[] { typeof(ModDoubleTime), typeof(ModNightcore) }, + [Key.F] = new[] { typeof(ModHidden) }, + [Key.G] = new[] { typeof(ModFlashlight) }, + [Key.Z] = new[] { typeof(ModRelax) }, + [Key.V] = new[] { typeof(ModAutoplay), typeof(ModCinema) } + }; + + private readonly bool allowIncompatibleSelection; + + public ClassicModHotkeyHandler(bool allowIncompatibleSelection) + { + this.allowIncompatibleSelection = allowIncompatibleSelection; + } + + public bool HandleHotkeyPressed(KeyDownEvent e, IEnumerable availableMods) + { + if (!mod_type_lookup.TryGetValue(e.Key, out var typesToMatch)) + return false; + + var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && !modState.Filtered.Value).ToArray(); + + if (matchingMods.Length == 0) + return false; + + if (matchingMods.Length == 1) + { + matchingMods.Single().Active.Toggle(); + return true; + } + + if (allowIncompatibleSelection) + { + // easier path - multiple incompatible mods can be active at a time. + // this is used in the free mod select overlay. + // in this case, just toggle everything. + bool anyActive = matchingMods.Any(mod => mod.Active.Value); + foreach (var mod in matchingMods) + mod.Active.Value = !anyActive; + return true; + } + + // we now know there are multiple possible mods to handle, and only one of them can be active at a time. + // let's make sure of this just in case. + Debug.Assert(matchingMods.Count(modState => modState.Active.Value) <= 1); + int currentSelectedIndex = Array.FindIndex(matchingMods, modState => modState.Active.Value); + + // `FindIndex` will return -1 if it doesn't find the item. + // this is convenient in the forward direction, since if we add 1 then we'll end up at the first item, + // but less so in the backwards direction. + // for convenience, detect this situation and set the index to one index past the last item. + // this makes it so that if we subtract 1 then we'll end up at the last item again. + if (currentSelectedIndex < 0 && e.ShiftPressed) + currentSelectedIndex = matchingMods.Length; + + int indexToSelect = e.ShiftPressed ? currentSelectedIndex - 1 : currentSelectedIndex + 1; + + // `currentSelectedIndex` and `indexToSelect` can both be equal to -1 or `matchingMods.Length`. + // if the former is beyond array range, it means nothing was previously selected and so there's nothing to deselect. + // if the latter is beyond array range, it means that either the previous selection was first and we're going backwards, + // or it was last and we're going forwards. + // in either case there is nothing to select. + if (currentSelectedIndex >= 0 && currentSelectedIndex <= matchingMods.Length - 1) + matchingMods[currentSelectedIndex].Active.Value = false; + if (indexToSelect >= 0 && indexToSelect <= matchingMods.Length - 1) + matchingMods[indexToSelect].Active.Value = true; + + return true; + } + + private static bool matches(ModState modState, Type[] typesToMatch) + => typesToMatch.Any(typeToMatch => typeToMatch.IsInstanceOfType(modState.Mod)); + } +} diff --git a/osu.Game/Overlays/Mods/Input/IModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/IModHotkeyHandler.cs new file mode 100644 index 0000000000..d2cc0e84d2 --- /dev/null +++ b/osu.Game/Overlays/Mods/Input/IModHotkeyHandler.cs @@ -0,0 +1,22 @@ +// 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.Events; + +namespace osu.Game.Overlays.Mods.Input +{ + /// + /// Encapsulates strategies of handling mod hotkeys on the . + /// + public interface IModHotkeyHandler + { + /// + /// Attempt to handle the supplied as a selection of one of the mods in . + /// + /// The event representing the user's keypress. + /// The list of currently available mods. + /// Whether the supplied event was handled as a mod selection/deselection. + bool HandleHotkeyPressed(KeyDownEvent e, IEnumerable availableMods); + } +} diff --git a/osu.Game/Overlays/Mods/Input/ModSelectHotkeyStyle.cs b/osu.Game/Overlays/Mods/Input/ModSelectHotkeyStyle.cs new file mode 100644 index 0000000000..6375b37f8b --- /dev/null +++ b/osu.Game/Overlays/Mods/Input/ModSelectHotkeyStyle.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 osu.Game.Rulesets.Mods; + +namespace osu.Game.Overlays.Mods.Input +{ + /// + /// The style of hotkey handling to use on the mod select screen. + /// + public enum ModSelectHotkeyStyle + { + /// + /// Each letter row on the keyboard controls one of the three first s. + /// Individual letters in a row trigger the mods in a sequential fashion. + /// Uses . + /// + Sequential, + + /// + /// Matches keybindings from stable 1:1. + /// One keybinding can toggle between what used to be s on stable, + /// and some mods in a column may not have any hotkeys at all. + /// + Classic + } +} diff --git a/osu.Game/Overlays/Mods/Input/NoopModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/NoopModHotkeyHandler.cs new file mode 100644 index 0000000000..3f7a6298a1 --- /dev/null +++ b/osu.Game/Overlays/Mods/Input/NoopModHotkeyHandler.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 System.Collections.Generic; +using osu.Framework.Input.Events; + +namespace osu.Game.Overlays.Mods.Input +{ + /// + /// A no-op implementation of . + /// Used when a column is not handling any hotkeys at all. + /// + public class NoopModHotkeyHandler : IModHotkeyHandler + { + public bool HandleHotkeyPressed(KeyDownEvent e, IEnumerable availableMods) => false; + } +} diff --git a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs new file mode 100644 index 0000000000..dedb556304 --- /dev/null +++ b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs @@ -0,0 +1,59 @@ +// Copyright (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.Input.Events; +using osu.Game.Rulesets.Mods; +using osuTK.Input; + +namespace osu.Game.Overlays.Mods.Input +{ + /// + /// This implementation of receives a sequence of s, + /// and maps the sequence of keys onto the items it is provided in . + /// In this case, particular mods are not bound to particular keys, the hotkeys are a byproduct of mod ordering. + /// + public class SequentialModHotkeyHandler : IModHotkeyHandler + { + public static SequentialModHotkeyHandler Create(ModType modType) + { + switch (modType) + { + case ModType.DifficultyReduction: + return new SequentialModHotkeyHandler(new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }); + + case ModType.DifficultyIncrease: + return new SequentialModHotkeyHandler(new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L }); + + case ModType.Automation: + return new SequentialModHotkeyHandler(new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M }); + + default: + throw new ArgumentOutOfRangeException(nameof(modType), modType, $"Cannot create {nameof(SequentialModHotkeyHandler)} for provided mod type"); + } + } + + private readonly Key[] toggleKeys; + + private SequentialModHotkeyHandler(Key[] keys) + { + toggleKeys = keys; + } + + public bool HandleHotkeyPressed(KeyDownEvent e, IEnumerable availableMods) + { + int index = Array.IndexOf(toggleKeys, e.Key); + if (index < 0) + return false; + + var modState = availableMods.Where(modState => !modState.Filtered.Value).ElementAtOrDefault(index); + if (modState == null) + return false; + + modState.Active.Toggle(); + return true; + } + } +} diff --git a/osu.Game/Overlays/Mods/ModButtonTooltip.cs b/osu.Game/Overlays/Mods/ModButtonTooltip.cs index 2f50e38a5a..e19f24103f 100644 --- a/osu.Game/Overlays/Mods/ModButtonTooltip.cs +++ b/osu.Game/Overlays/Mods/ModButtonTooltip.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 42f9daec4d..3f788d10e3 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; @@ -19,14 +17,15 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; +using osu.Game.Overlays.Mods.Input; using osu.Game.Rulesets.Mods; using osuTK; using osuTK.Graphics; -using osuTK.Input; namespace osu.Game.Overlays.Mods { @@ -72,7 +71,7 @@ namespace osu.Game.Overlays.Mods protected virtual ModPanel CreateModPanel(ModState mod) => new ModPanel(mod); - private readonly Key[]? toggleKeys; + private readonly bool allowIncompatibleSelection; private readonly TextFlowContainer headerText; private readonly Box headerBackground; @@ -83,15 +82,18 @@ namespace osu.Game.Overlays.Mods private Colour4 accentColour; + private Bindable hotkeyStyle = null!; + private IModHotkeyHandler hotkeyHandler = null!; + private Task? latestLoadTask; internal bool ItemsLoaded => latestLoadTask == null; private const float header_height = 42; - public ModColumn(ModType modType, bool allowBulkSelection, Key[]? toggleKeys = null) + public ModColumn(ModType modType, bool allowIncompatibleSelection) { ModType = modType; - this.toggleKeys = toggleKeys; + this.allowIncompatibleSelection = allowIncompatibleSelection; Width = 320; RelativeSizeAxes = Axes.Y; @@ -199,7 +201,7 @@ namespace osu.Game.Overlays.Mods createHeaderText(); - if (allowBulkSelection) + if (allowIncompatibleSelection) { controlContainer.Height = 35; controlContainer.Add(toggleAllCheckbox = new ToggleAllCheckbox(this) @@ -233,7 +235,7 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, OsuColour colours) + private void load(OverlayColourProvider colourProvider, OsuColour colours, OsuConfigManager configManager) { headerBackground.Colour = accentColour = colours.ForModType(ModType); @@ -245,6 +247,8 @@ namespace osu.Game.Overlays.Mods contentContainer.BorderColour = ColourInfo.GradientVertical(colourProvider.Background4, colourProvider.Background3); contentBackground.Colour = colourProvider.Background4; + + hotkeyStyle = configManager.GetBindable(OsuSetting.ModSelectHotkeyStyle); } protected override void LoadComplete() @@ -252,6 +256,7 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); toggleAllCheckbox?.Current.BindValueChanged(_ => updateToggleAllText(), true); + hotkeyStyle.BindValueChanged(val => hotkeyHandler = createHotkeyHandler(val.NewValue), true); asyncLoadPanels(); } @@ -425,19 +430,32 @@ namespace osu.Game.Overlays.Mods #region Keyboard selection support + /// + /// Creates an appropriate for this column's and + /// the supplied . + /// + private IModHotkeyHandler createHotkeyHandler(ModSelectHotkeyStyle hotkeyStyle) + { + switch (ModType) + { + case ModType.DifficultyReduction: + case ModType.DifficultyIncrease: + case ModType.Automation: + return hotkeyStyle == ModSelectHotkeyStyle.Sequential + ? SequentialModHotkeyHandler.Create(ModType) + : new ClassicModHotkeyHandler(allowIncompatibleSelection); + + default: + return new NoopModHotkeyHandler(); + } + } + protected override bool OnKeyDown(KeyDownEvent e) { - if (e.ControlPressed || e.AltPressed || e.SuperPressed) return false; - if (toggleKeys == null) return false; + if (e.ControlPressed || e.AltPressed || e.SuperPressed || e.Repeat) + return false; - int index = Array.IndexOf(toggleKeys, e.Key); - if (index < 0) return false; - - var modState = availableMods.ElementAtOrDefault(index); - if (modState == null || modState.Filtered.Value) return false; - - modState.Active.Toggle(); - return true; + return hotkeyHandler.HandleHotkeyPressed(e, availableMods); } #endregion diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 358bdd3202..02eb395bd9 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -218,9 +216,9 @@ namespace osu.Game.Overlays.Mods base.OnMouseUp(e); } - protected virtual Colour4 BackgroundColour => Active.Value ? activeColour.Darken(0.3f) : (Colour4)ColourProvider.Background3; - protected virtual Colour4 ForegroundColour => Active.Value ? activeColour : (Colour4)ColourProvider.Background2; - protected virtual Colour4 TextColour => Active.Value ? (Colour4)ColourProvider.Background6 : Colour4.White; + protected virtual Colour4 BackgroundColour => Active.Value ? activeColour.Darken(0.3f) : ColourProvider.Background3; + protected virtual Colour4 ForegroundColour => Active.Value ? activeColour : ColourProvider.Background2; + protected virtual Colour4 TextColour => Active.Value ? ColourProvider.Background6 : Colour4.White; protected virtual void UpdateState() { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 4bad34d94f..afc6775e83 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -1,13 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,7 +23,6 @@ using osu.Game.Localisation; using osu.Game.Rulesets.Mods; using osu.Game.Utils; using osuTK; -using osuTK.Input; namespace osu.Game.Overlays.Mods { @@ -31,6 +30,9 @@ namespace osu.Game.Overlays.Mods { public const int BUTTON_WIDTH = 200; + protected override string PopInSampleName => ""; + protected override string PopOutSampleName => @"SongSelect/mod-select-overlay-pop-out"; + [Cached] public Bindable> SelectedMods { get; private set; } = new Bindable>(Array.Empty()); @@ -43,7 +45,7 @@ namespace osu.Game.Overlays.Mods /// public Bindable>> AvailableMods { get; } = new Bindable>>(new Dictionary>()); - private Func isValidMod = m => true; + private Func isValidMod = _ => true; /// /// A function determining whether each mod in the column should be displayed. @@ -70,7 +72,7 @@ namespace osu.Game.Overlays.Mods /// protected virtual bool AllowCustomisation => true; - protected virtual ModColumn CreateModColumn(ModType modType, Key[]? toggleKeys = null) => new ModColumn(modType, false, toggleKeys); + protected virtual ModColumn CreateModColumn(ModType modType) => new ModColumn(modType, false); protected virtual IReadOnlyList ComputeNewModsFromSelection(IReadOnlyList oldSelection, IReadOnlyList newSelection) => newSelection; @@ -104,17 +106,21 @@ namespace osu.Game.Overlays.Mods private ShearedToggleButton? customisationButton; + private Sample? columnAppearSample; + protected ModSelectOverlay(OverlayColourScheme colourScheme = OverlayColourScheme.Green) : base(colourScheme) { } [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours) + private void load(OsuGameBase game, OsuColour colours, AudioManager audio) { Header.Title = ModSelectOverlayStrings.ModSelectTitle; Header.Description = ModSelectOverlayStrings.ModSelectDescription; + columnAppearSample = audio.Samples.Get(@"SongSelect/mod-column-pop-in"); + AddRange(new Drawable[] { new ClickToReturnContainer @@ -162,9 +168,9 @@ namespace osu.Game.Overlays.Mods Padding = new MarginPadding { Bottom = 10 }, Children = new[] { - createModColumnContent(ModType.DifficultyReduction, new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }), - createModColumnContent(ModType.DifficultyIncrease, new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L }), - createModColumnContent(ModType.Automation, new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M }), + createModColumnContent(ModType.DifficultyReduction), + createModColumnContent(ModType.DifficultyIncrease), + createModColumnContent(ModType.Automation), createModColumnContent(ModType.Conversion), createModColumnContent(ModType.Fun) } @@ -216,6 +222,8 @@ namespace osu.Game.Overlays.Mods globalAvailableMods.BindTo(game.AvailableMods); } + private ModSettingChangeTracker? modSettingChangeTracker; + protected override void LoadComplete() { // this is called before base call so that the mod state is populated early, and the transition in `PopIn()` can play out properly. @@ -232,9 +240,17 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(val => { + modSettingChangeTracker?.Dispose(); + updateMultiplier(); updateCustomisation(val); updateFromExternalSelection(); + + if (AllowCustomisation) + { + modSettingChangeTracker = new ModSettingChangeTracker(val.NewValue); + modSettingChangeTracker.SettingChanged += _ => updateMultiplier(); + } }, true); customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); @@ -266,9 +282,9 @@ namespace osu.Game.Overlays.Mods column.DeselectAll(); } - private ColumnDimContainer createModColumnContent(ModType modType, Key[]? toggleKeys = null) + private ColumnDimContainer createModColumnContent(ModType modType) { - var column = CreateModColumn(modType, toggleKeys).With(column => + var column = CreateModColumn(modType).With(column => { // spacing applied here rather than via `columnFlow.Spacing` to avoid uneven gaps when some of the columns are hidden. column.Margin = new MarginPadding { Right = 10 }; @@ -456,8 +472,31 @@ namespace osu.Game.Overlays.Mods .MoveToY(0, duration, Easing.OutQuint) .FadeIn(duration, Easing.OutQuint); - if (!allFiltered) - nonFilteredColumnCount += 1; + if (allFiltered) + continue; + + int columnNumber = nonFilteredColumnCount; + Scheduler.AddDelayed(() => + { + var channel = columnAppearSample?.GetChannel(); + if (channel == null) return; + + // Still play sound effects for off-screen columns up to a certain point. + if (columnNumber > 5 && !column.Active.Value) return; + + // use X position of the column on screen as a basis for panning the sample + float balance = column.Parent.BoundingBox.Centre.X / RelativeToAbsoluteFactor.X; + + // dip frequency and ramp volume of sample over the first 5 displayed columns + float progress = Math.Min(1, columnNumber / 5f); + + channel.Frequency.Value = 1.3 - (progress * 0.3) + RNG.NextDouble(0.1); + channel.Volume.Value = Math.Max(progress, 0.2); + channel.Balance.Value = -1 + balance * 2; + channel.Play(); + }, delay); + + nonFilteredColumnCount += 1; } } @@ -692,11 +731,11 @@ namespace osu.Game.Overlays.Mods switch (e) { - case ClickEvent _: + case ClickEvent: OnClicked?.Invoke(); return true; - case MouseEvent _: + case MouseEvent: return true; } diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs index f44e4bf07f..0932c2c832 100644 --- a/osu.Game/Overlays/Mods/ModSettingsArea.cs +++ b/osu.Game/Overlays/Mods/ModSettingsArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Mods/ModState.cs b/osu.Game/Overlays/Mods/ModState.cs index 8fdd5db00b..79880b85a5 100644 --- a/osu.Game/Overlays/Mods/ModState.cs +++ b/osu.Game/Overlays/Mods/ModState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index f7078b2fa5..fc24e99c7e 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs index 92e88bfaaf..2585e44e05 100644 --- a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs +++ b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Mods/UserModSelectOverlay.cs b/osu.Game/Overlays/Mods/UserModSelectOverlay.cs index 7100446730..1090306c5b 100644 --- a/osu.Game/Overlays/Mods/UserModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/UserModSelectOverlay.cs @@ -3,10 +3,8 @@ using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Game.Rulesets.Mods; using osu.Game.Utils; -using osuTK.Input; namespace osu.Game.Overlays.Mods { @@ -17,7 +15,7 @@ namespace osu.Game.Overlays.Mods { } - protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new UserModColumn(modType, false, toggleKeys); + protected override ModColumn CreateModColumn(ModType modType) => new UserModColumn(modType, false); protected override IReadOnlyList ComputeNewModsFromSelection(IReadOnlyList oldSelection, IReadOnlyList newSelection) { @@ -42,8 +40,8 @@ namespace osu.Game.Overlays.Mods private class UserModColumn : ModColumn { - public UserModColumn(ModType modType, bool allowBulkSelection, [CanBeNull] Key[] toggleKeys = null) - : base(modType, allowBulkSelection, toggleKeys) + public UserModColumn(ModType modType, bool allowIncompatibleSelection) + : base(modType, allowIncompatibleSelection) { } diff --git a/osu.Game/Overlays/Music/CollectionDropdown.cs b/osu.Game/Overlays/Music/CollectionDropdown.cs index 658eebe67b..c1ba16788e 100644 --- a/osu.Game/Overlays/Music/CollectionDropdown.cs +++ b/osu.Game/Overlays/Music/CollectionDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index 46c66b4bae..eb12a62864 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Music/FilterCriteria.cs b/osu.Game/Overlays/Music/FilterCriteria.cs index f15edff4d0..f435c4e6e4 100644 --- a/osu.Game/Overlays/Music/FilterCriteria.cs +++ b/osu.Game/Overlays/Music/FilterCriteria.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Collections; diff --git a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs index 6b33c9200e..8df465e075 100644 --- a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs +++ b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 24d867141c..954c4de493 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; @@ -30,7 +32,15 @@ namespace osu.Game.Overlays.Music var items = (SearchContainer>>)ListContainer; foreach (var item in items.OfType()) - item.InSelectedCollection = criteria.Collection?.Beatmaps.Any(b => item.Model.ID == b.BeatmapSet?.ID) ?? true; + { + if (criteria.Collection == null) + item.InSelectedCollection = true; + else + { + item.InSelectedCollection = item.Model.Value.Beatmaps.Select(b => b.MD5Hash) + .Any(criteria.Collection.BeatmapHashes.Contains); + } + } items.SearchTerm = criteria.SearchText; } diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 82599d3ec9..b30ae095b1 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index ce816f84f0..e33fc8064f 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -83,7 +85,7 @@ namespace osu.Game.Overlays.Music }, }; - filter.Search.OnCommit += (sender, newText) => + filter.Search.OnCommit += (_, _) => { list.FirstVisibleSet?.PerformRead(set => { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index aa09ff6b97..8af295dfe8 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -12,6 +14,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Database; @@ -104,10 +107,12 @@ namespace osu.Game.Overlays if (beatmap.Disabled) return; + Logger.Log($"{nameof(MusicController)} skipping next track to {nameof(EnsurePlayingSomething)}"); NextTrack(); } else if (!IsPlaying) { + Logger.Log($"{nameof(MusicController)} starting playback to {nameof(EnsurePlayingSomething)}"); Play(); } } @@ -128,9 +133,9 @@ namespace osu.Game.Overlays UserPauseRequested = false; if (restart) - CurrentTrack.Restart(); + CurrentTrack.RestartAsync(); else if (!IsPlaying) - CurrentTrack.Start(); + CurrentTrack.StartAsync(); return true; } @@ -147,7 +152,7 @@ namespace osu.Game.Overlays { UserPauseRequested |= requestedByUser; if (CurrentTrack.IsRunning) - CurrentTrack.Stop(); + CurrentTrack.StopAsync(); } /// @@ -245,7 +250,7 @@ namespace osu.Game.Overlays { // if not scheduled, the previously track will be stopped one frame later (see ScheduleAfterChildren logic in GameBase). // we probably want to move this to a central method for switching to a new working beatmap in the future. - Schedule(() => CurrentTrack.Restart()); + Schedule(() => CurrentTrack.RestartAsync()); } private WorkingBeatmap current; diff --git a/osu.Game/Overlays/News/Displays/ArticleListing.cs b/osu.Game/Overlays/News/Displays/ArticleListing.cs index dc3b17b323..8465ebf07c 100644 --- a/osu.Game/Overlays/News/Displays/ArticleListing.cs +++ b/osu.Game/Overlays/News/Displays/ArticleListing.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/News/NewsCard.cs b/osu.Game/Overlays/News/NewsCard.cs index 5ce0b9df9c..eb76522e11 100644 --- a/osu.Game/Overlays/News/NewsCard.cs +++ b/osu.Game/Overlays/News/NewsCard.cs @@ -1,10 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -144,7 +147,7 @@ namespace osu.Game.Overlays.News }, new OsuSpriteText { - Text = date.ToString("d MMM yyyy").ToUpper(), + Text = date.ToLocalisableString(@"d MMM yyyy").ToUpper(), Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold), Margin = new MarginPadding { diff --git a/osu.Game/Overlays/News/NewsHeader.cs b/osu.Game/Overlays/News/NewsHeader.cs index 35e3c7755d..d204dfcf2e 100644 --- a/osu.Game/Overlays/News/NewsHeader.cs +++ b/osu.Game/Overlays/News/NewsHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/News/NewsPostBackground.cs b/osu.Game/Overlays/News/NewsPostBackground.cs index 386ef7f669..bddca8f7ec 100644 --- a/osu.Game/Overlays/News/NewsPostBackground.cs +++ b/osu.Game/Overlays/News/NewsPostBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index e2ce25660e..894f8d5667 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs b/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs index 829fc5b3eb..884e15c03b 100644 --- a/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs +++ b/osu.Game/Overlays/News/Sidebar/NewsSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/News/Sidebar/YearsPanel.cs b/osu.Game/Overlays/News/Sidebar/YearsPanel.cs index 58c0f6ac82..915ed1817c 100644 --- a/osu.Game/Overlays/News/Sidebar/YearsPanel.cs +++ b/osu.Game/Overlays/News/Sidebar/YearsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/NewsOverlay.cs b/osu.Game/Overlays/NewsOverlay.cs index 12e3f81ca1..87b7ebbe89 100644 --- a/osu.Game/Overlays/NewsOverlay.cs +++ b/osu.Game/Overlays/NewsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index f1ed5c4ba6..281077bcf6 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -2,19 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Overlays.Notifications; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics.Containers; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Threading; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays.Notifications; using osu.Game.Resources.Localisation.Web; using NotificationsStrings = osu.Game.Localisation.NotificationsStrings; @@ -30,13 +30,15 @@ namespace osu.Game.Overlays public const float TRANSITION_LENGTH = 600; - private FlowContainer sections; + private FlowContainer sections = null!; [Resolved] - private AudioManager audio { get; set; } + private AudioManager audio { get; set; } = null!; + + private readonly IBindable firstRunSetupVisibility = new Bindable(); [BackgroundDependencyLoader] - private void load() + private void load(FirstRunSetupOverlay? firstRunSetup) { X = WIDTH; Width = WIDTH; @@ -75,13 +77,16 @@ namespace osu.Game.Overlays } } }; + + if (firstRunSetup != null) + firstRunSetupVisibility.BindTo(firstRunSetup.State); } - private ScheduledDelegate notificationsEnabler; + private ScheduledDelegate? notificationsEnabler; private void updateProcessingMode() { - bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State.Value == Visibility.Visible; + bool enabled = (OverlayActivationMode.Value == OverlayActivation.All && firstRunSetupVisibility.Value != Visibility.Visible) || State.Value == Visibility.Visible; notificationsEnabler?.Cancel(); @@ -96,7 +101,8 @@ namespace osu.Game.Overlays { base.LoadComplete(); - State.ValueChanged += _ => updateProcessingMode(); + State.BindValueChanged(_ => updateProcessingMode()); + firstRunSetupVisibility.BindValueChanged(_ => updateProcessingMode()); OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true); } diff --git a/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs b/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs index 603f53cb53..e4aeb4d6ce 100644 --- a/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs +++ b/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Overlays.Notifications diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index ec6e9e09b3..64bf3693c8 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index a4851ab365..b7e21822fa 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index 754f9bd600..cb9d54c14c 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 4735fcb7c1..719e77db83 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using osu.Framework.Allocation; @@ -127,7 +129,7 @@ namespace osu.Game.Overlays.Notifications case ProgressNotificationState.Completed: loadingSpinner.Hide(); NotificationContent.MoveToY(-DrawSize.Y / 2, 200, Easing.OutQuint); - this.FadeOut(200).Finally(d => Completed()); + this.FadeOut(200).Finally(_ => Completed()); break; } } diff --git a/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs b/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs index faab4ed472..ffefcb033f 100644 --- a/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Notifications diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index b9a1cc6d90..fc594902cf 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 4617a91885..6eddc7da83 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading.Tasks; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index 12e30d8de2..a9fab0a23d 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/OSD/TrackedSettingToast.cs b/osu.Game/Overlays/OSD/TrackedSettingToast.cs index 9939ba024e..3bed5e7e4c 100644 --- a/osu.Game/Overlays/OSD/TrackedSettingToast.cs +++ b/osu.Game/Overlays/OSD/TrackedSettingToast.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -66,7 +68,7 @@ namespace osu.Game.Overlays.OSD if (val) selectedOption = 0; break; - case Enum _: + case Enum: var values = Enum.GetValues(description.RawValue.GetType()); optionCount = values.Length; selectedOption = Convert.ToInt32(description.RawValue); diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 6b3696ced9..f2836885ce 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/OnlineOverlay.cs b/osu.Game/Overlays/OnlineOverlay.cs index a610511398..424584fbcf 100644 --- a/osu.Game/Overlays/OnlineOverlay.cs +++ b/osu.Game/Overlays/OnlineOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/OverlayActivation.cs b/osu.Game/Overlays/OverlayActivation.cs index 68d7ee8ea9..354153734e 100644 --- a/osu.Game/Overlays/OverlayActivation.cs +++ b/osu.Game/Overlays/OverlayActivation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Overlays { public enum OverlayActivation diff --git a/osu.Game/Overlays/OverlayColourProvider.cs b/osu.Game/Overlays/OverlayColourProvider.cs index a4f6527024..d7581960f4 100644 --- a/osu.Game/Overlays/OverlayColourProvider.cs +++ b/osu.Game/Overlays/OverlayColourProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index fed1e57686..ed8e3849d4 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/OverlayHeaderBackground.cs b/osu.Game/Overlays/OverlayHeaderBackground.cs index 2fef593285..c47f16272f 100644 --- a/osu.Game/Overlays/OverlayHeaderBackground.cs +++ b/osu.Game/Overlays/OverlayHeaderBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs index d7a3b052ae..14a99cd5bb 100644 --- a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs +++ b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 8c44157f78..a0efb197c2 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index 1f11b98881..ba0b81a514 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index 7fe188eb04..95b27665f4 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/OverlaySidebar.cs b/osu.Game/Overlays/OverlaySidebar.cs index 468b5b6eb3..62f3e1af13 100644 --- a/osu.Game/Overlays/OverlaySidebar.cs +++ b/osu.Game/Overlays/OverlaySidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/OverlaySortTabControl.cs b/osu.Game/Overlays/OverlaySortTabControl.cs index 5f5cfce344..f02d2b388f 100644 --- a/osu.Game/Overlays/OverlaySortTabControl.cs +++ b/osu.Game/Overlays/OverlaySortTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/OverlayStreamControl.cs b/osu.Game/Overlays/OverlayStreamControl.cs index 8b6aca6d5d..1bd244176e 100644 --- a/osu.Game/Overlays/OverlayStreamControl.cs +++ b/osu.Game/Overlays/OverlayStreamControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input.Events; using System.Collections.Generic; diff --git a/osu.Game/Overlays/OverlayStreamItem.cs b/osu.Game/Overlays/OverlayStreamItem.cs index 56502ff70f..3e09956480 100644 --- a/osu.Game/Overlays/OverlayStreamItem.cs +++ b/osu.Game/Overlays/OverlayStreamItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/OverlayTabControl.cs b/osu.Game/Overlays/OverlayTabControl.cs index 578cd703c7..35e073a3a1 100644 --- a/osu.Game/Overlays/OverlayTabControl.cs +++ b/osu.Game/Overlays/OverlayTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Overlays/OverlayTitle.cs b/osu.Game/Overlays/OverlayTitle.cs index d92979e8d4..f2c42034a3 100644 --- a/osu.Game/Overlays/OverlayTitle.cs +++ b/osu.Game/Overlays/OverlayTitle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/OverlayView.cs b/osu.Game/Overlays/OverlayView.cs index c254cdf290..80df0c695f 100644 --- a/osu.Game/Overlays/OverlayView.cs +++ b/osu.Game/Overlays/OverlayView.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index a70d57661b..dcc8b19021 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Humanizer; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 00a866f1f4..b07817de46 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs index 74f3ed846b..cf75818a0c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/DrawableBadge.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs index 4cfdf5cc86..62b228c285 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs b/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs index 1b21bfc982..6fbfff1dd7 100644 --- a/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/FollowersButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs index e1302788da..fdf7478834 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelBadge.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs index d8eb5b65ac..1ba391431f 100644 --- a/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs +++ b/osu.Game/Overlays/Profile/Header/Components/LevelProgressBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs b/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs index 6d1024ff18..7bfc78cb2d 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MappingSubscribersButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs index e3dc5f818a..46cb811846 100644 --- a/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/MessageUserButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs b/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs index 5ef8482b47..7ac472ee00 100644 --- a/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs +++ b/osu.Game/Overlays/Profile/Header/Components/OverlinedInfoContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs b/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs index 1ead2cd2f5..9e5a0f5962 100644 --- a/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs +++ b/osu.Game/Overlays/Profile/Header/Components/OverlinedTotalPlayTime.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs index 49744e885a..808c814928 100644 --- a/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs +++ b/osu.Game/Overlays/Profile/Header/Components/PreviousUsernames.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index cea63574cf..5bdf9c19e1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs index b098f9f840..3b3251fc4e 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderStatisticsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs index 4d2290266c..3a47570cf7 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs index 4a44e285bf..d75fe1ae84 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index d195babcbf..85fb5c4e5c 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index f450754c02..a05d8ba152 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 79e553062d..d65691f531 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 922f3832e4..deb675df1d 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 6ba5cb2f7f..7e079c8341 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; @@ -133,8 +136,8 @@ namespace osu.Game.Overlays.Profile.Header { userFlag = new UpdateableFlag { - Size = new Vector2(30, 20), - ShowPlaceholderOnNull = false, + Size = new Vector2(28, 20), + ShowPlaceholderOnUnknown = false, }, userCountryText = new OsuSpriteText { @@ -172,8 +175,8 @@ namespace osu.Game.Overlays.Profile.Header avatar.User = user; usernameText.Text = user?.Username ?? string.Empty; openUserExternally.Link = $@"{api.WebsiteRootUrl}/users/{user?.Id ?? 0}"; - userFlag.Country = user?.Country; - userCountryText.Text = user?.Country?.FullName ?? "Alien"; + userFlag.CountryCode = user?.CountryCode ?? default; + userCountryText.Text = (user?.CountryCode ?? default).GetDescription(); supporterTag.SupportLevel = user?.SupportLevel ?? 0; titleText.Text = user?.Title ?? string.Empty; titleText.Colour = Color4Extensions.FromHex(user?.Colour ?? "fff"); diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 44e0d9c37f..f84f829f7a 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index fc6fce0d8e..67738943e8 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Profile/Sections/AboutSection.cs b/osu.Game/Overlays/Profile/Sections/AboutSection.cs index d0d9362fd2..2b6ce732a2 100644 --- a/osu.Game/Overlays/Profile/Sections/AboutSection.cs +++ b/osu.Game/Overlays/Profile/Sections/AboutSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 13465f3bf8..5d36537c3e 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 8224cd5eb5..aaaed5ad0a 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 6b93c24a78..e3cff5da05 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile.Sections.Beatmaps; diff --git a/osu.Game/Overlays/Profile/Sections/CounterPill.cs b/osu.Game/Overlays/Profile/Sections/CounterPill.cs index bd6cb4d09b..e9b55f62ef 100644 --- a/osu.Game/Overlays/Profile/Sections/CounterPill.cs +++ b/osu.Game/Overlays/Profile/Sections/CounterPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs index 4edbdc31bd..f0819c4474 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ChartProfileSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs index 3ed4bd9e50..70ab95b848 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 06de0f62dc..34c9892f06 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs b/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs index 51d704a6b0..73e39a2440 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PlayHistorySubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs b/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs index c049bff7b2..78a28a39d2 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ProfileLineChart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using JetBrains.Annotations; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs b/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs index 22312afdc9..89e8f51338 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/ReplaysSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs b/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs index f80167f9d3..48d75a4953 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/UserHistoryGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs index 203844b6b5..f1e1c44734 100644 --- a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs +++ b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs index ce05beffd1..44f1af4b72 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/DrawableKudosuHistoryItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 79a06ecdd4..bb9d48c473 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osuTK; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs index 9af854e6b9..34e6866d25 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs index 5b749c78a8..517b4d92cf 100644 --- a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs +++ b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Overlays.Profile.Sections.Kudosu; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs index cacdd44b61..a458bc4873 100644 --- a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs index 33bd155d71..8ed1dc3676 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs b/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs index afa6bd9f79..392e35ac05 100644 --- a/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/ProfileItemContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs index fdf8cb19ff..8e43519a17 100644 --- a/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/ProfileSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs b/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs index 408cb00770..f2770d81cd 100644 --- a/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs +++ b/osu.Game/Overlays/Profile/Sections/ProfileSubsectionHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 998f5d158e..5d8f8c8326 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; @@ -29,7 +31,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks private const float performance_background_shear = 0.45f; - protected readonly APIScore Score; + protected readonly SoloScoreInfo Score; [Resolved] private OsuColour colours { get; set; } @@ -37,7 +39,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks [Resolved] private OverlayColourProvider colourProvider { get; set; } - public DrawableProfileScore(APIScore score) + public DrawableProfileScore(SoloScoreInfo score) { Score = score; @@ -96,7 +98,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), Colour = colours.Yellow }, - new DrawableDate(Score.Date, 12) + new DrawableDate(Score.EndedAt, 12) { Colour = colourProvider.Foreground1 } @@ -134,9 +136,9 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Spacing = new Vector2(2), Children = Score.Mods.Select(mod => { - var ruleset = rulesets.GetRuleset(Score.RulesetID) ?? throw new InvalidOperationException(); + var ruleset = rulesets.GetRuleset(Score.RulesetID) ?? throw new InvalidOperationException($"Ruleset with ID of {Score.RulesetID} not found locally"); - return new ModIcon(ruleset.CreateInstance().CreateModFromAcronym(mod.Acronym)) + return new ModIcon(mod.ToMod(ruleset.CreateInstance())) { Scale = new Vector2(0.35f) }; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs index 78ae0a5634..94d95dc27e 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,7 +18,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { private readonly double weight; - public DrawableProfileWeightedScore(APIScore score, double weight) + public DrawableProfileWeightedScore(SoloScoreInfo score, double weight) : base(score) { this.weight = weight; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index ef9f4b5ff3..2564692c87 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; using System; @@ -15,7 +17,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Overlays.Profile.Sections.Ranks { - public class PaginatedScoreContainer : PaginatedProfileSubsection + public class PaginatedScoreContainer : PaginatedProfileSubsection { private readonly ScoreType type; @@ -52,7 +54,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks } } - protected override void OnItemsReceived(List items) + protected override void OnItemsReceived(List items) { if (CurrentPage == null || CurrentPage?.Offset == 0) drawableItemIndex = 0; @@ -60,12 +62,12 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks base.OnItemsReceived(items); } - protected override APIRequest> CreateRequest(PaginationParameters pagination) => + protected override APIRequest> CreateRequest(PaginationParameters pagination) => new GetUserScoresRequest(User.Value.Id, type, pagination); private int drawableItemIndex; - protected override Drawable CreateDrawableItem(APIScore model) + protected override Drawable CreateDrawableItem(SoloScoreInfo model) { switch (type) { diff --git a/osu.Game/Overlays/Profile/Sections/RanksSection.cs b/osu.Game/Overlays/Profile/Sections/RanksSection.cs index f48e33dc12..581b6e1139 100644 --- a/osu.Game/Overlays/Profile/Sections/RanksSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RanksSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Online.API.Requests; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 7a27c6e4e1..943c105008 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 0c1f8b2e92..e3072f3420 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 77008d5f34..2878e0e940 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Profile/Sections/RecentSection.cs b/osu.Game/Overlays/Profile/Sections/RecentSection.cs index 33d435aa1b..c20594f974 100644 --- a/osu.Game/Overlays/Profile/Sections/RecentSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RecentSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Overlays.Profile.Sections.Recent; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Profile/UserGraph.cs b/osu.Game/Overlays/Profile/UserGraph.cs index 182221eea7..a8a4de68ff 100644 --- a/osu.Game/Overlays/Profile/UserGraph.cs +++ b/osu.Game/Overlays/Profile/UserGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index 9950f36141..9376bafdff 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -14,14 +16,14 @@ using osuTK; namespace osu.Game.Overlays.Rankings { - public class CountryFilter : CompositeDrawable, IHasCurrentValue + public class CountryFilter : CompositeDrawable, IHasCurrentValue { private const int duration = 200; private const int height = 70; - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); - public Bindable Current + public Bindable Current { get => current.Current; set => current.Current = value; @@ -87,9 +89,9 @@ namespace osu.Game.Overlays.Rankings Current.BindValueChanged(onCountryChanged, true); } - private void onCountryChanged(ValueChangedEvent country) + private void onCountryChanged(ValueChangedEvent country) { - if (country.NewValue == null) + if (Current.Value == CountryCode.Unknown) { countryPill.Collapse(); this.ResizeHeightTo(0, duration, Easing.OutQuint); diff --git a/osu.Game/Overlays/Rankings/CountryPill.cs b/osu.Game/Overlays/Rankings/CountryPill.cs index edd7b596d2..ee4c4f08af 100644 --- a/osu.Game/Overlays/Rankings/CountryPill.cs +++ b/osu.Game/Overlays/Rankings/CountryPill.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -19,13 +22,13 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Rankings { - public class CountryPill : CompositeDrawable, IHasCurrentValue + public class CountryPill : CompositeDrawable, IHasCurrentValue { private const int duration = 200; - private readonly BindableWithCurrent current = new BindableWithCurrent(); + private readonly BindableWithCurrent current = new BindableWithCurrent(); - public Bindable Current + public Bindable Current { get => current.Current; set => current.Current = value; @@ -77,7 +80,7 @@ namespace osu.Game.Overlays.Rankings { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(30, 20) + Size = new Vector2(28, 20) }, countryName = new OsuSpriteText { @@ -91,7 +94,7 @@ namespace osu.Game.Overlays.Rankings { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Action = () => Current.Value = null + Action = Current.SetDefault, } } } @@ -128,13 +131,13 @@ namespace osu.Game.Overlays.Rankings this.FadeOut(duration, Easing.OutQuint); } - private void onCountryChanged(ValueChangedEvent country) + private void onCountryChanged(ValueChangedEvent country) { - if (country.NewValue == null) + if (Current.Value == CountryCode.Unknown) return; - flag.Country = country.NewValue; - countryName.Text = country.NewValue.FullName; + flag.CountryCode = country.NewValue; + countryName.Text = country.NewValue.GetDescription(); } private class CloseButton : OsuHoverContainer diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 417b33ddf6..936545bd49 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; @@ -14,7 +16,7 @@ namespace osu.Game.Overlays.Rankings { public Bindable Ruleset => rulesetSelector.Current; - public Bindable Country => countryFilter.Current; + public Bindable Country => countryFilter.Current; private OverlayRulesetSelector rulesetSelector; private CountryFilter countryFilter; diff --git a/osu.Game/Overlays/Rankings/RankingsScope.cs b/osu.Game/Overlays/Rankings/RankingsScope.cs index e660c2898a..2644fee58b 100644 --- a/osu.Game/Overlays/Rankings/RankingsScope.cs +++ b/osu.Game/Overlays/Rankings/RankingsScope.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs index f05795b2a2..905c0fae65 100644 --- a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs +++ b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index c05c160463..234b91de66 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs index 7f5d096fe2..c23b9711dd 100644 --- a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs +++ b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Threading; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index a908380e95..a6f0c7a123 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; @@ -9,6 +11,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Game.Resources.Localisation.Web; @@ -31,9 +34,9 @@ namespace osu.Game.Overlays.Rankings.Tables new RankingsTableColumn(RankingsStrings.StatAveragePerformance, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)), }; - protected override Country GetCountry(CountryStatistics item) => item.Country; + protected override CountryCode GetCountryCode(CountryStatistics item) => item.Code; - protected override Drawable CreateFlagContent(CountryStatistics item) => new CountryName(item.Country); + protected override Drawable CreateFlagContent(CountryStatistics item) => new CountryName(item.Code); protected override Drawable[] CreateAdditionalContent(CountryStatistics item) => new Drawable[] { @@ -68,15 +71,15 @@ namespace osu.Game.Overlays.Rankings.Tables [Resolved(canBeNull: true)] private RankingsOverlay rankings { get; set; } - public CountryName(Country country) + public CountryName(CountryCode countryCode) : base(t => t.Font = OsuFont.GetFont(size: 12)) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; TextAnchor = Anchor.CentreLeft; - if (!string.IsNullOrEmpty(country.FullName)) - AddLink(country.FullName, () => rankings?.ShowCountry(country)); + if (countryCode != CountryCode.Unknown) + AddLink(countryCode.GetDescription(), () => rankings?.ShowCountry(countryCode)); } } } diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 6c85ec2753..a77546d83f 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index fd69b6c80a..073bf86a7a 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System.Collections.Generic; @@ -77,7 +79,7 @@ namespace osu.Game.Overlays.Rankings.Tables protected sealed override Drawable CreateHeader(int index, TableColumn column) => (column as RankingsTableColumn)?.CreateHeaderText() ?? new HeaderText(column?.Header ?? default, false); - protected abstract Country GetCountry(TModel item); + protected abstract CountryCode GetCountryCode(TModel item); protected abstract Drawable CreateFlagContent(TModel item); @@ -95,10 +97,10 @@ namespace osu.Game.Overlays.Rankings.Tables Margin = new MarginPadding { Bottom = row_spacing }, Children = new[] { - new UpdateableFlag(GetCountry(item)) + new UpdateableFlag(GetCountryCode(item)) { - Size = new Vector2(30, 20), - ShowPlaceholderOnNull = false, + Size = new Vector2(28, 20), + ShowPlaceholderOnUnknown = false, }, CreateFlagContent(item) } diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 934da4501e..71c78baf3c 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs index b49fec65db..fd9f6da749 100644 --- a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs +++ b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs index 5d150c9535..48185e6083 100644 --- a/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/UserBasedTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.LocalisationExtensions; @@ -57,7 +59,7 @@ namespace osu.Game.Overlays.Rankings.Tables .Concat(GradeColumns.Select(grade => new GradeTableColumn(grade, Anchor.Centre, new Dimension(GridSizeMode.AutoSize)))) .ToArray(); - protected sealed override Country GetCountry(UserStatistics item) => item.User.Country; + protected sealed override CountryCode GetCountryCode(UserStatistics item) => item.User.CountryCode; protected sealed override Drawable CreateFlagContent(UserStatistics item) { diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 80ce2e038d..586b883604 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -15,7 +17,7 @@ namespace osu.Game.Overlays { public class RankingsOverlay : TabbableOnlineOverlay { - protected Bindable Country => Header.Country; + protected Bindable Country => Header.Country; private APIRequest lastRequest; @@ -42,7 +44,7 @@ namespace osu.Game.Overlays Country.BindValueChanged(_ => { // if a country is requested, force performance scope. - if (Country.Value != null) + if (!Country.IsDefault) Header.Current.Value = RankingsScope.Performance; Scheduler.AddOnce(triggerTabChanged); @@ -74,7 +76,7 @@ namespace osu.Game.Overlays { // country filtering is only valid for performance scope. if (Header.Current.Value != RankingsScope.Performance) - Country.Value = null; + Country.SetDefault(); Scheduler.AddOnce(triggerTabChanged); } @@ -83,9 +85,9 @@ namespace osu.Game.Overlays protected override RankingsOverlayHeader CreateHeader() => new RankingsOverlayHeader(); - public void ShowCountry(Country requested) + public void ShowCountry(CountryCode requested) { - if (requested == null) + if (requested == default) return; Show(); @@ -126,7 +128,7 @@ namespace osu.Game.Overlays switch (Header.Current.Value) { case RankingsScope.Performance: - return new GetUserRankingsRequest(ruleset.Value, country: Country.Value?.FlagName); + return new GetUserRankingsRequest(ruleset.Value, countryCode: Country.Value); case RankingsScope.Country: return new GetCountryRankingsRequest(ruleset.Value); diff --git a/osu.Game/Overlays/RestoreDefaultValueButton.cs b/osu.Game/Overlays/RestoreDefaultValueButton.cs index afc4146199..a5da696f58 100644 --- a/osu.Game/Overlays/RestoreDefaultValueButton.cs +++ b/osu.Game/Overlays/RestoreDefaultValueButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs index 4ca3ace8a1..bf7c9ccf2b 100644 --- a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs +++ b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/ISettingsItem.cs b/osu.Game/Overlays/Settings/ISettingsItem.cs index 61191dcacf..509fc1ab0d 100644 --- a/osu.Game/Overlays/Settings/ISettingsItem.cs +++ b/osu.Game/Overlays/Settings/ISettingsItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/OutlinedTextBox.cs b/osu.Game/Overlays/Settings/OutlinedTextBox.cs index 93eaf74b77..de7fe75060 100644 --- a/osu.Game/Overlays/Settings/OutlinedTextBox.cs +++ b/osu.Game/Overlays/Settings/OutlinedTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index 3945a410ab..76e75a5b3c 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Configuration; 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 858d555f06..7cb9efa1b9 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index eaacb9293f..d25e9490b7 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 00c1cb8f43..cea8fdd733 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 7ffa0bd415..70c74cd77c 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 2e23d8a22a..a02e28d33a 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index 8833420523..e79d27ad2a 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -9,6 +11,7 @@ using osu.Framework.Screens; using osu.Game.Localisation; using osu.Game.Screens; using osu.Game.Screens.Import; +using osu.Game.Screens.Utility; namespace osu.Game.Overlays.Settings.Sections.DebugSettings { @@ -30,13 +33,18 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { LabelText = DebugSettingsStrings.BypassFrontToBackPass, Current = config.GetBindable(DebugSetting.BypassFrontToBackPass) + }, + new SettingsButton + { + Text = DebugSettingsStrings.ImportFiles, + Action = () => performer?.PerformFromScreen(menu => menu.Push(new FileImportScreen())) + }, + new SettingsButton + { + Text = @"Run latency certifier", + Action = () => performer?.PerformFromScreen(menu => menu.Push(new LatencyCertifierScreen())) } }; - Add(new SettingsButton - { - Text = DebugSettingsStrings.ImportFiles, - Action = () => performer?.PerformFromScreen(menu => menu.Push(new FileImportScreen())) - }); } } } diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs index f26326a220..42ac4adb34 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using System.Threading.Tasks; @@ -37,7 +39,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings Action = () => { // Blocking operations implicitly causes a Compact(). - using (realm.BlockAllOperations()) + using (realm.BlockAllOperations("compact")) { } } @@ -56,7 +58,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { try { - var token = realm.BlockAllOperations(); + var token = realm.BlockAllOperations("maintenance"); blockAction.Enabled.Value = false; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs index e2e00813bd..d369c4470b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs index 94e0c5e494..cc224a4f7f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs index aaa60ce81b..becb7aa80f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 5231ce1211..c16ee39191 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index 0d31e70880..0893af7d3e 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs index 83ea655601..b5315d5268 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework; 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 ed88d80570..53f7f52212 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index 120e2d908c..48e76bfeb7 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index cdce187a35..63f0dec953 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 5bc88b8692..b68a4fed48 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index ced3116728..59cbd8cd5a 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 05890ad882..28642f12a1 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Drawing; using System.Linq; @@ -158,13 +160,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSettings.ForEach(s => bindPreviewEvent(s.Current)); - windowModeDropdown.Current.BindValueChanged(mode => + windowModeDropdown.Current.BindValueChanged(_ => { updateDisplayModeDropdowns(); updateScreenModeWarning(); }, true); - windowModes.BindCollectionChanged((sender, args) => + windowModes.BindCollectionChanged((_, _) => { if (windowModes.Count > 1) windowModeDropdown.Show(); @@ -188,7 +190,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics updateDisplayModeDropdowns(); }), true); - scalingMode.BindValueChanged(mode => + scalingMode.BindValueChanged(_ => { scalingSettings.ClearTransforms(); scalingSettings.AutoSizeDuration = transition_duration; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 8c3e45cd62..2e15172e46 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -15,8 +17,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader; - private SettingsEnumDropdown frameLimiterDropdown; - [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { // TODO: this needs to be a custom dropdown at some point - frameLimiterDropdown = new SettingsEnumDropdown + new SettingsEnumDropdown { LabelText = GraphicsSettingsStrings.FrameLimiter, Current = config.GetBindable(FrameworkSetting.FrameSync) @@ -41,24 +41,5 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; } - - protected override void LoadComplete() - { - base.LoadComplete(); - - frameLimiterDropdown.Current.BindValueChanged(limit => - { - switch (limit.NewValue) - { - case FrameSync.Unlimited: - frameLimiterDropdown.SetNoticeText(GraphicsSettingsStrings.UnlimitedFramesNote, true); - break; - - default: - frameLimiterDropdown.ClearNoticeText(); - break; - } - }, true); - } } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs index dbb9ddc1c1..7f88cc23d2 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs index 921eab63ed..56d0a6421b 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/VideoSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 8cd3b841c2..e094e0e051 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs index 3227decc46..b92746a65a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs index 3350ff4eaa..a2e07065f1 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/GlobalKeyBindingsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs index 60849cd6d4..34be846595 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/JoystickSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs index 67f1bb8d3e..0830241f2b 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs index 7312748435..9ff47578e9 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs index 297af35fb5..628fe08607 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 1511d53b6b..b815239c9f 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -124,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input }, true); } - private class SensitivitySetting : SettingsSlider + public class SensitivitySetting : SettingsSlider { public SensitivitySetting() { @@ -133,7 +135,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input } } - private class SensitivitySlider : OsuSliderBar + public class SensitivitySlider : OsuSliderBar { public override LocalisableString TooltipText => Current.Disabled ? MouseSettingsStrings.EnableHighPrecisionForSensitivityAdjust : $"{base.TooltipText}x"; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs b/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs index dbdf600002..2172dc175e 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RotationPresetButtons.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index dae276c711..6f3127a377 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs index 58abfab29c..cd6554e52d 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 5d31c38ae7..271438ed14 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs index a0f069b3bb..23f91fba4b 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/VariantBindingsSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Rulesets; diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index d2c5d2fcf7..4d75537f6b 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -1,14 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Handlers; -using osu.Framework.Input.Handlers.Joystick; -using osu.Framework.Input.Handlers.Midi; -using osu.Framework.Input.Handlers.Mouse; -using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Localisation; @@ -22,9 +20,6 @@ namespace osu.Game.Overlays.Settings.Sections public override LocalisableString Header => InputSettingsStrings.InputSectionHeader; - [Resolved] - private GameHost host { get; set; } - public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.Keyboard @@ -36,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections } [BackgroundDependencyLoader] - private void load() + private void load(GameHost host, OsuGameBase game) { Children = new Drawable[] { @@ -45,45 +40,14 @@ namespace osu.Game.Overlays.Settings.Sections foreach (var handler in host.AvailableInputHandlers) { - var handlerSection = createSectionFor(handler); + var handlerSection = game.CreateSettingsSubsectionFor(handler); if (handlerSection != null) Add(handlerSection); } } - private SettingsSubsection createSectionFor(InputHandler handler) - { - SettingsSubsection section; - - switch (handler) - { - // ReSharper disable once SuspiciousTypeConversion.Global (net standard fuckery) - case ITabletHandler th: - section = new TabletSettings(th); - break; - - case MouseHandler mh: - section = new MouseSettings(mh); - break; - - // whitelist the handlers which should be displayed to avoid any weird cases of users touching settings they shouldn't. - case JoystickHandler jh: - section = new JoystickSettings(jh); - break; - - case MidiHandler _: - section = new HandlerSection(handler); - break; - - default: - return null; - } - - return section; - } - - private class HandlerSection : SettingsSubsection + public class HandlerSection : SettingsSubsection { private readonly InputHandler handler; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs new file mode 100644 index 0000000000..453dbd2e18 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/BeatmapSettings.cs @@ -0,0 +1,88 @@ +// 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.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Localisation; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Localisation; + +namespace osu.Game.Overlays.Settings.Sections.Maintenance +{ + public class BeatmapSettings : SettingsSubsection + { + protected override LocalisableString Header => "Beatmaps"; + + private SettingsButton importBeatmapsButton = null!; + private SettingsButton deleteBeatmapsButton = null!; + private SettingsButton deleteBeatmapVideosButton = null!; + private SettingsButton restoreButton = null!; + private SettingsButton undeleteButton = null!; + + [BackgroundDependencyLoader] + private void load(BeatmapManager beatmaps, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + { + if (legacyImportManager?.SupportsImportFromStable == true) + { + Add(importBeatmapsButton = new SettingsButton + { + Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable, + Action = () => + { + importBeatmapsButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Beatmaps).ContinueWith(_ => Schedule(() => importBeatmapsButton.Enabled.Value = true)); + } + }); + } + + Add(deleteBeatmapsButton = new DangerousSettingsButton + { + Text = MaintenanceSettingsStrings.DeleteAllBeatmaps, + Action = () => + { + dialogOverlay?.Push(new MassDeleteConfirmationDialog(() => + { + deleteBeatmapsButton.Enabled.Value = false; + Task.Run(() => beatmaps.Delete()).ContinueWith(_ => Schedule(() => deleteBeatmapsButton.Enabled.Value = true)); + })); + } + }); + + Add(deleteBeatmapVideosButton = new DangerousSettingsButton + { + Text = MaintenanceSettingsStrings.DeleteAllBeatmapVideos, + Action = () => + { + dialogOverlay?.Push(new MassVideoDeleteConfirmationDialog(() => + { + deleteBeatmapVideosButton.Enabled.Value = false; + Task.Run(beatmaps.DeleteAllVideos).ContinueWith(_ => Schedule(() => deleteBeatmapVideosButton.Enabled.Value = true)); + })); + } + }); + AddRange(new Drawable[] + { + restoreButton = new SettingsButton + { + Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties, + Action = () => + { + restoreButton.Enabled.Value = false; + Task.Run(beatmaps.RestoreAll).ContinueWith(_ => Schedule(() => restoreButton.Enabled.Value = true)); + } + }, + undeleteButton = new SettingsButton + { + Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps, + Action = () => + { + undeleteButton.Enabled.Value = false; + Task.Run(beatmaps.UndeleteAll).ContinueWith(_ => Schedule(() => undeleteButton.Enabled.Value = true)); + } + } + }); + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs new file mode 100644 index 0000000000..5367f644ca --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/CollectionsSettings.cs @@ -0,0 +1,46 @@ +// Copyright (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.Localisation; +using osu.Game.Collections; +using osu.Game.Database; +using osu.Game.Localisation; + +namespace osu.Game.Overlays.Settings.Sections.Maintenance +{ + public class CollectionsSettings : SettingsSubsection + { + protected override LocalisableString Header => "Collections"; + + private SettingsButton importCollectionsButton = null!; + + [BackgroundDependencyLoader] + private void load(CollectionManager? collectionManager, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + { + if (collectionManager == null) return; + + if (legacyImportManager?.SupportsImportFromStable == true) + { + Add(importCollectionsButton = new SettingsButton + { + Text = MaintenanceSettingsStrings.ImportCollectionsFromStable, + Action = () => + { + importCollectionsButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Collections).ContinueWith(_ => Schedule(() => importCollectionsButton.Enabled.Value = true)); + } + }); + } + + Add(new DangerousSettingsButton + { + Text = MaintenanceSettingsStrings.DeleteAllCollections, + Action = () => + { + dialogOverlay?.Push(new MassDeleteConfirmationDialog(collectionManager.DeleteAll)); + } + }); + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index c7fd248842..1c9a758c6f 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using System.IO; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs deleted file mode 100644 index 054de8dbd7..0000000000 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ /dev/null @@ -1,175 +0,0 @@ -// 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.Tasks; -using JetBrains.Annotations; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Localisation; -using osu.Game.Beatmaps; -using osu.Game.Collections; -using osu.Game.Database; -using osu.Game.Localisation; -using osu.Game.Scoring; -using osu.Game.Skinning; - -namespace osu.Game.Overlays.Settings.Sections.Maintenance -{ - public class GeneralSettings : SettingsSubsection - { - protected override LocalisableString Header => "General"; - - private SettingsButton importBeatmapsButton; - private SettingsButton importScoresButton; - private SettingsButton importSkinsButton; - private SettingsButton importCollectionsButton; - private SettingsButton deleteBeatmapsButton; - private SettingsButton deleteScoresButton; - private SettingsButton deleteSkinsButton; - private SettingsButton restoreButton; - private SettingsButton undeleteButton; - private SettingsButton deleteBeatmapVideosButton; - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapManager beatmaps, ScoreManager scores, SkinManager skins, [CanBeNull] CollectionManager collectionManager, [CanBeNull] LegacyImportManager legacyImportManager, IDialogOverlay dialogOverlay) - { - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importBeatmapsButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportBeatmapsFromStable, - Action = () => - { - importBeatmapsButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Beatmaps).ContinueWith(t => Schedule(() => importBeatmapsButton.Enabled.Value = true)); - } - }); - } - - Add(deleteBeatmapsButton = new DangerousSettingsButton - { - Text = MaintenanceSettingsStrings.DeleteAllBeatmaps, - Action = () => - { - dialogOverlay?.Push(new MassDeleteConfirmationDialog(() => - { - deleteBeatmapsButton.Enabled.Value = false; - Task.Run(() => beatmaps.Delete()).ContinueWith(t => Schedule(() => deleteBeatmapsButton.Enabled.Value = true)); - })); - } - }); - - Add(deleteBeatmapVideosButton = new DangerousSettingsButton - { - Text = MaintenanceSettingsStrings.DeleteAllBeatmapVideos, - Action = () => - { - dialogOverlay?.Push(new MassVideoDeleteConfirmationDialog(() => - { - deleteBeatmapVideosButton.Enabled.Value = false; - Task.Run(beatmaps.DeleteAllVideos).ContinueWith(t => Schedule(() => deleteBeatmapVideosButton.Enabled.Value = true)); - })); - } - }); - - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importScoresButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportScoresFromStable, - Action = () => - { - importScoresButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Scores).ContinueWith(t => Schedule(() => importScoresButton.Enabled.Value = true)); - } - }); - } - - Add(deleteScoresButton = new DangerousSettingsButton - { - Text = MaintenanceSettingsStrings.DeleteAllScores, - Action = () => - { - dialogOverlay?.Push(new MassDeleteConfirmationDialog(() => - { - deleteScoresButton.Enabled.Value = false; - Task.Run(() => scores.Delete()).ContinueWith(t => Schedule(() => deleteScoresButton.Enabled.Value = true)); - })); - } - }); - - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importSkinsButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportSkinsFromStable, - Action = () => - { - importSkinsButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Skins).ContinueWith(t => Schedule(() => importSkinsButton.Enabled.Value = true)); - } - }); - } - - Add(deleteSkinsButton = new DangerousSettingsButton - { - Text = MaintenanceSettingsStrings.DeleteAllSkins, - Action = () => - { - dialogOverlay?.Push(new MassDeleteConfirmationDialog(() => - { - deleteSkinsButton.Enabled.Value = false; - Task.Run(() => skins.Delete()).ContinueWith(t => Schedule(() => deleteSkinsButton.Enabled.Value = true)); - })); - } - }); - - if (collectionManager != null) - { - if (legacyImportManager?.SupportsImportFromStable == true) - { - Add(importCollectionsButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.ImportCollectionsFromStable, - Action = () => - { - importCollectionsButton.Enabled.Value = false; - legacyImportManager.ImportFromStableAsync(StableContent.Collections).ContinueWith(t => Schedule(() => importCollectionsButton.Enabled.Value = true)); - } - }); - } - - Add(new DangerousSettingsButton - { - Text = MaintenanceSettingsStrings.DeleteAllCollections, - Action = () => - { - dialogOverlay?.Push(new MassDeleteConfirmationDialog(collectionManager.DeleteAll)); - } - }); - } - - AddRange(new Drawable[] - { - restoreButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.RestoreAllHiddenDifficulties, - Action = () => - { - restoreButton.Enabled.Value = false; - Task.Run(beatmaps.RestoreAll).ContinueWith(t => Schedule(() => restoreButton.Enabled.Value = true)); - } - }, - undeleteButton = new SettingsButton - { - Text = MaintenanceSettingsStrings.RestoreAllRecentlyDeletedBeatmaps, - Action = () => - { - undeleteButton.Enabled.Value = false; - Task.Run(beatmaps.UndeleteAll).ContinueWith(t => Schedule(() => undeleteButton.Enabled.Value = true)); - } - }, - }); - } - } -} diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs index c481c80d82..526c096493 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs index fc8c9d497b..e3870bc76a 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassVideoDeleteConfirmationDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Overlays.Settings.Sections.Maintenance diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs index b7b797936e..d565576d09 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationRunScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Threading.Tasks; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs index 3cb5521e51..0d32e33d87 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MigrationSelectScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; @@ -54,7 +56,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance dialogOverlay.Push(new ConfirmDialog("To complete this operation, osu! will close. Please open it again to use the new data location.", () => { (storage as OsuStorage)?.ChangeDataPath(target.FullName); - game.GracefullyExit(); + game.Exit(); }, () => { })); }, () => { })); diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.cs new file mode 100644 index 0000000000..70e11d45dc --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/ScoreSettings.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 System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Localisation; +using osu.Game.Database; +using osu.Game.Localisation; +using osu.Game.Scoring; + +namespace osu.Game.Overlays.Settings.Sections.Maintenance +{ + public class ScoreSettings : SettingsSubsection + { + protected override LocalisableString Header => "Scores"; + + private SettingsButton importScoresButton = null!; + private SettingsButton deleteScoresButton = null!; + + [BackgroundDependencyLoader] + private void load(ScoreManager scores, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + { + if (legacyImportManager?.SupportsImportFromStable == true) + { + Add(importScoresButton = new SettingsButton + { + Text = MaintenanceSettingsStrings.ImportScoresFromStable, + Action = () => + { + importScoresButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Scores).ContinueWith(_ => Schedule(() => importScoresButton.Enabled.Value = true)); + } + }); + } + + Add(deleteScoresButton = new DangerousSettingsButton + { + Text = MaintenanceSettingsStrings.DeleteAllScores, + Action = () => + { + dialogOverlay?.Push(new MassDeleteConfirmationDialog(() => + { + deleteScoresButton.Enabled.Value = false; + Task.Run(() => scores.Delete()).ContinueWith(_ => Schedule(() => deleteScoresButton.Enabled.Value = true)); + })); + } + }); + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.cs new file mode 100644 index 0000000000..c95b1d4dd8 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/SkinSettings.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 System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Localisation; +using osu.Game.Database; +using osu.Game.Localisation; +using osu.Game.Skinning; + +namespace osu.Game.Overlays.Settings.Sections.Maintenance +{ + public class SkinSettings : SettingsSubsection + { + protected override LocalisableString Header => "Skins"; + + private SettingsButton importSkinsButton = null!; + private SettingsButton deleteSkinsButton = null!; + + [BackgroundDependencyLoader] + private void load(SkinManager skins, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay) + { + if (legacyImportManager?.SupportsImportFromStable == true) + { + Add(importSkinsButton = new SettingsButton + { + Text = MaintenanceSettingsStrings.ImportSkinsFromStable, + Action = () => + { + importSkinsButton.Enabled.Value = false; + legacyImportManager.ImportFromStableAsync(StableContent.Skins).ContinueWith(_ => Schedule(() => importSkinsButton.Enabled.Value = true)); + } + }); + } + + Add(deleteSkinsButton = new DangerousSettingsButton + { + Text = MaintenanceSettingsStrings.DeleteAllSkins, + Action = () => + { + dialogOverlay?.Push(new MassDeleteConfirmationDialog(() => + { + deleteSkinsButton.Enabled.Value = false; + Task.Run(() => skins.Delete()).ContinueWith(_ => Schedule(() => deleteSkinsButton.Enabled.Value = true)); + })); + } + }); + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs index b16fd9a5a1..8aff4520b5 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs index 86934ae514..047d589689 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using System.Threading.Tasks; diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 9410a87848..841a7d0abe 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -22,7 +22,10 @@ namespace osu.Game.Overlays.Settings.Sections { Children = new Drawable[] { - new GeneralSettings() + new BeatmapSettings(), + new SkinSettings(), + new CollectionsSettings(), + new ScoreSettings() }; } } diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index 351a32c72e..529f1b5ee4 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index 0207f2fd01..17228d6359 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index e864260cc6..ba707e2145 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 8b523b90b9..feb281f1b8 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/RulesetSection.cs b/osu.Game/Overlays/Settings/Sections/RulesetSection.cs index b9339d5299..a5f5810214 100644 --- a/osu.Game/Overlays/Settings/Sections/RulesetSection.cs +++ b/osu.Game/Overlays/Settings/Sections/RulesetSection.cs @@ -1,15 +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 System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Game.Rulesets; using osu.Game.Localisation; +using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections { @@ -34,9 +33,9 @@ namespace osu.Game.Overlays.Settings.Sections if (section != null) Add(section); } - catch (Exception e) + catch { - Logger.Error(e, "Failed to load ruleset settings"); + Logger.Log($"Failed to load ruleset settings for {ruleset.RulesetInfo.Name}. Please check for an update from the developer.", level: LogLevel.Error); } } } diff --git a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs index c8a46162af..28b4cd6418 100644 --- a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs +++ b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index b83600a16d..d23ef7e3e7 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -60,7 +62,8 @@ namespace osu.Game.Overlays.Settings.Sections { skinDropdown = new SkinSettingsDropdown { - LabelText = SkinSettingsStrings.CurrentSkin + LabelText = SkinSettingsStrings.CurrentSkin, + Keywords = new[] { @"skins" } }, new SettingsButton { @@ -80,12 +83,12 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown.Current = dropdownBindable; - realmSubscription = realm.RegisterForNotifications(r => realm.Realm.All() + realmSubscription = realm.RegisterForNotifications(_ => realm.Realm.All() .Where(s => !s.DeletePending) .OrderByDescending(s => s.Protected) // protected skins should be at the top. .ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase), skinsChanged); - configBindable.BindValueChanged(id => Scheduler.AddOnce(updateSelectedSkinFromConfig)); + configBindable.BindValueChanged(_ => Scheduler.AddOnce(updateSelectedSkinFromConfig)); dropdownBindable.BindValueChanged(dropdownSelectionChanged); } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index dd1b9cc2a0..85cfdb33d5 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs index fceffa09c5..7ca45bb6b8 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index b91b5c5243..708bee6fbd 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs @@ -1,33 +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; +#nullable disable + using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; +using osu.Game.Overlays.Mods.Input; namespace osu.Game.Overlays.Settings.Sections.UserInterface { public class SongSelectSettings : SettingsSubsection { - private Bindable minStars; - private Bindable maxStars; - protected override LocalisableString Header => UserInterfaceStrings.SongSelectHeader; [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - minStars = config.GetBindable(OsuSetting.DisplayStarsMinimum); - maxStars = config.GetBindable(OsuSetting.DisplayStarsMaximum); - - minStars.ValueChanged += min => maxStars.Value = Math.Max(min.NewValue, maxStars.Value); - maxStars.ValueChanged += max => minStars.Value = Math.Min(max.NewValue, minStars.Value); - Children = new Drawable[] { new SettingsCheckbox @@ -41,36 +32,18 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface LabelText = UserInterfaceStrings.ShowConvertedBeatmaps, Current = config.GetBindable(OsuSetting.ShowConvertedBeatmaps), }, - new SettingsSlider - { - LabelText = UserInterfaceStrings.StarsMinimum, - Current = config.GetBindable(OsuSetting.DisplayStarsMinimum), - KeyboardStep = 0.1f, - Keywords = new[] { "minimum", "maximum", "star", "difficulty" } - }, - new SettingsSlider - { - LabelText = UserInterfaceStrings.StarsMaximum, - Current = config.GetBindable(OsuSetting.DisplayStarsMaximum), - KeyboardStep = 0.1f, - Keywords = new[] { "minimum", "maximum", "star", "difficulty" } - }, new SettingsEnumDropdown { LabelText = UserInterfaceStrings.RandomSelectionAlgorithm, Current = config.GetBindable(OsuSetting.RandomSelectAlgorithm), + }, + new SettingsEnumDropdown + { + LabelText = UserInterfaceStrings.ModSelectHotkeyStyle, + Current = config.GetBindable(OsuSetting.ModSelectHotkeyStyle), + ClassicDefault = ModSelectHotkeyStyle.Classic } }; } - - private class MaximumStarsSlider : StarsSlider - { - public override LocalisableString TooltipText => Current.IsDefault ? UserInterfaceStrings.NoLimit : base.TooltipText; - } - - private class StarsSlider : OsuSliderBar - { - public override LocalisableString TooltipText => Current.Value.ToString(@"0.## stars"); - } } } diff --git a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs index 6228c4c99a..b2711af612 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 9e4dc763ec..5f2a416f58 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index 8a8fed4d30..efe7fb6d9e 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SettingsDropdown.cs b/osu.Game/Overlays/Settings/SettingsDropdown.cs index 3c10c084ab..347ef03b42 100644 --- a/osu.Game/Overlays/Settings/SettingsDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 199ba14b48..9408e4a9ce 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; 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 263f2f4829..db0dc8fd5e 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -1,11 +1,13 @@ // 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; +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -26,32 +28,17 @@ namespace osu.Game.Overlays.Settings Direction = FillDirection.Vertical; Padding = new MarginPadding { Top = 20, Bottom = 30, Horizontal = SettingsPanel.CONTENT_MARGINS }; - var modes = new List(); - - foreach (var ruleset in rulesets.AvailableRulesets) - { - var icon = new ConstrainedIconContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Icon = ruleset.CreateInstance().CreateIcon(), - Colour = Color4.Gray, - Size = new Vector2(20), - }; - - modes.Add(icon); - } + FillFlowContainer modes; Children = new Drawable[] { - new FillFlowContainer + modes = new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Direction = FillDirection.Full, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Children = modes, Spacing = new Vector2(5), Padding = new MarginPadding { Bottom = 10 }, }, @@ -68,6 +55,27 @@ namespace osu.Game.Overlays.Settings Origin = Anchor.TopCentre, } }; + + foreach (var ruleset in rulesets.AvailableRulesets) + { + try + { + var icon = new ConstrainedIconContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Icon = ruleset.CreateInstance().CreateIcon(), + Colour = Color4.Gray, + Size = new Vector2(20), + }; + + modes.Add(icon); + } + catch + { + Logger.Log($"Could not create ruleset icon for {ruleset.Name}. Please check for an update from the developer.", level: LogLevel.Error); + } + } } private class BuildDisplay : OsuAnimatedButton diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index f9ee8df0bd..56360fc4a1 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index ea076b77ac..c34964fa96 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index d931c53e73..4f98954289 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index da596e4d9d..dfdc850ed8 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Overlays/Settings/SettingsSidebar.cs b/osu.Game/Overlays/Settings/SettingsSidebar.cs index 4e6a1eb914..ca6bcae6e4 100644 --- a/osu.Game/Overlays/Settings/SettingsSidebar.cs +++ b/osu.Game/Overlays/Settings/SettingsSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index b95b0af11c..43f007f201 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 21391d5ccf..72788c55cd 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index a724003183..4d0f4253eb 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 1a34143e1f..c6a4cbbcaa 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SidebarIconButton.cs b/osu.Game/Overlays/Settings/SidebarIconButton.cs index 6f3d3d5d52..b32337eb2e 100644 --- a/osu.Game/Overlays/Settings/SidebarIconButton.cs +++ b/osu.Game/Overlays/Settings/SidebarIconButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 7cd8fc6d66..b28ac4ab8b 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index a5a6f9bce7..eb457032ea 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs index d55c609d3f..4548cdfb5d 100644 --- a/osu.Game/Overlays/SettingsSubPanel.cs +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/SettingsToolboxGroup.cs b/osu.Game/Overlays/SettingsToolboxGroup.cs index 077762c0d0..548d75c9a9 100644 --- a/osu.Game/Overlays/SettingsToolboxGroup.cs +++ b/osu.Game/Overlays/SettingsToolboxGroup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Extensions.EnumExtensions; diff --git a/osu.Game/Overlays/SortDirection.cs b/osu.Game/Overlays/SortDirection.cs index 3af9614972..98ac31103f 100644 --- a/osu.Game/Overlays/SortDirection.cs +++ b/osu.Game/Overlays/SortDirection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Overlays { public enum SortDirection diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index 1b0bd658d9..caec4aeed0 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -106,19 +108,7 @@ namespace osu.Game.Overlays public OverlayHeaderTabItem(T value) : base(value) { - if (!(Value is Enum enumValue)) - Text.Text = Value.ToString().ToLower(); - else - { - var localisableDescription = enumValue.GetLocalisableDescription(); - string nonLocalisableDescription = enumValue.GetDescription(); - - // If localisable == non-localisable, then we must have a basic string, so .ToLower() is used. - Text.Text = localisableDescription.Equals(nonLocalisableDescription) - ? nonLocalisableDescription.ToLower() - : localisableDescription; - } - + Text.Text = value.GetLocalisableDescription().ToLower(); Text.Font = OsuFont.GetFont(size: 14); Text.Margin = new MarginPadding { Vertical = 16.5f }; // 15px padding + 1.5px line-height difference compensation Bar.Margin = new MarginPadding { Bottom = bar_height }; diff --git a/osu.Game/Overlays/TabbableOnlineOverlay.cs b/osu.Game/Overlays/TabbableOnlineOverlay.cs index 9ceab12d3d..a99be4cc18 100644 --- a/osu.Game/Overlays/TabbableOnlineOverlay.cs +++ b/osu.Game/Overlays/TabbableOnlineOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs index 9228900e99..477991f599 100644 --- a/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/AnalogClockDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ClockDisplay.cs b/osu.Game/Overlays/Toolbar/ClockDisplay.cs index c1befbb198..0711341445 100644 --- a/osu.Game/Overlays/Toolbar/ClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/ClockDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs index ac6f563336..5592590fd9 100644 --- a/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/DigitalClockDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index b7fb2e45be..82fa20aa9c 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -14,6 +16,7 @@ using osu.Framework.Bindables; using osu.Framework.Input.Events; using osu.Game.Rulesets; using osu.Framework.Input.Bindings; +using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; namespace osu.Game.Overlays.Toolbar @@ -41,8 +44,6 @@ namespace osu.Game.Overlays.Toolbar // Toolbar and its components need keyboard input even when hidden. public override bool PropagateNonPositionalInputSubTree => true; - protected override bool BlockScrollInput => false; - public Toolbar() { RelativeSizeAxes = Axes.X; @@ -67,45 +68,115 @@ namespace osu.Game.Overlays.Toolbar Children = new Drawable[] { new ToolbarBackground(), - new FillFlowContainer + new GridContainer { - Direction = FillDirection.Horizontal, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - new ToolbarSettingsButton(), - new ToolbarHomeButton + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { - Action = () => OnHome?.Invoke() + new Container + { + Name = "Left buttons", + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Depth = float.MinValue, + Children = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.1f), + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new ToolbarSettingsButton(), + new ToolbarHomeButton + { + Action = () => OnHome?.Invoke() + }, + }, + }, + } + }, + new Container + { + Name = "Ruleset selector", + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuScrollContainer(Direction.Horizontal) + { + ScrollbarVisible = false, + RelativeSizeAxes = Axes.Both, + Masking = false, + Children = new Drawable[] + { + rulesetSelector = new ToolbarRulesetSelector() + } + }, + new Box + { + Colour = ColourInfo.GradientHorizontal(OsuColour.Gray(0.1f).Opacity(0), OsuColour.Gray(0.1f)), + Width = 50, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + } + }, + new Container + { + Name = "Right buttons", + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.1f), + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Direction = FillDirection.Horizontal, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new ToolbarNewsButton(), + new ToolbarChangelogButton(), + new ToolbarRankingsButton(), + new ToolbarBeatmapListingButton(), + new ToolbarChatButton(), + new ToolbarSocialButton(), + new ToolbarWikiButton(), + new ToolbarMusicButton(), + //new ToolbarButton + //{ + // Icon = FontAwesome.Solid.search + //}, + userButton = new ToolbarUserButton(), + new ToolbarClock(), + new ToolbarNotificationButton(), + } + }, + } + }, }, - rulesetSelector = new ToolbarRulesetSelector() - } - }, - new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Direction = FillDirection.Horizontal, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new ToolbarNewsButton(), - new ToolbarChangelogButton(), - new ToolbarRankingsButton(), - new ToolbarBeatmapListingButton(), - new ToolbarChatButton(), - new ToolbarSocialButton(), - new ToolbarWikiButton(), - new ToolbarMusicButton(), - //new ToolbarButton - //{ - // Icon = FontAwesome.Solid.search - //}, - userButton = new ToolbarUserButton(), - new ToolbarClock(), - new ToolbarNotificationButton(), } } }; diff --git a/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs b/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs index bfe36a6a0f..a2de186488 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index b686f11c13..96d4da1112 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -161,7 +163,7 @@ namespace osu.Game.Overlays.Toolbar }; } - protected override bool OnMouseDown(MouseDownEvent e) => true; + protected override bool OnMouseDown(MouseDownEvent e) => false; protected override bool OnClick(ClickEvent e) { diff --git a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs index 86bc73361a..5ce6387196 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index 2d3b33e9bc..86f87deabd 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarClock.cs b/osu.Game/Overlays/Toolbar/ToolbarClock.cs index 12529da07f..c5add6eee2 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarClock.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs index 76fbd40d66..f170ec84ac 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 0f5e8e5456..bd56c60582 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -1,25 +1,137 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Input.Events; +using osu.Framework.Threading; using osu.Game.Input.Bindings; +using osuTK.Graphics; +using osuTK.Input; namespace osu.Game.Overlays.Toolbar { public class ToolbarMusicButton : ToolbarOverlayToggleButton { + private Circle volumeBar; + protected override Anchor TooltipAnchor => Anchor.TopRight; public ToolbarMusicButton() { Hotkey = GlobalAction.ToggleNowPlaying; + AutoSizeAxes = Axes.X; } [BackgroundDependencyLoader(true)] private void load(NowPlayingOverlay music) { StateContainer = music; + + Flow.Padding = new MarginPadding { Horizontal = Toolbar.HEIGHT / 4 }; + Flow.Add(volumeDisplay = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 3f, + Height = IconContainer.Height, + Margin = new MarginPadding { Horizontal = 2.5f }, + Masking = true, + Children = new[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White.Opacity(0.25f), + }, + volumeBar = new Circle + { + RelativeSizeAxes = Axes.Both, + Height = 0f, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Colour = Color4.White, + } + } + }); + } + + [Resolved] + private AudioManager audio { get; set; } + + [Resolved(canBeNull: true)] + private VolumeOverlay volume { get; set; } + + private IBindable globalVolume; + private Container volumeDisplay; + + protected override void LoadComplete() + { + base.LoadComplete(); + + globalVolume = audio.Volume.GetBoundCopy(); + globalVolume.BindValueChanged(v => volumeBar.ResizeHeightTo((float)v.NewValue, 200, Easing.OutQuint), true); + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (!IsHovered) + return false; + + switch (e.Key) + { + case Key.Up: + focusForAdjustment(); + volume?.Adjust(GlobalAction.IncreaseVolume); + return true; + + case Key.Down: + focusForAdjustment(); + volume?.Adjust(GlobalAction.DecreaseVolume); + return true; + } + + return base.OnKeyDown(e); + } + + protected override bool OnScroll(ScrollEvent e) + { + focusForAdjustment(); + volume?.Adjust(GlobalAction.IncreaseVolume, e.ScrollDelta.Y, e.IsPrecise); + return true; + } + + private void focusForAdjustment() + { + volume?.FocusMasterVolume(); + expandVolumeBarTemporarily(); + } + + private TransformSequence expandTransform; + private ScheduledDelegate contractTransform; + + private void expandVolumeBarTemporarily() + { + // avoid starting a new transform if one is already active. + if (expandTransform == null) + { + expandTransform = volumeDisplay.ResizeWidthTo(6, 500, Easing.OutQuint); + expandTransform.Finally(_ => expandTransform = null); + } + + contractTransform?.Cancel(); + contractTransform = Scheduler.AddDelayed(() => + { + volumeDisplay.ResizeWidthTo(3f, 500, Easing.OutQuint); + }, 1000); } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs index 9b2573ad07..286cfa20f0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 313a2bc3f4..265eb044e0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 0dea71cc08..03c365e49e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs index 312fc41aab..1bda6da419 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 6e5fbf6efb..1ca492f81a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs index a70a0d8a71..31c6802fda 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; using osu.Game.Rulesets; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index c53f4a55d9..c3d48bc60e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index 1e00afc5fd..f8ee39d56e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index d8ba07dc3b..a93ba17c5b 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs index a521219b4f..5511902fa8 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 518a2bf9c8..c0ca63bbd9 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/VersionManager.cs b/osu.Game/Overlays/VersionManager.cs index fe6613fba2..a1cfdf4594 100644 --- a/osu.Game/Overlays/VersionManager.cs +++ b/osu.Game/Overlays/VersionManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Development; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index e9d3b31207..744b2bafbd 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs index c601ce4130..f2b637c104 100644 --- a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Containers; using osu.Framework.Input; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 24d9f785f2..e01890ddc2 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using osu.Framework; diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 9d2ed3f837..4cedd87eac 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; @@ -140,11 +142,16 @@ namespace osu.Game.Overlays private ScheduledDelegate popOutDelegate; + public void FocusMasterVolume() + { + volumeMeters.Select(volumeMeterMaster); + } + public override void Show() { // Focus on the master meter as a default if previously hidden if (State.Value == Visibility.Hidden) - volumeMeters.Select(volumeMeterMaster); + FocusMasterVolume(); if (State.Value == Visibility.Visible) schedulePopOut(); diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 52ae4dbdbb..faf2cca8cf 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs index 789ed457a4..7754c1d450 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Markdig.Extensions.Yaml; using Markdig.Syntax; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs index 27d1fe9b2f..1c7a08930b 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax.Inlines; using osu.Game.Graphics.Containers.Markdown; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 501e00bc00..5ce3f179a4 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index 11cab80a57..64d7e20d9b 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Extensions.Yaml; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Wiki/WikiArticlePage.cs b/osu.Game/Overlays/Wiki/WikiArticlePage.cs index 0061bff8ea..f4ba0a4d8d 100644 --- a/osu.Game/Overlays/Wiki/WikiArticlePage.cs +++ b/osu.Game/Overlays/Wiki/WikiArticlePage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Markdig.Syntax; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 3e81d2cffe..fc8df03892 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Wiki/WikiMainPage.cs b/osu.Game/Overlays/Wiki/WikiMainPage.cs index 9416ec77f1..67e4bdf2e5 100644 --- a/osu.Game/Overlays/Wiki/WikiMainPage.cs +++ b/osu.Game/Overlays/Wiki/WikiMainPage.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs index 7e7e005586..552770f098 100644 --- a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs +++ b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Markdig.Syntax; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Wiki/WikiSidebar.cs b/osu.Game/Overlays/Wiki/WikiSidebar.cs index da96885fb5..78ce9c8a24 100644 --- a/osu.Game/Overlays/Wiki/WikiSidebar.cs +++ b/osu.Game/Overlays/Wiki/WikiSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Markdig.Syntax; using Markdig.Syntax.Inlines; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Wiki/WikiTableOfContents.cs b/osu.Game/Overlays/Wiki/WikiTableOfContents.cs index c0615dce1f..d60d728aca 100644 --- a/osu.Game/Overlays/Wiki/WikiTableOfContents.cs +++ b/osu.Game/Overlays/Wiki/WikiTableOfContents.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 4015d8e196..148d2977c7 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; @@ -98,6 +100,11 @@ namespace osu.Game.Overlays private void onPathChanged(ValueChangedEvent e) { + // the path could change as a result of redirecting to a newer location of the same page. + // we already have the correct wiki data, so we can safely return here. + if (e.NewValue == wikiData.Value?.Path) + return; + cancellationToken?.Cancel(); request?.Cancel(); @@ -119,6 +126,7 @@ namespace osu.Game.Overlays private void onSuccess(APIWikiPage response) { wikiData.Value = response; + path.Value = response.Path; if (response.Layout == index_path) { diff --git a/osu.Game/PerformFromMenuRunner.cs b/osu.Game/PerformFromMenuRunner.cs index ae9879fb5a..eae13fe5d0 100644 --- a/osu.Game/PerformFromMenuRunner.cs +++ b/osu.Game/PerformFromMenuRunner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Performance/HighPerformanceSession.cs b/osu.Game/Performance/HighPerformanceSession.cs index 3ef0e0bf93..dd5de03077 100644 --- a/osu.Game/Performance/HighPerformanceSession.cs +++ b/osu.Game/Performance/HighPerformanceSession.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Properties/AssemblyInfo.cs b/osu.Game/Properties/AssemblyInfo.cs index 1b77e45891..dde1af6461 100644 --- a/osu.Game/Properties/AssemblyInfo.cs +++ b/osu.Game/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game/Rulesets/AssemblyRulesetStore.cs b/osu.Game/Rulesets/AssemblyRulesetStore.cs index 7313a77aa5..03554ef2db 100644 --- a/osu.Game/Rulesets/AssemblyRulesetStore.cs +++ b/osu.Game/Rulesets/AssemblyRulesetStore.cs @@ -7,8 +7,6 @@ using System.Linq; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Platform; -#nullable enable - namespace osu.Game.Rulesets { /// diff --git a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs index 5a3ad5e786..af315bfb28 100644 --- a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Configuration.Tracking; diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 30bb95ba72..5a03d66b84 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -94,7 +96,7 @@ namespace osu.Game.Rulesets.Configuration databasedSettings.Add(setting); } - bindable.ValueChanged += b => + bindable.ValueChanged += _ => { lock (pendingWrites) pendingWrites.Add(lookup); diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs index ec3d22b67a..bd45482235 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -1,9 +1,11 @@ // Copyright (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.Game.Beatmaps; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Difficulty @@ -24,11 +26,12 @@ namespace osu.Game.Rulesets.Difficulty protected const int ATTRIB_ID_SCORE_MULTIPLIER = 15; protected const int ATTRIB_ID_FLASHLIGHT = 17; protected const int ATTRIB_ID_SLIDER_FACTOR = 19; + protected const int ATTRIB_ID_SPEED_NOTE_COUNT = 21; /// /// The mods which were applied to the beatmap. /// - public Mod[] Mods { get; set; } + public Mod[] Mods { get; set; } = Array.Empty(); /// /// The combined star rating of all skills. @@ -72,7 +75,8 @@ namespace osu.Game.Rulesets.Difficulty /// Reads osu-web database attribute mappings into this object. /// /// The attribute mappings. - public virtual void FromDatabaseAttributes(IReadOnlyDictionary values) + /// The where more information about the beatmap may be extracted from (such as AR/CS/OD/etc). + public virtual void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { } } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index b5aec0d659..9c58a53b97 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -67,7 +69,7 @@ namespace osu.Game.Rulesets.Difficulty foreach (var skill in skills) { cancellationToken.ThrowIfCancellationRequested(); - skill.ProcessInternal(hitObject); + skill.Process(hitObject); } } @@ -108,7 +110,7 @@ namespace osu.Game.Rulesets.Difficulty foreach (var skill in skills) { cancellationToken.ThrowIfCancellationRequested(); - skill.ProcessInternal(hitObject); + skill.Process(hitObject); } attribs.Add(new TimedDifficultyAttributes(hitObject.EndTime * clockRate, CreateDifficultyAttributes(progressiveBeatmap, playableMods, skills, clockRate))); diff --git a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs b/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs index e8c4c71913..15b90e5147 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs index 273d8613c5..bd971db476 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Difficulty { /// diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 1e5dda253f..4465f1a328 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 4c55249661..38a35ddb3b 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Scoring; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs b/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs index 7958bc174e..76dfca3db7 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Difficulty { /// diff --git a/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs index 5edfb2207b..9ce0906dea 100644 --- a/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs +++ b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs @@ -1,6 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Collections.Generic; +using System.Linq; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Difficulty.Preprocessing @@ -10,6 +14,13 @@ namespace osu.Game.Rulesets.Difficulty.Preprocessing /// public class DifficultyHitObject { + private readonly IReadOnlyList difficultyHitObjects; + + /// + /// The index of this in the list of all s. + /// + public int Index; + /// /// The this wraps. /// @@ -41,13 +52,21 @@ namespace osu.Game.Rulesets.Difficulty.Preprocessing /// 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) + /// The list of s in the current beatmap. + /// The index of this in list. + public DifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, List objects, int index) { + difficultyHitObjects = objects; + Index = index; BaseObject = hitObject; LastObject = lastObject; DeltaTime = (hitObject.StartTime - lastObject.StartTime) / clockRate; StartTime = hitObject.StartTime / clockRate; EndTime = hitObject.GetEndTime() / clockRate; } + + public DifficultyHitObject Previous(int backwardsIndex) => difficultyHitObjects.ElementAtOrDefault(Index - (backwardsIndex + 1)); + + public DifficultyHitObject Next(int forwardsIndex) => difficultyHitObjects.ElementAtOrDefault(Index + (forwardsIndex + 1)); } } diff --git a/osu.Game/Rulesets/Difficulty/Skills/Skill.cs b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs index b5c94ad806..44abbaaf41 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/Skill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs @@ -1,9 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Preprocessing; -using osu.Game.Rulesets.Difficulty.Utils; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Difficulty.Skills @@ -12,21 +13,10 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// A bare minimal abstract skill for fully custom skill implementations. /// /// - /// This class should be considered a "processing" class and not persisted, as it keeps references to - /// gameplay objects after processing is run (see ). + /// This class should be considered a "processing" class and not persisted. /// public abstract class Skill { - /// - /// s that were processed previously. They can affect the strain values of the following objects. - /// - protected readonly ReverseQueue Previous; - - /// - /// Number of previous s to keep inside the queue. - /// - protected virtual int HistoryLength => 1; - /// /// Mods for use in skill calculations. /// @@ -37,24 +27,13 @@ namespace osu.Game.Rulesets.Difficulty.Skills protected Skill(Mod[] mods) { this.mods = mods; - Previous = new ReverseQueue(HistoryLength + 1); - } - - internal void ProcessInternal(DifficultyHitObject current) - { - while (Previous.Count > HistoryLength) - Previous.Dequeue(); - - Process(current); - - Previous.Enqueue(current); } /// /// Process a . /// /// The to process. - protected abstract void Process(DifficultyHitObject current); + public abstract void Process(DifficultyHitObject current); /// /// Returns the calculated difficulty value representing all s that have been processed up to this point. diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs index d8babf2f32..6abde64eb7 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; @@ -34,7 +36,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills { } - protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime); + protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => CurrentStrain * strainDecay(time - current.Previous(0).StartTime); protected override double StrainValueAt(DifficultyHitObject current) { diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index 97266562e4..4beba22e05 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -44,16 +46,16 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// /// Process a and update current strain values accordingly. /// - protected sealed override void Process(DifficultyHitObject current) + public sealed override void Process(DifficultyHitObject current) { // The first object doesn't generate a strain, so we begin with an incremented section end - if (Previous.Count == 0) + if (current.Index == 0) currentSectionEnd = Math.Ceiling(current.StartTime / SectionLength) * SectionLength; while (current.StartTime > currentSectionEnd) { saveCurrentPeak(); - startNewSectionFrom(currentSectionEnd); + startNewSectionFrom(currentSectionEnd, current); currentSectionEnd += SectionLength; } @@ -72,19 +74,21 @@ namespace osu.Game.Rulesets.Difficulty.Skills /// Sets the initial strain level for a new section. /// /// The beginning of the new section in milliseconds. - private void startNewSectionFrom(double time) + /// The current hit object. + private void startNewSectionFrom(double time, DifficultyHitObject current) { // The maximum strain of the new section is not zero by default // This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level. - currentSectionPeak = CalculateInitialStrain(time); + currentSectionPeak = CalculateInitialStrain(time, current); } /// /// Retrieves the peak strain at a point in time. /// /// The time to retrieve the peak strain at. + /// The current hit object. /// The peak strain. - protected abstract double CalculateInitialStrain(double time); + protected abstract double CalculateInitialStrain(double time, DifficultyHitObject current); /// /// Returns a live enumerable of the peak strains for each section of the beatmap, diff --git a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs index c07d1cd46e..a07827d50b 100644 --- a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Rulesets.Difficulty diff --git a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs index bc0eb8af88..d20eb5e885 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs b/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs index 57db9df3ca..3dc2d133ba 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/EFRulesetInfo.cs b/osu.Game/Rulesets/EFRulesetInfo.cs index 4174aa773c..bd67bdb93c 100644 --- a/osu.Game/Rulesets/EFRulesetInfo.cs +++ b/osu.Game/Rulesets/EFRulesetInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; @@ -77,7 +79,7 @@ namespace osu.Game.Rulesets public int OnlineID { get => ID ?? -1; - set => ID = value >= 0 ? value : (int?)null; + set => ID = value >= 0 ? value : null; } #endregion diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 6ed91e983a..a89a0e76a9 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Edit.Checks; diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs index 6feee82bda..53bdf3140c 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifierContext.cs @@ -3,8 +3,6 @@ using osu.Game.Beatmaps; -#nullable enable - namespace osu.Game.Rulesets.Edit { /// diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs index a285979fd2..93fb7b9ab8 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioInVideo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using osu.Game.IO.FileAbstraction; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs index 94c48c300a..fa3e114c55 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index ec2ff68aad..96254ba6fd 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs index 067800b409..96840fd344 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 1f65752fa6..b15a9f5331 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs index ba5fbcf58d..02579b675d 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckConcurrentObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs b/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs index 3358e81d5f..b25abb0cfc 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFewHitsounds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Game.Audio; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs index a1605a11d0..67d480c28c 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckFilePresence.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs index a4ff921b7e..00b1ca9dc9 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -72,7 +74,7 @@ namespace osu.Game.Rulesets.Edit.Checks if (edgeType == EdgeType.None) yield break; - string postfix = hitObject is IHasDuration ? edgeType.ToString().ToLower() : null; + string postfix = hitObject is IHasDuration ? edgeType.ToString().ToLowerInvariant() : null; if (maxVolume <= muted_threshold) { diff --git a/osu.Game/Rulesets/Edit/Checks/CheckTooShortAudioFiles.cs b/osu.Game/Rulesets/Edit/Checks/CheckTooShortAudioFiles.cs index 6015d0a1b2..2a222aece0 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckTooShortAudioFiles.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckTooShortAudioFiles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using System.Linq; @@ -63,7 +65,7 @@ namespace osu.Game.Rulesets.Edit.Checks } } - private bool hasAudioExtension(string filename) => audioExtensions.Any(filename.ToLower().EndsWith); + private bool hasAudioExtension(string filename) => audioExtensions.Any(filename.ToLowerInvariant().EndsWith); private bool probablyHasAudioData(Stream data) => data.Length > min_bytes_threshold; public class IssueTemplateTooShort : IssueTemplate diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs index ded1bb54ca..a3c52cf547 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnsnappedObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckZeroByteFiles.cs b/osu.Game/Rulesets/Edit/Checks/CheckZeroByteFiles.cs index 75cb08002f..987711188e 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckZeroByteFiles.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckZeroByteFiles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.IO; using osu.Game.Extensions; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckZeroLengthObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckZeroLengthObjects.cs index b9be94736b..3b30fab934 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckZeroLengthObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckZeroLengthObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/CheckCategory.cs b/osu.Game/Rulesets/Edit/Checks/Components/CheckCategory.cs index ae943cfda9..3e2150fe0b 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/CheckCategory.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/CheckCategory.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Edit.Checks.Components { /// diff --git a/osu.Game/Rulesets/Edit/Checks/Components/CheckMetadata.cs b/osu.Game/Rulesets/Edit/Checks/Components/CheckMetadata.cs index cebb2f5455..5c9021ba61 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/CheckMetadata.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/CheckMetadata.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Edit.Checks.Components { public class CheckMetadata diff --git a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs index 141de55f1d..333ec0a810 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; namespace osu.Game.Rulesets.Edit.Checks.Components diff --git a/osu.Game/Rulesets/Edit/Checks/Components/Issue.cs b/osu.Game/Rulesets/Edit/Checks/Components/Issue.cs index 2bc9930e8f..b3f227f364 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/Issue.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/Issue.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/IssueTemplate.cs b/osu.Game/Rulesets/Edit/Checks/Components/IssueTemplate.cs index 97df79ecd8..9101d83fa7 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/IssueTemplate.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/IssueTemplate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Humanizer; using osu.Framework.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Rulesets/Edit/Checks/Components/IssueType.cs b/osu.Game/Rulesets/Edit/Checks/Components/IssueType.cs index 1f708209fe..a957cbc296 100644 --- a/osu.Game/Rulesets/Edit/Checks/Components/IssueType.cs +++ b/osu.Game/Rulesets/Edit/Checks/Components/IssueType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Edit.Checks.Components { /// diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index aaee15eae8..4726211666 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; diff --git a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs index 392a5db9da..9588a092a8 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs b/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs index bde426f56a..7dcc90b16d 100644 --- a/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs +++ b/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Overlays; diff --git a/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs b/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs index c6cc09a16c..d3371d3543 100644 --- a/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs +++ b/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index f6fdb228ce..37c66037eb 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs b/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs index 77dc55c6ef..c74fb83d58 100644 --- a/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/HitObjectSelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Primitives; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs b/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs index 616f854cd7..dbad407b75 100644 --- a/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/IBeatSnapProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Edit { public interface IBeatSnapProvider diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index 06f0abedb0..826bffef5f 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs index b12e1437dc..5ad1cc78ff 100644 --- a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs b/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs index a6a6e39e23..ad129e068d 100644 --- a/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osuTK; diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 0c0c5990d1..c8196b6865 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -1,6 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Linq; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -71,6 +74,10 @@ namespace osu.Game.Rulesets.Edit /// Whether this call is committing a value for HitObject.StartTime and continuing with further adjustments. protected void BeginPlacement(bool commitStart = false) { + var nearestSampleControlPoint = beatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.SampleControlPoint?.DeepClone() as SampleControlPoint; + + HitObject.SampleControlPoint = nearestSampleControlPoint ?? new SampleControlPoint(); + placementHandler.BeginPlacement(HitObject); if (commitStart) PlacementActive = PlacementState.Active; @@ -122,10 +129,10 @@ namespace osu.Game.Rulesets.Edit switch (e) { - case ScrollEvent _: + case ScrollEvent: return false; - case DoubleClickEvent _: + case DoubleClickEvent: return false; case MouseButtonEvent mouse: diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 5e5bc9036d..fc24b55d21 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Edit/SnapResult.cs b/osu.Game/Rulesets/Edit/SnapResult.cs index 31dd2b9496..9a1405b97c 100644 --- a/osu.Game/Rulesets/Edit/SnapResult.cs +++ b/osu.Game/Rulesets/Edit/SnapResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.UI; using osuTK; diff --git a/osu.Game/Rulesets/Edit/SnapType.cs b/osu.Game/Rulesets/Edit/SnapType.cs index 6761356331..6eb46457c8 100644 --- a/osu.Game/Rulesets/Edit/SnapType.cs +++ b/osu.Game/Rulesets/Edit/SnapType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Rulesets.Edit diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 0a01ac4320..707645edeb 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Rulesets.Edit.Tools diff --git a/osu.Game/Rulesets/Edit/Tools/SelectTool.cs b/osu.Game/Rulesets/Edit/Tools/SelectTool.cs index c050766b23..9640830a09 100644 --- a/osu.Game/Rulesets/Edit/Tools/SelectTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/SelectTool.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Rulesets/ILegacyRuleset.cs b/osu.Game/Rulesets/ILegacyRuleset.cs index f4b03baccd..a8cfed4866 100644 --- a/osu.Game/Rulesets/ILegacyRuleset.cs +++ b/osu.Game/Rulesets/ILegacyRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets { public interface ILegacyRuleset diff --git a/osu.Game/Rulesets/IRulesetConfigCache.cs b/osu.Game/Rulesets/IRulesetConfigCache.cs index b946b43905..3943a62e59 100644 --- a/osu.Game/Rulesets/IRulesetConfigCache.cs +++ b/osu.Game/Rulesets/IRulesetConfigCache.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Game.Rulesets.Configuration; namespace osu.Game.Rulesets diff --git a/osu.Game/Rulesets/IRulesetInfo.cs b/osu.Game/Rulesets/IRulesetInfo.cs index 60a02212fc..5af6ef07cf 100644 --- a/osu.Game/Rulesets/IRulesetInfo.cs +++ b/osu.Game/Rulesets/IRulesetInfo.cs @@ -4,8 +4,6 @@ using System; using osu.Game.Database; -#nullable enable - namespace osu.Game.Rulesets { /// diff --git a/osu.Game/Rulesets/IRulesetStore.cs b/osu.Game/Rulesets/IRulesetStore.cs index 08d907810b..f4895118e3 100644 --- a/osu.Game/Rulesets/IRulesetStore.cs +++ b/osu.Game/Rulesets/IRulesetStore.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; -#nullable enable - namespace osu.Game.Rulesets { public interface IRulesetStore diff --git a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs index 29b771a81d..c2b27d4ce8 100644 --- a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index d25d46c6e2..0d8b8429d8 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using JetBrains.Annotations; diff --git a/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs b/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs index b38b83b534..2bc5a62983 100644 --- a/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs b/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs index d2a434058d..f08b43e72a 100644 --- a/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs +++ b/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Judgements diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 99dce82ec2..770f656e8f 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index e3b2501cdc..2685cb4e2a 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs index c8e7284f5d..599e81f2b8 100644 --- a/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs +++ b/osu.Game/Rulesets/Mods/DifficultyAdjustSettingsControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -8,6 +10,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; namespace osu.Game.Rulesets.Mods @@ -53,8 +56,8 @@ namespace osu.Game.Rulesets.Mods { base.LoadComplete(); - Current.BindValueChanged(current => updateCurrentFromSlider()); - beatmap.BindValueChanged(b => updateCurrentFromSlider(), true); + Current.BindValueChanged(_ => updateCurrentFromSlider()); + beatmap.BindValueChanged(_ => updateCurrentFromSlider(), true); sliderDisplayCurrent.BindValueChanged(number => { @@ -101,9 +104,9 @@ namespace osu.Game.Rulesets.Mods { InternalChildren = new Drawable[] { - new SettingsSlider + new OsuSliderBar { - ShowsDefaultIndicator = false, + RelativeSizeAxes = Axes.X, Current = currentNumber, KeyboardStep = 0.1f, } diff --git a/osu.Game/Rulesets/Mods/DifficultyBindable.cs b/osu.Game/Rulesets/Mods/DifficultyBindable.cs index 6cfae0b085..34e9fe40a3 100644 --- a/osu.Game/Rulesets/Mods/DifficultyBindable.cs +++ b/osu.Game/Rulesets/Mods/DifficultyBindable.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mods /// /// A function that can extract the current value of this setting from a beatmap difficulty for display purposes. /// - public Func ReadCurrentFromDifficulty; + public Func? ReadCurrentFromDifficulty; public float Precision { diff --git a/osu.Game/Rulesets/Mods/ICreateReplayData.cs b/osu.Game/Rulesets/Mods/ICreateReplayData.cs index 7d208e9000..c13e65c7b8 100644 --- a/osu.Game/Rulesets/Mods/ICreateReplayData.cs +++ b/osu.Game/Rulesets/Mods/ICreateReplayData.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mods /// public readonly ModCreatedUser User; - public ModReplayData(Replay replay, ModCreatedUser user = null) + public ModReplayData(Replay replay, ModCreatedUser? user = null) { Replay = replay; User = user ?? new ModCreatedUser(); @@ -56,6 +56,7 @@ namespace osu.Game.Rulesets.Mods public class ModCreatedUser : IUser { public int OnlineID => APIUser.SYSTEM_USER_ID; + public CountryCode CountryCode => default; public bool IsBot => true; public string Username { get; set; } = string.Empty; diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index af1550f8a9..0f3d758f74 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Mods [JsonIgnore] public virtual Type[] IncompatibleMods => Array.Empty(); - private IReadOnlyList settingsBacking; + private IReadOnlyList? settingsBacking; /// /// A list of the all settings within this mod. @@ -126,6 +126,11 @@ namespace osu.Game.Rulesets.Mods .Cast() .ToList(); + /// + /// Whether all settings in this mod are set to their default state. + /// + protected virtual bool UsesDefaultConfiguration => Settings.All(s => s.IsDefault); + /// /// Creates a copy of this initialised to a default state. /// @@ -214,8 +219,8 @@ namespace osu.Game.Rulesets.Mods public bool Equals(IBindable x, IBindable y) { - object xValue = x?.GetUnderlyingSettingValue(); - object yValue = y?.GetUnderlyingSettingValue(); + object xValue = x.GetUnderlyingSettingValue(); + object yValue = y.GetUnderlyingSettingValue(); return EqualityComparer.Default.Equals(xValue, yValue); } diff --git a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs index fb291fe10f..38d26ed05a 100644 --- a/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs +++ b/osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mods public override bool ValidForMultiplayer => false; public override bool ValidForMultiplayerAsFreeMod => false; - public override Type[] IncompatibleMods => new[] { typeof(ModRateAdjust), typeof(ModTimeRamp) }; + public override Type[] IncompatibleMods => new[] { typeof(ModRateAdjust), typeof(ModTimeRamp), typeof(ModAutoplay) }; [SettingSource("Initial rate", "The starting speed of the track")] public BindableNumber InitialRate { get; } = new BindableDouble @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Mods // Apply a fixed rate change when missing, allowing the player to catch up when the rate is too fast. private const double rate_change_on_miss = 0.95d; - private IAdjustableAudioComponent track; + private IAdjustableAudioComponent? track; private double targetRate = 1d; /// @@ -163,7 +163,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToDrawableHitObject(DrawableHitObject drawable) { - drawable.OnNewResult += (o, result) => + drawable.OnNewResult += (_, result) => { if (ratesForRewinding.ContainsKey(result.HitObject)) return; if (!shouldProcessResult(result)) return; @@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Mods updateTargetRate(); }; - drawable.OnRevertResult += (o, result) => + drawable.OnRevertResult += (_, result) => { if (!ratesForRewinding.ContainsKey(result.HitObject)) return; if (!shouldProcessResult(result)) return; diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 0ebe11b393..ab49dd5575 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mods public override bool ValidForMultiplayer => false; public override bool ValidForMultiplayerAsFreeMod => false; - public override Type[] IncompatibleMods => new[] { typeof(ModCinema), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail) }; + public override Type[] IncompatibleMods => new[] { typeof(ModCinema), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail), typeof(ModAdaptiveSpeed) }; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 8a9b0cddc8..cdfb36ebbc 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mods { public abstract class ModBlockFail : Mod, IApplicableFailOverride, IApplicableToHUD, IReadFromConfig { - private Bindable showHealthBar; + private readonly Bindable showHealthBar = new Bindable(); /// /// We never fail, 'yo. @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mods public void ReadFromConfig(OsuConfigManager config) { - showHealthBar = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail); + config.BindWith(OsuSetting.ShowHealthDisplayWhenCantFail, showHealthBar); } public void ApplyToHUD(HUDOverlay overlay) diff --git a/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs b/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs index 2ac0f59d84..c4396e440e 100644 --- a/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs +++ b/osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mods private int retries; - private BindableNumber health; + private readonly BindableNumber health = new BindableDouble(); public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { - health = healthProcessor.Health.GetBoundCopy(); + health.BindTo(healthProcessor.Health); } } } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index b449f3f64d..e8bc6c2026 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -94,13 +94,13 @@ namespace osu.Game.Rulesets.Mods { public readonly BindableInt Combo = new BindableInt(); - private IShader shader; + private IShader shader = null!; protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(this); public override bool RemoveCompletedTransforms => false; - public List Breaks; + public List Breaks = new List(); private readonly float defaultFlashlightSize; private readonly float sizeMultiplier; @@ -205,7 +205,7 @@ namespace osu.Game.Rulesets.Mods { protected new Flashlight Source => (Flashlight)base.Source; - private IShader shader; + private IShader shader = null!; private Quad screenSpaceDrawQuad; private Vector2 flashlightPosition; private Vector2 flashlightSize; @@ -253,7 +253,7 @@ namespace osu.Game.Rulesets.Mods protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - quadBatch?.Dispose(); + quadBatch.Dispose(); } } } diff --git a/osu.Game/Rulesets/Mods/ModMuted.cs b/osu.Game/Rulesets/Mods/ModMuted.cs index 84341faab7..55d5abfa82 100644 --- a/osu.Game/Rulesets/Mods/ModMuted.cs +++ b/osu.Game/Rulesets/Mods/ModMuted.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mods private readonly BindableNumber mainVolumeAdjust = new BindableDouble(0.5); private readonly BindableNumber metronomeVolumeAdjust = new BindableDouble(0.5); - private BindableNumber currentCombo; + private readonly BindableNumber currentCombo = new BindableInt(); [SettingSource("Enable metronome", "Add a metronome beat to help you keep track of the rhythm.")] public BindableBool EnableMetronome { get; } = new BindableBool @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - currentCombo = scoreProcessor.Combo.GetBoundCopy(); + currentCombo.BindTo(scoreProcessor.Combo); currentCombo.BindValueChanged(combo => { double dimFactor = MuteComboCount.Value == 0 ? 1 : (double)combo.NewValue / MuteComboCount.Value; diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 7997204450..c4417ec509 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -55,10 +55,10 @@ namespace osu.Game.Rulesets.Mods public class NightcoreBeatContainer : BeatSyncedContainer { - private PausableSkinnableSound hatSample; - private PausableSkinnableSound clapSample; - private PausableSkinnableSound kickSample; - private PausableSkinnableSound finishSample; + private PausableSkinnableSound? hatSample; + private PausableSkinnableSound? clapSample; + private PausableSkinnableSound? kickSample; + private PausableSkinnableSound? finishSample; private int? firstBeat; diff --git a/osu.Game/Rulesets/Mods/ModNoScope.cs b/osu.Game/Rulesets/Mods/ModNoScope.cs index 7a935eb38f..1b9ce833ad 100644 --- a/osu.Game/Rulesets/Mods/ModNoScope.cs +++ b/osu.Game/Rulesets/Mods/ModNoScope.cs @@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Mods protected const float TRANSITION_DURATION = 100; - protected BindableNumber CurrentCombo; + protected readonly BindableNumber CurrentCombo = new BindableInt(); - protected IBindable IsBreakTime; + protected readonly IBindable IsBreakTime = new Bindable(); protected float ComboBasedAlpha; @@ -40,14 +40,14 @@ namespace osu.Game.Rulesets.Mods public void ApplyToPlayer(Player player) { - IsBreakTime = player.IsBreakTime.GetBoundCopy(); + IsBreakTime.BindTo(player.IsBreakTime); } public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { if (HiddenComboCount.Value == 0) return; - CurrentCombo = scoreProcessor.Combo.GetBoundCopy(); + CurrentCombo.BindTo(scoreProcessor.Combo); CurrentCombo.BindValueChanged(combo => { ComboBasedAlpha = Math.Max(MIN_ALPHA, 1 - (float)combo.NewValue / HiddenComboCount.Value); diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index 98abda872b..7031489d0e 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -44,12 +44,12 @@ namespace osu.Game.Rulesets.Mods Precision = 0.01, }; - private IAdjustableAudioComponent track; + private IAdjustableAudioComponent? track; protected ModTimeRamp() { // for preview purpose at song select. eventually we'll want to be able to update every frame. - FinalRate.BindValueChanged(val => applyRateAdjustment(double.PositiveInfinity), true); + FinalRate.BindValueChanged(_ => applyRateAdjustment(double.PositiveInfinity), true); AdjustPitch.BindValueChanged(applyPitchAdjustment); } diff --git a/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs b/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs index b58ee5ff36..2e3619ec63 100644 --- a/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs +++ b/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mods /// /// The first adjustable object. /// - protected HitObject FirstObject { get; private set; } + protected HitObject? FirstObject { get; private set; } /// /// Whether the visibility of should be increased. @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Mods { FirstObject = getFirstAdjustableObjectRecursive(beatmap.HitObjects); - HitObject getFirstAdjustableObjectRecursive(IReadOnlyList hitObjects) + HitObject? getFirstAdjustableObjectRecursive(IReadOnlyList hitObjects) { foreach (var h in hitObjects) { @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mods /// The to check. /// The which may be equal to or contain as a nested object. /// Whether is equal to or nested within . - private bool isObjectEqualToOrNestedIn(HitObject toCheck, HitObject target) + private bool isObjectEqualToOrNestedIn(HitObject toCheck, HitObject? target) { if (target == null) return false; diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs index d71a499119..dec81d9bbd 100644 --- a/osu.Game/Rulesets/Objects/BarLineGenerator.cs +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs index b2d9f50602..4faf0920d1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs +++ b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects.Drawables { public enum ArmedState diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 2e573a7f85..39ccaa2e5d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 57b897e5b5..d20e0616e5 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -106,7 +108,7 @@ namespace osu.Game.Rulesets.Objects if (legacyInfo != null) DifficultyControlPoint = (DifficultyControlPoint)legacyInfo.DifficultyPointAt(StartTime).DeepClone(); - else if (DifficultyControlPoint == DifficultyControlPoint.DEFAULT) + else if (ReferenceEquals(DifficultyControlPoint, DifficultyControlPoint.DEFAULT)) DifficultyControlPoint = new DifficultyControlPoint(); DifficultyControlPoint.Time = StartTime; @@ -116,7 +118,7 @@ namespace osu.Game.Rulesets.Objects // This is done here after ApplyDefaultsToSelf as we may require custom defaults to be applied to have an accurate end time. if (legacyInfo != null) SampleControlPoint = (SampleControlPoint)legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency).DeepClone(); - else if (SampleControlPoint == SampleControlPoint.DEFAULT) + else if (ReferenceEquals(SampleControlPoint, SampleControlPoint.DEFAULT)) SampleControlPoint = new SampleControlPoint(); SampleControlPoint.Time = this.GetEndTime() + control_point_leniency; diff --git a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs index 096dad88bd..9af4cf3544 100644 --- a/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs +++ b/osu.Game/Rulesets/Objects/HitObjectLifetimeEntry.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.Performance; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game/Rulesets/Objects/HitObjectParser.cs b/osu.Game/Rulesets/Objects/HitObjectParser.cs index d3c29d90ce..9728a4393b 100644 --- a/osu.Game/Rulesets/Objects/HitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/HitObjectParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects { public abstract class HitObjectParser diff --git a/osu.Game/Rulesets/Objects/HitObjectProperty.cs b/osu.Game/Rulesets/Objects/HitObjectProperty.cs new file mode 100644 index 0000000000..f1df83f80c --- /dev/null +++ b/osu.Game/Rulesets/Objects/HitObjectProperty.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. + +#nullable disable + +using JetBrains.Annotations; +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets.Objects +{ + /// + /// Represents a wrapper containing a lazily-initialised , backed by a temporary field used for storage until initialisation. + /// + public struct HitObjectProperty + { + [CanBeNull] + private Bindable backingBindable; + + /// + /// A temporary field to store the current value to, prior to 's initialisation. + /// + private T backingValue; + + /// + /// The underlying , only initialised on first access. + /// + public Bindable Bindable => backingBindable ??= new Bindable(defaultValue) { Value = backingValue }; + + /// + /// The current value, derived from and delegated to if initialised, or a temporary field otherwise. + /// + public T Value + { + get => backingBindable != null ? backingBindable.Value : backingValue; + set + { + if (backingBindable != null) + backingBindable.Value = value; + else + backingValue = value; + } + } + + private readonly T defaultValue; + + public HitObjectProperty(T value = default) + { + backingValue = defaultValue = value; + backingBindable = null; + } + } +} diff --git a/osu.Game/Rulesets/Objects/IBarLine.cs b/osu.Game/Rulesets/Objects/IBarLine.cs index 14df80e3b9..8cdead6776 100644 --- a/osu.Game/Rulesets/Objects/IBarLine.cs +++ b/osu.Game/Rulesets/Objects/IBarLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects { /// diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs index 12b4812824..9facfec96f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 2beb6bdbf2..4861e8b3f7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Game.Audio; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs index fb1afed3b4..62726019bb 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 014494ec54..cccb66d92b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Catch diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs index e3b0d8a498..d95f97624d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index d3d1196eae..b289299a63 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Game.Rulesets.Objects.Types; using System; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 9ff92fcc75..bd2713a7d1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 0b69817c13..639cacb128 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 386eb8d3ee..6f1968b41d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Game.Audio; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 2fa4766c1d..b6594d0206 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 84cde5fa95..330ebf72c7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index c05aaceb9c..dcbaf22c51 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index 069366bad3..33b390e3ba 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 cb98721be5..7a88a31bd5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using System.Collections.Generic; using osu.Game.Audio; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index e947690668..2f8e9dd352 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 e9e5ca8c94..d49e9fe9db 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 cb5178ce48..980d37ccd5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 1eafc4e68b..d62e8cd04c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using System.Collections.Generic; using osu.Game.Audio; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index 821554f7ee..a391c8cb43 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 1d5ecb1ef3..ec8d7971ec 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Taiko diff --git a/osu.Game/Rulesets/Objects/PathControlPoint.cs b/osu.Game/Rulesets/Objects/PathControlPoint.cs index 53eb430fa3..ae9fa08085 100644 --- a/osu.Game/Rulesets/Objects/PathControlPoint.cs +++ b/osu.Game/Rulesets/Objects/PathControlPoint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs b/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs index 9c6097a048..8dc588da9e 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PoolableDrawableWithLifetime.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs index d35933dba8..07a80895e6 100644 --- a/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs +++ b/osu.Game/Rulesets/Objects/Pooling/PooledDrawableWithLifetimeContainer.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index bae5a5e8d9..d32a7cb16d 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index e0c62fe359..ddc121eb5b 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -85,7 +87,7 @@ namespace osu.Game.Rulesets.Objects } public SliderPath(PathType type, Vector2[] controlPoints, double? expectedDistance = null) - : this(controlPoints.Select((c, i) => new PathControlPoint(c, i == 0 ? (PathType?)type : null)).ToArray(), expectedDistance) + : this(controlPoints.Select((c, i) => new PathControlPoint(c, i == 0 ? type : null)).ToArray(), expectedDistance) { } diff --git a/osu.Game/Rulesets/Objects/SliderPathExtensions.cs b/osu.Game/Rulesets/Objects/SliderPathExtensions.cs index dd418a1b7b..92a3b570fb 100644 --- a/osu.Game/Rulesets/Objects/SliderPathExtensions.cs +++ b/osu.Game/Rulesets/Objects/SliderPathExtensions.cs @@ -6,8 +6,6 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Types; using osuTK; -#nullable enable - namespace osu.Game.Rulesets.Objects { public static class SliderPathExtensions diff --git a/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs b/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs index 76f9eaf25a..ee860e82e2 100644 --- a/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs +++ b/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Objects diff --git a/osu.Game/Rulesets/Objects/Types/IHasColumn.cs b/osu.Game/Rulesets/Objects/Types/IHasColumn.cs index dc07cfbb6a..3978a7e765 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasColumn.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasColumn.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs index d1a4683a1d..d02b97a3e4 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 29a56fc625..b45ea989f3 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Skinning; using osuTK.Graphics; diff --git a/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs b/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs index 8807b802d8..89ee5022bf 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osuTK.Graphics; diff --git a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs index b497ca5da3..549abc046a 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasDuration.cs b/osu.Game/Rulesets/Objects/Types/IHasDuration.cs index ca734da5ad..06ed8eba76 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDuration.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDuration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 469b8b7892..91b05dc3fd 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasHold.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasHold.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 caf22c3023..dfc526383a 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasPath.cs b/osu.Game/Rulesets/Objects/Types/IHasPath.cs index 567c24a4a2..46834a55dd 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPath.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPath.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects.Types { public interface IHasPath : IHasDistance diff --git a/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs index 279946b44e..536707e95f 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; 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 8948fe59a9..281f619ba5 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 2a4215b960..821a6de520 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 7e55b21050..f688c783e1 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 d2561b10a7..3c0cc595fb 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 923ce9eba4..266a3de6ec 100644 --- a/osu.Game/Rulesets/Objects/Types/PathType.cs +++ b/osu.Game/Rulesets/Objects/Types/PathType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Objects.Types { public enum PathType diff --git a/osu.Game/Rulesets/RealmRulesetStore.cs b/osu.Game/Rulesets/RealmRulesetStore.cs index f42bf06da4..62a7a13c07 100644 --- a/osu.Game/Rulesets/RealmRulesetStore.cs +++ b/osu.Game/Rulesets/RealmRulesetStore.cs @@ -9,8 +9,6 @@ using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Database; -#nullable enable - namespace osu.Game.Rulesets { public class RealmRulesetStore : RulesetStore diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 83e85146d4..f4b96b3884 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Replays; using osu.Game.Rulesets.Objects; @@ -32,7 +31,7 @@ namespace osu.Game.Rulesets.Replays /// public abstract Replay Generate(); - protected virtual HitObject GetNextObject(int currentIndex) + protected virtual HitObject? GetNextObject(int currentIndex) { if (currentIndex >= Beatmap.HitObjects.Count - 1) return null; @@ -49,8 +48,7 @@ namespace osu.Game.Rulesets.Replays /// protected readonly List Frames = new List(); - [CanBeNull] - protected TFrame LastFrame => Frames.Count == 0 ? null : Frames[^1]; + protected TFrame? LastFrame => Frames.Count == 0 ? null : Frames[^1]; protected AutoGenerator(IBeatmap beatmap) : base(beatmap) diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index f889d15485..020bae1c42 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; @@ -163,7 +161,7 @@ namespace osu.Game.Rulesets.Replays CurrentTime = Math.Clamp(time, frameStart, frameEnd); // In an important section, a mid-frame time cannot be used and a null is returned instead. - return inImportantSection && frameStart < time && time < frameEnd ? null : (double?)CurrentTime; + return inImportantSection && frameStart < time && time < frameEnd ? null : CurrentTime; } private double getFrameTime(int index) diff --git a/osu.Game/Rulesets/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs index 2b67b60d8f..433be6e4b7 100644 --- a/osu.Game/Rulesets/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using MessagePack; using osu.Game.Online.Spectator; diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index d9aa615c6e..9a4af9e4ee 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Replays.Types /// The to extract values from. /// The beatmap. /// The last post-conversion , used to fill in missing delta information. May be null. - void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null); + void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame? lastFrame = null); /// /// Populates this using values from a . diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index b7c6132bdb..c1ec6c30ef 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -93,6 +95,15 @@ namespace osu.Game.Rulesets return AllMods.FirstOrDefault(m => m is T)?.CreateInstance() as T; } + /// + /// Creates an enumerable with mods that are supported by the ruleset for the supplied . + /// + /// + /// If there are no applicable mods from the given in this ruleset, + /// then the proper behaviour is to return an empty enumerable. + /// mods should not be present in the returned enumerable. + /// + [ItemNotNull] public abstract IEnumerable GetModsFor(ModType type); /// @@ -115,55 +126,55 @@ namespace osu.Game.Rulesets { switch (mod) { - case ModNoFail _: + case ModNoFail: value |= LegacyMods.NoFail; break; - case ModEasy _: + case ModEasy: value |= LegacyMods.Easy; break; - case ModHidden _: + case ModHidden: value |= LegacyMods.Hidden; break; - case ModHardRock _: + case ModHardRock: value |= LegacyMods.HardRock; break; - case ModPerfect _: - value |= LegacyMods.Perfect; + case ModPerfect: + value |= LegacyMods.Perfect | LegacyMods.SuddenDeath; break; - case ModSuddenDeath _: + case ModSuddenDeath: value |= LegacyMods.SuddenDeath; break; - case ModNightcore _: - value |= LegacyMods.Nightcore; + case ModNightcore: + value |= LegacyMods.Nightcore | LegacyMods.DoubleTime; break; - case ModDoubleTime _: + case ModDoubleTime: value |= LegacyMods.DoubleTime; break; - case ModRelax _: + case ModRelax: value |= LegacyMods.Relax; break; - case ModHalfTime _: + case ModHalfTime: value |= LegacyMods.HalfTime; break; - case ModFlashlight _: + case ModFlashlight: value |= LegacyMods.Flashlight; break; - case ModCinema _: - value |= LegacyMods.Cinema; + case ModCinema: + value |= LegacyMods.Cinema | LegacyMods.Autoplay; break; - case ModAutoplay _: + case ModAutoplay: value |= LegacyMods.Autoplay; break; } diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index c4f1933cd8..017214df61 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 88e3988431..b5e5fa1561 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -6,8 +6,6 @@ using JetBrains.Annotations; using osu.Framework.Testing; using Realms; -#nullable enable - namespace osu.Game.Rulesets { [ExcludeFromDynamicCompile] diff --git a/osu.Game/Rulesets/RulesetLoadException.cs b/osu.Game/Rulesets/RulesetLoadException.cs index 7c3a4bb75d..6fee8f446b 100644 --- a/osu.Game/Rulesets/RulesetLoadException.cs +++ b/osu.Game/Rulesets/RulesetLoadException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Rulesets diff --git a/osu.Game/Rulesets/RulesetSelector.cs b/osu.Game/Rulesets/RulesetSelector.cs index 8e6ec556d2..701e60eec9 100644 --- a/osu.Game/Rulesets/RulesetSelector.cs +++ b/osu.Game/Rulesets/RulesetSelector.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.UserInterface; using osu.Framework.Allocation; +using osu.Framework.Logging; namespace osu.Game.Rulesets { @@ -16,8 +19,17 @@ namespace osu.Game.Rulesets [BackgroundDependencyLoader] private void load() { - foreach (var r in Rulesets.AvailableRulesets) - AddItem(r); + foreach (var ruleset in Rulesets.AvailableRulesets) + { + try + { + AddItem(ruleset); + } + catch + { + Logger.Log($"Could not create ruleset icon for {ruleset.Name}. Please check for an update from the developer.", level: LogLevel.Error); + } + } } } } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 6f88d97a58..6b3e43cc1c 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -10,8 +10,6 @@ using osu.Framework; using osu.Framework.Logging; using osu.Framework.Platform; -#nullable enable - namespace osu.Game.Rulesets { public abstract class RulesetStore : IDisposable, IRulesetStore diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs index 5dfb5167f4..c6b9d227af 100644 --- a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.Scoring { /// diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index e7bb6d79f8..65af161393 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 0f51560476..0a1e6b729f 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Bindables; using osu.Framework.Utils; diff --git a/osu.Game/Rulesets/Scoring/HitEvent.cs b/osu.Game/Rulesets/Scoring/HitEvent.cs index 0ebbec62ba..cabbf40a7d 100644 --- a/osu.Game/Rulesets/Scoring/HitEvent.cs +++ b/osu.Game/Rulesets/Scoring/HitEvent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osuTK; diff --git a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs index fea13cf4b6..2fde73d5a2 100644 --- a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs +++ b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 9f03c381ee..bfa256fc20 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.ComponentModel; using System.Diagnostics; diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 2d008b58ba..99129fcf96 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index bfa67b8c45..12fe0056bb 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index df094ddb7c..56bbe031e6 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index 23325bcd13..1e80bd165b 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index be1105e7ff..95cb02c477 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index 53996b6b84..6a7369a150 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs index f2dbb1a23f..dcd7141419 100644 --- a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs index ae5f9c6111..3149b7f890 100644 --- a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index c18698f77e..fd8fcfddab 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Audio; @@ -56,12 +58,12 @@ namespace osu.Game.Rulesets.UI PlaySamples(samples); } - protected void PlaySamples(ISampleInfo[] samples) + protected void PlaySamples(ISampleInfo[] samples) => Schedule(() => { var hitSound = getNextSample(); hitSound.Samples = samples; hitSound.Play(); - } + }); protected HitObject GetMostValidObject() { diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index fee77af0ba..589b585643 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/IFrameStableClock.cs b/osu.Game/Rulesets/UI/IFrameStableClock.cs index 569ef5e06c..132605adaf 100644 --- a/osu.Game/Rulesets/UI/IFrameStableClock.cs +++ b/osu.Game/Rulesets/UI/IFrameStableClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Timing; diff --git a/osu.Game/Rulesets/UI/IHitObjectContainer.cs b/osu.Game/Rulesets/UI/IHitObjectContainer.cs index 4c784132e8..74fd7dee81 100644 --- a/osu.Game/Rulesets/UI/IHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/IHitObjectContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs index 2d700076d6..b842e708b0 100644 --- a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs +++ b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/UI/JudgementContainer.cs b/osu.Game/Rulesets/UI/JudgementContainer.cs index f1a68a0323..4336977aa8 100644 --- a/osu.Game/Rulesets/UI/JudgementContainer.cs +++ b/osu.Game/Rulesets/UI/JudgementContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 79bada0490..b1f355a789 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK.Graphics; using osu.Framework.Allocation; @@ -13,6 +15,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osuTK; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Localisation; namespace osu.Game.Rulesets.UI @@ -51,7 +54,6 @@ namespace osu.Game.Rulesets.UI private OsuColour colours { get; set; } private Color4 backgroundColour; - private Color4 highlightedColour; /// /// Construct a new instance. @@ -121,47 +123,13 @@ namespace osu.Game.Rulesets.UI modAcronym.FadeOut(); } - switch (value.Type) - { - default: - case ModType.DifficultyIncrease: - backgroundColour = colours.Yellow; - highlightedColour = colours.YellowLight; - break; - - case ModType.DifficultyReduction: - backgroundColour = colours.Green; - highlightedColour = colours.GreenLight; - break; - - case ModType.Automation: - backgroundColour = colours.Blue; - highlightedColour = colours.BlueLight; - break; - - case ModType.Conversion: - backgroundColour = colours.Purple; - highlightedColour = colours.PurpleLight; - break; - - case ModType.Fun: - backgroundColour = colours.Pink; - highlightedColour = colours.PinkLight; - break; - - case ModType.System: - backgroundColour = colours.Gray6; - highlightedColour = colours.Gray7; - modIcon.Colour = colours.Yellow; - break; - } - + backgroundColour = colours.ForModType(value.Type); updateColour(); } private void updateColour() { - background.Colour = Selected.Value ? highlightedColour : backgroundColour; + background.Colour = Selected.Value ? backgroundColour.Lighten(0.2f) : backgroundColour; } } } diff --git a/osu.Game/Rulesets/UI/ModSwitchSmall.cs b/osu.Game/Rulesets/UI/ModSwitchSmall.cs index 676bbac95c..1b777f3e88 100644 --- a/osu.Game/Rulesets/UI/ModSwitchSmall.cs +++ b/osu.Game/Rulesets/UI/ModSwitchSmall.cs @@ -13,8 +13,6 @@ using osu.Game.Rulesets.Mods; using osuTK; using osuTK.Graphics; -#nullable enable - namespace osu.Game.Rulesets.UI { public class ModSwitchSmall : CompositeDrawable diff --git a/osu.Game/Rulesets/UI/ModSwitchTiny.cs b/osu.Game/Rulesets/UI/ModSwitchTiny.cs index b1d453f588..1bb0fe535f 100644 --- a/osu.Game/Rulesets/UI/ModSwitchTiny.cs +++ b/osu.Game/Rulesets/UI/ModSwitchTiny.cs @@ -14,8 +14,6 @@ using osu.Game.Rulesets.Mods; using osuTK; using osuTK.Graphics; -#nullable enable - namespace osu.Game.Rulesets.UI { public class ModSwitchTiny : CompositeDrawable diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index ea5ffb10c6..60d1555052 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs index fff4a450e5..d0e79281a7 100644 --- a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Rulesets/UI/PlayfieldBorder.cs b/osu.Game/Rulesets/UI/PlayfieldBorder.cs index 458b88c6db..a129760ef3 100644 --- a/osu.Game/Rulesets/UI/PlayfieldBorder.cs +++ b/osu.Game/Rulesets/UI/PlayfieldBorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs b/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs index 0a0aad884e..a4a483e930 100644 --- a/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs +++ b/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.UI { public enum PlayfieldBorderStyle diff --git a/osu.Game/Rulesets/UI/ReplayRecorder.cs b/osu.Game/Rulesets/UI/ReplayRecorder.cs index dcd8f12028..b04807e475 100644 --- a/osu.Game/Rulesets/UI/ReplayRecorder.cs +++ b/osu.Game/Rulesets/UI/ReplayRecorder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index b5390eb6e2..7c37913576 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -121,7 +123,7 @@ namespace osu.Game.Rulesets.UI { switch (e) { - case MouseDownEvent _: + case MouseDownEvent: if (mouseDisabled.Value) return true; // importantly, block upwards propagation so global bindings also don't fire. diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs index ab6e07f424..0bd8aa64c9 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public class ConstantScrollAlgorithm : IScrollAlgorithm diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs index c394a05bcc..d2fb9e3531 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public interface IScrollAlgorithm diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 7b827e0c63..d41117bce8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; 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 45d3b3bcd4..bfddc22573 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 926f2fd539..d8a8a6ccd8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs index cd85932599..e00f0ffe5d 100644 --- a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs +++ b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 81e1a6c916..58bb80accd 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Rulesets.UI.Scrolling { public enum ScrollingDirection diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 3b15bc2cdf..0ed3ca1e63 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Allocation; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 782255733f..078f06b745 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Scoring/EFScoreInfo.cs b/osu.Game/Scoring/EFScoreInfo.cs index 4161336cfc..8a5bbbf0da 100644 --- a/osu.Game/Scoring/EFScoreInfo.cs +++ b/osu.Game/Scoring/EFScoreInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; diff --git a/osu.Game/Scoring/HitResultDisplayStatistic.cs b/osu.Game/Scoring/HitResultDisplayStatistic.cs index d43d8bf0ba..4603ff053e 100644 --- a/osu.Game/Scoring/HitResultDisplayStatistic.cs +++ b/osu.Game/Scoring/HitResultDisplayStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring diff --git a/osu.Game/Scoring/IScoreInfo.cs b/osu.Game/Scoring/IScoreInfo.cs index b4ad183cd3..289679a724 100644 --- a/osu.Game/Scoring/IScoreInfo.cs +++ b/osu.Game/Scoring/IScoreInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Beatmaps; using osu.Game.Database; diff --git a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs index 03e13455f0..8908163646 100644 --- a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 754ace82c5..f64e730c06 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index ae9afbf32e..750bb50be3 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -145,6 +144,7 @@ namespace osu.Game.Scoring.Legacy return legacyFrame; case IConvertibleReplayFrame convertibleFrame: + Debug.Assert(beatmap != null); return convertibleFrame.ToLegacy(beatmap); default: diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index a11cd5fcbd..0219111e5c 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring.Legacy diff --git a/osu.Game/Scoring/LegacyDatabasedScore.cs b/osu.Game/Scoring/LegacyDatabasedScore.cs index ac444c1bf3..de35cb5faf 100644 --- a/osu.Game/Scoring/LegacyDatabasedScore.cs +++ b/osu.Game/Scoring/LegacyDatabasedScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.IO.Stores; diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index 83e4389dc8..06bc3edd37 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Replays; using osu.Game.Utils; diff --git a/osu.Game/Scoring/ScoreFileInfo.cs b/osu.Game/Scoring/ScoreFileInfo.cs index 8acc98eff6..6c3509bccd 100644 --- a/osu.Game/Scoring/ScoreFileInfo.cs +++ b/osu.Game/Scoring/ScoreFileInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel.DataAnnotations; using osu.Game.Database; using osu.Game.IO; diff --git a/osu.Game/Scoring/ScoreModelManager.cs b/osu.Game/Scoring/ScoreImporter.cs similarity index 79% rename from osu.Game/Scoring/ScoreModelManager.cs rename to osu.Game/Scoring/ScoreImporter.cs index 59102360f9..4107c66dfe 100644 --- a/osu.Game/Scoring/ScoreModelManager.cs +++ b/osu.Game/Scoring/ScoreImporter.cs @@ -13,14 +13,14 @@ using osu.Game.Database; using osu.Game.IO.Archives; using osu.Game.Rulesets; using osu.Game.Scoring.Legacy; -using osu.Game.Stores; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using Realms; -#nullable enable - namespace osu.Game.Scoring { - public class ScoreModelManager : RealmArchiveModelManager + public class ScoreImporter : RealmArchiveModelImporter { public override IEnumerable HandledExtensions => new[] { ".osr" }; @@ -29,11 +29,14 @@ namespace osu.Game.Scoring private readonly RulesetStore rulesets; private readonly Func beatmaps; - public ScoreModelManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm) + private readonly IAPIProvider api; + + public ScoreImporter(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm, IAPIProvider api) : base(storage, realm) { this.rulesets = rulesets; this.beatmaps = beatmaps; + this.api = api; } protected override ScoreInfo? CreateModel(ArchiveReader archive) @@ -72,9 +75,16 @@ namespace osu.Game.Scoring model.StatisticsJson = JsonConvert.SerializeObject(model.Statistics); } - public override bool IsAvailableLocally(ScoreInfo model) + protected override void PostImport(ScoreInfo model, Realm realm) { - return Realm.Run(realm => realm.All().Any(s => s.OnlineID == model.OnlineID)); + base.PostImport(model, realm); + + var userRequest = new GetUserRequest(model.RealmUser.Username); + + api.Perform(userRequest); + + if (userRequest.Response is APIUser user) + model.User = user; } } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d7185a1677..d32d611a27 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -20,8 +20,6 @@ using osu.Game.Users; using osu.Game.Utils; using Realms; -#nullable enable - namespace osu.Game.Scoring { [ExcludeFromDynamicCompile] @@ -47,7 +45,7 @@ namespace osu.Game.Scoring public double Accuracy { get; set; } - public bool HasReplay { get; set; } + public bool HasReplay => !string.IsNullOrEmpty(Hash); public DateTimeOffset Date { get; set; } @@ -87,8 +85,9 @@ namespace osu.Game.Scoring { get => user ??= new APIUser { - Username = RealmUser.Username, Id = RealmUser.OnlineID, + Username = RealmUser.Username, + CountryCode = RealmUser.CountryCode, }; set { @@ -97,7 +96,8 @@ namespace osu.Game.Scoring RealmUser = new RealmUser { OnlineID = user.OnlineID, - Username = user.Username + Username = user.Username, + CountryCode = user.CountryCode, }; } } @@ -137,6 +137,7 @@ namespace osu.Game.Scoring { OnlineID = RealmUser.OnlineID, Username = RealmUser.Username, + CountryCode = RealmUser.CountryCode, }; return clone; diff --git a/osu.Game/Scoring/ScoreInfoExtensions.cs b/osu.Game/Scoring/ScoreInfoExtensions.cs index 2279337fef..7979ca8aaa 100644 --- a/osu.Game/Scoring/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/ScoreInfoExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; namespace osu.Game.Scoring diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index fbec6ea1fb..9aed8904e6 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -19,29 +21,32 @@ using osu.Game.IO.Archives; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; +using osu.Game.Online.API; namespace osu.Game.Scoring { - public class ScoreManager : IModelManager, IModelImporter + public class ScoreManager : ModelManager, IModelImporter { - private readonly RealmAccess realm; private readonly Scheduler scheduler; - private readonly Func difficulties; + private readonly BeatmapDifficultyCache difficultyCache; private readonly OsuConfigManager configManager; - private readonly ScoreModelManager scoreModelManager; + private readonly ScoreImporter scoreImporter; - public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm, Scheduler scheduler, - Func difficulties = null, OsuConfigManager configManager = null) + public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm, Scheduler scheduler, IAPIProvider api, + BeatmapDifficultyCache difficultyCache = null, OsuConfigManager configManager = null) + : base(storage, realm) { - this.realm = realm; this.scheduler = scheduler; - this.difficulties = difficulties; + this.difficultyCache = difficultyCache; this.configManager = configManager; - scoreModelManager = new ScoreModelManager(rulesets, beatmaps, storage, realm); + scoreImporter = new ScoreImporter(rulesets, beatmaps, storage, realm, api) + { + PostNotification = obj => PostNotification?.Invoke(obj) + }; } - public Score GetScore(ScoreInfo score) => scoreModelManager.GetScore(score); + public Score GetScore(ScoreInfo score) => scoreImporter.GetScore(score); /// /// Perform a lookup query on available s. @@ -50,7 +55,7 @@ namespace osu.Game.Scoring /// The first result for the provided query, or null if no results were found. public ScoreInfo Query(Expression> query) { - return realm.Run(r => r.All().FirstOrDefault(query)?.Detach()); + return Realm.Run(r => r.All().FirstOrDefault(query)?.Detach()); } /// @@ -61,8 +66,6 @@ namespace osu.Game.Scoring /// The given ordered by decreasing total score. public async Task OrderByTotalScoreAsync(ScoreInfo[] scores, CancellationToken cancellationToken = default) { - var difficultyCache = difficulties?.Invoke(); - if (difficultyCache != null) { // Compute difficulties asynchronously first to prevent blocking via the GetTotalScore() call below. @@ -164,11 +167,11 @@ namespace osu.Game.Scoring return score.BeatmapInfo.MaxCombo.Value; #pragma warning restore CS0618 - if (difficulties == null) + if (difficultyCache == null) return null; // We can compute the max combo locally after the async beatmap difficulty computation. - var difficulty = await difficulties().GetDifficultyAsync(score.BeatmapInfo, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false); + var difficulty = await difficultyCache.GetDifficultyAsync(score.BeatmapInfo, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false); return difficulty?.MaxCombo; } @@ -227,25 +230,9 @@ namespace osu.Game.Scoring } } - #region Implementation of IPostNotifications - - public Action PostNotification - { - set => scoreModelManager.PostNotification = value; - } - - #endregion - - #region Implementation of IModelManager - - public bool Delete(ScoreInfo item) - { - return scoreModelManager.Delete(item); - } - public void Delete([CanBeNull] Expression> filter = null, bool silent = false) { - realm.Run(r => + Realm.Run(r => { var items = r.All() .Where(s => !s.DeletePending); @@ -253,78 +240,37 @@ namespace osu.Game.Scoring if (filter != null) items = items.Where(filter); - scoreModelManager.Delete(items.ToList(), silent); + Delete(items.ToList(), silent); }); } public void Delete(BeatmapInfo beatmap, bool silent = false) { - realm.Run(r => + Realm.Run(r => { var beatmapScores = r.Find(beatmap.ID).Scores.ToList(); - scoreModelManager.Delete(beatmapScores, silent); + Delete(beatmapScores, silent); }); } - public void Delete(List items, bool silent = false) - { - scoreModelManager.Delete(items, silent); - } + public Task Import(params string[] paths) => scoreImporter.Import(paths); - public void Undelete(List items, bool silent = false) - { - scoreModelManager.Undelete(items, silent); - } + public Task Import(params ImportTask[] tasks) => scoreImporter.Import(tasks); - public void Undelete(ScoreInfo item) - { - scoreModelManager.Undelete(item); - } + public override bool IsAvailableLocally(ScoreInfo model) => Realm.Run(realm => realm.All().Any(s => s.OnlineID == model.OnlineID)); - public Task Import(params string[] paths) - { - return scoreModelManager.Import(paths); - } + public IEnumerable HandledExtensions => scoreImporter.HandledExtensions; - public Task Import(params ImportTask[] tasks) - { - return scoreModelManager.Import(tasks); - } + public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreImporter.Import(notification, tasks); - public IEnumerable HandledExtensions => scoreModelManager.HandledExtensions; - - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) - { - return scoreModelManager.Import(notification, tasks); - } - - public Task> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return scoreModelManager.Import(task, lowPriority, cancellationToken); - } - - public Task> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return scoreModelManager.Import(archive, lowPriority, cancellationToken); - } - - public Live Import(ScoreInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return scoreModelManager.Import(item, archive, lowPriority, cancellationToken); - } - - public bool IsAvailableLocally(ScoreInfo model) - { - return scoreModelManager.IsAvailableLocally(model); - } - - #endregion + public Live Import(ScoreInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => + scoreImporter.ImportModel(item, archive, batchImport, cancellationToken); #region Implementation of IPresentImports - public Action>> PostImport + public Action>> PresentImport { - set => scoreModelManager.PostImport = value; + set => scoreImporter.PresentImport = value; } #endregion diff --git a/osu.Game/Scoring/ScorePerformanceCache.cs b/osu.Game/Scoring/ScorePerformanceCache.cs index e15d59e648..f51fb41497 100644 --- a/osu.Game/Scoring/ScorePerformanceCache.cs +++ b/osu.Game/Scoring/ScorePerformanceCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using System.Threading.Tasks; diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index 64f7da9ba3..a1916953c4 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -9,6 +11,10 @@ namespace osu.Game.Scoring { public enum ScoreRank { + // TODO: Localisable? + [Description(@"F")] + F = -1, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankD))] [Description(@"D")] D, diff --git a/osu.Game/Scoring/ScoringValues.cs b/osu.Game/Scoring/ScoringValues.cs index d31cd7c68b..9bc4e6e12a 100644 --- a/osu.Game/Scoring/ScoringValues.cs +++ b/osu.Game/Scoring/ScoringValues.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using MessagePack; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index 6084ec4b01..8e1fd63040 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Screens; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index 9f562a618e..bafd1ff348 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 65bc9cfaea..ca05c8af46 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs index d946fd41d9..4b0f262ab1 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index 49c7934ed9..3dd72685e9 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics.Backgrounds; namespace osu.Game.Screens.Backgrounds diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 452f033dcc..c794c768c6 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -1,10 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Logging; using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Beatmaps; @@ -24,7 +27,7 @@ namespace osu.Game.Screens.Backgrounds private const int background_count = 7; private IBindable user; private Bindable skin; - private Bindable mode; + private Bindable source; private Bindable introSequence; private readonly SeasonalBackgroundLoader seasonalBackgroundLoader = new SeasonalBackgroundLoader(); @@ -43,24 +46,29 @@ namespace osu.Game.Screens.Backgrounds { user = api.LocalUser.GetBoundCopy(); skin = skinManager.CurrentSkin.GetBoundCopy(); - mode = config.GetBindable(OsuSetting.MenuBackgroundSource); + source = config.GetBindable(OsuSetting.MenuBackgroundSource); introSequence = config.GetBindable(OsuSetting.IntroSequence); AddInternal(seasonalBackgroundLoader); - user.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired); - skin.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired); - mode.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired); - beatmap.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired); - introSequence.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired); - seasonalBackgroundLoader.SeasonalBackgroundChanged += () => Scheduler.AddOnce(loadNextIfRequired); - + // Load first background asynchronously as part of BDL load. currentDisplay = RNG.Next(0, background_count); - Next(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + user.ValueChanged += _ => Scheduler.AddOnce(next); + skin.ValueChanged += _ => Scheduler.AddOnce(next); + source.ValueChanged += _ => Scheduler.AddOnce(next); + beatmap.ValueChanged += _ => Scheduler.AddOnce(next); + introSequence.ValueChanged += _ => Scheduler.AddOnce(next); + seasonalBackgroundLoader.SeasonalBackgroundChanged += () => Scheduler.AddOnce(next); // helper function required for AddOnce usage. - void loadNextIfRequired() => Next(); + void next() => Next(); } private ScheduledDelegate nextTask; @@ -78,6 +86,8 @@ namespace osu.Game.Screens.Backgrounds if (nextBackground == background) return false; + Logger.Log("🌅 Background change queued"); + cancellationTokenSource?.Cancel(); cancellationTokenSource = new CancellationTokenSource(); @@ -106,12 +116,12 @@ namespace osu.Game.Screens.Backgrounds if (newBackground == null && user.Value?.IsSupporter == true) { - switch (mode.Value) + switch (source.Value) { case BackgroundSource.Beatmap: case BackgroundSource.BeatmapWithStoryboard: { - if (mode.Value == BackgroundSource.BeatmapWithStoryboard && AllowStoryboardBackground) + if (source.Value == BackgroundSource.BeatmapWithStoryboard && AllowStoryboardBackground) newBackground = new BeatmapBackgroundWithStoryboard(beatmap.Value, getBackgroundTextureName()); newBackground ??= new BeatmapBackground(beatmap.Value, getBackgroundTextureName()); diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 8f430dce77..a7faf961cf 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Edit/BottomBar.cs b/osu.Game/Screens/Edit/BottomBar.cs index 62caaced89..444911cf2d 100644 --- a/osu.Game/Screens/Edit/BottomBar.cs +++ b/osu.Game/Screens/Edit/BottomBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/ClipboardContent.cs b/osu.Game/Screens/Edit/ClipboardContent.cs index 0348a7c15d..a39b24e7bb 100644 --- a/osu.Game/Screens/Edit/ClipboardContent.cs +++ b/osu.Game/Screens/Edit/ClipboardContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index 3c63da3a4a..482a0bbe5f 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio.Track; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Components/CircularButton.cs b/osu.Game/Screens/Edit/Components/CircularButton.cs index 40b5ac663a..74e4162102 100644 --- a/osu.Game/Screens/Edit/Components/CircularButton.cs +++ b/osu.Game/Screens/Edit/Components/CircularButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Graphics.UserInterface; using osuTK; diff --git a/osu.Game/Screens/Edit/Components/EditorSidebar.cs b/osu.Game/Screens/Edit/Components/EditorSidebar.cs index 4e9b1d5222..da15512cdc 100644 --- a/osu.Game/Screens/Edit/Components/EditorSidebar.cs +++ b/osu.Game/Screens/Edit/Components/EditorSidebar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs b/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs index 3871720562..6782b2f357 100644 --- a/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs +++ b/osu.Game/Screens/Edit/Components/EditorSidebarSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Components/Menus/DifficultyMenuItem.cs b/osu.Game/Screens/Edit/Components/Menus/DifficultyMenuItem.cs index f17fe4c3ce..e14354222b 100644 --- a/osu.Game/Screens/Edit/Components/Menus/DifficultyMenuItem.cs +++ b/osu.Game/Screens/Edit/Components/Menus/DifficultyMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; @@ -22,6 +24,6 @@ namespace osu.Game.Screens.Edit.Components.Menus Action.Value = () => difficultyChangeFunc.Invoke(beatmapInfo); } - public override IconUsage? GetIconForState(bool state) => state ? (IconUsage?)FontAwesome.Solid.Check : null; + public override IconUsage? GetIconForState(bool state) => state ? FontAwesome.Solid.Check : null; } } diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index 20b8bba6da..8321fde171 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs index 0a2c073dcd..1085f2c277 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 4e75a92e19..6af3b99017 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Edit.Components.Menus { public class EditorMenuItemSpacer : EditorMenuItem diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs b/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs index 8b868a4649..0bba5a79ab 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorScreenSwitcherControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index d1a999c2d1..30316cb12c 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs index d66856ebd8..82e94dc862 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs index 6a7b0c9ef7..b8d1cca061 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/EditorRadioButtonCollection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs index ca79dd15d7..03745ce19d 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs index c43561eaa7..55302833c1 100644 --- a/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs +++ b/osu.Game/Screens/Edit/Components/TernaryButtons/DrawableTernaryButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -65,7 +67,7 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons { base.LoadComplete(); - Button.Bindable.BindValueChanged(selected => updateSelectionState(), true); + Button.Bindable.BindValueChanged(_ => updateSelectionState(), true); Action = onAction; } diff --git a/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs b/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs index 7f64695bde..8eb781c947 100644 --- a/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs +++ b/osu.Game/Screens/Edit/Components/TernaryButtons/TernaryButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index bd5377e578..7051dd226c 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Allocation; 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 8298cf4773..058aa83b97 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; 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 3d535ec915..4dbec880dc 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; 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 f1edb7dc7e..54ef5a2bd7 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Specialized; using System.Linq; @@ -22,7 +24,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts controlPointGroups.UnbindAll(); controlPointGroups.BindTo(beatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((sender, args) => + controlPointGroups.BindCollectionChanged((_, args) => { switch (args.Action) { @@ -47,7 +49,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts case NotifyCollectionChangedAction.Remove: foreach (var group in args.OldItems.OfType()) { - var matching = Children.SingleOrDefault(gv => gv.Group == group); + var matching = Children.SingleOrDefault(gv => ReferenceEquals(gv.Group, group)); if (matching != null) matching.Expire(); diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs index 41716f9c23..89c0309222 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs index 7c14152b3d..b2007273e8 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/EffectPointVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs index 88587399f2..e058cae191 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -27,7 +29,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts // Run in constructor so IsRedundant calls can work correctly. controlPoints.BindTo(Group.ControlPoints); - controlPoints.BindCollectionChanged((_, __) => + controlPoints.BindCollectionChanged((_, _) => { ClearInternal(); @@ -38,15 +40,15 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { switch (point) { - case TimingControlPoint _: + case TimingControlPoint: AddInternal(new ControlPointVisualisation(point) { Y = 0, }); break; - case DifficultyControlPoint _: + case DifficultyControlPoint: AddInternal(new ControlPointVisualisation(point) { Y = 0.25f, }); break; - case SampleControlPoint _: + case SampleControlPoint: AddInternal(new ControlPointVisualisation(point) { Y = 0.5f, }); break; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs index c81f1828f7..b9e2a969a5 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/IControlPointVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts 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 d551333616..c00ebb32bc 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; 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 5aba81aa7d..54914f4b23 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; @@ -36,7 +38,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { AddInternal(this.content = content ?? new Container { RelativeSizeAxes = Axes.Both }); - beatmap.ValueChanged += b => + beatmap.ValueChanged += _ => { updateRelativeChildSize(); }; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index 1706c47c96..afaedee0a9 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs index 99cdc014aa..d38596b9be 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/TestGameplayButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; 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 ec68bf9c00..88e40cb305 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; 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 a4b6b0c392..b8e55c8db8 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index bf4d70baa6..40403e08ad 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; @@ -291,7 +293,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.LoadComplete(); BeatDivisor.BindValueChanged(_ => updateState(), true); - divisorTextBox.OnCommit += (_, __) => setPresets(); + divisorTextBox.OnCommit += (_, _) => setPresets(); Schedule(() => GetContainingInputManager().ChangeFocus(divisorTextBox)); } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs index 4616669c6d..67b346fb64 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs index 4a25144881..ebdb030e76 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Edit.Compose.Components { public enum BeatDivisorType diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index d56dc176f6..540fbf9a72 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -53,7 +55,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - SelectedItems.CollectionChanged += (selectedObjects, args) => + SelectedItems.CollectionChanged += (_, args) => { switch (args.Action) { diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 771612fcf1..98079116cd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 68be20720d..4c37d200bc 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using Humanizer; @@ -30,8 +32,6 @@ namespace osu.Game.Screens.Edit.Compose.Components /// public class ComposeBlueprintContainer : EditorBlueprintContainer { - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - private readonly Container placementBlueprintContainer; protected new EditorSelectionHandler SelectionHandler => (EditorSelectionHandler)base.SelectionHandler; @@ -39,6 +39,12 @@ namespace osu.Game.Screens.Edit.Compose.Components private PlacementBlueprint currentPlacement; private InputManager inputManager; + /// + /// Positional input must be received outside the container's bounds, + /// in order to handle composer blueprints which are partially offscreen. + /// + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + public ComposeBlueprintContainer(HitObjectComposer composer) : base(composer) { diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 1f64a50c02..69c7fc2775 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index ecbac82db0..838562719d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs index 22b211f257..6a4fe27f04 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 7f693996a4..0bdfc5b0a0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -29,7 +31,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // bring in updates from selection changes EditorBeatmap.HitObjectUpdated += _ => Scheduler.AddOnce(UpdateTernaryStates); - SelectedItems.CollectionChanged += (sender, args) => Scheduler.AddOnce(UpdateTernaryStates); + SelectedItems.CollectionChanged += (_, _) => Scheduler.AddOnce(UpdateTernaryStates); } protected override void DeleteItems(IEnumerable items) => EditorBeatmap.RemoveRange(items); diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs index 3fc26fa974..06af232111 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs index 2b71bb2f16..46d948f8b6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs +++ b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Edit; using osuTK; diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs index f0d26c7b6a..64fb2ccaba 100644 --- a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index cda986c7cd..2c4c220ad0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs index 346bb2b508..3d6dacc95e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs index 8f22e67922..c4675685f6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index c37fefeed4..308d0cc893 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs index 397158b9f6..5c7debf57e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandleContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index f13ed0456a..761cd118bf 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs index 1f82f28380..bd1e2f4649 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 78b98a3649..8419d3b380 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -19,6 +21,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; using osuTK.Input; @@ -61,7 +64,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { InternalChild = SelectionBox = CreateSelectionBox(); - SelectedItems.CollectionChanged += (sender, args) => + SelectedItems.CollectionChanged += (_, _) => { Scheduler.AddOnce(updateVisibility); }; @@ -97,6 +100,14 @@ namespace osu.Game.Screens.Edit.Compose.Components #region User Input Handling + /// + /// Positional input must be received outside the container's bounds, + /// in order to handle blueprints which are partially offscreen. + /// + /// + /// + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + /// /// Handles the selected items being moved. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs index 8c8b38d9ea..6c545f8f78 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index eaaa663fe7..b028f67ba1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs index 6b62459c97..1091afe226 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs index 9abea73f6b..648ffd9609 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -40,8 +38,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [BackgroundDependencyLoader] private void load() { - volume.BindValueChanged(volume => updateText()); - bank.BindValueChanged(bank => updateText(), true); + volume.BindValueChanged(_ => updateText()); + bank.BindValueChanged(_ => updateText(), true); } protected override bool OnClick(ClickEvent e) @@ -121,7 +119,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline }); // on commit, ensure that the value is correct by sourcing it from the objects' control points again. // this ensures that committing empty text causes a revert to the previous value. - bank.OnCommit += (_, __) => bank.Current.Value = getCommonBank(relevantControlPoints); + bank.OnCommit += (_, _) => bank.Current.Value = getCommonBank(relevantControlPoints); volume.Current.BindValueChanged(val => updateVolumeFor(relevantObjects, val.NewValue)); } @@ -133,7 +131,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } private static string? getCommonBank(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleBank).Distinct().Count() == 1 ? relevantControlPoints.First().SampleBank : null; - private static int? getCommonVolume(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleVolume).Distinct().Count() == 1 ? (int?)relevantControlPoints.First().SampleVolume : null; + private static int? getCommonVolume(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleVolume).Distinct().Count() == 1 ? relevantControlPoints.First().SampleVolume : null; private void updateBankFor(IEnumerable objects, string? newBank) { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 89e9fb2404..37fc4b03b2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio.Track; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 4cffebc57c..c2415ce978 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -116,7 +118,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.Solid.SearchPlus, - Action = () => changeZoom(1) + Action = () => Timeline.AdjustZoomRelatively(1) }, new TimelineButton { @@ -125,7 +127,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.Solid.SearchMinus, - Action = () => changeZoom(-1) + Action = () => Timeline.AdjustZoomRelatively(-1) }, } } @@ -151,7 +153,5 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Timeline.ControlPointsVisible.BindTo(controlPointsCheckbox.Current); Timeline.TicksVisible.BindTo(ticksCheckbox.Current); } - - private void changeZoom(float change) => Timeline.Zoom += change; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index a9e9ef5001..742e16d5a9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -33,8 +35,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private Bindable placement; private SelectionBlueprint placementBlueprint; - // We want children within the timeline to be interactable - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => timeline.ScreenSpaceDrawQuad.Contains(screenSpacePos); + /// + /// Positional input must be received outside the container's bounds, + /// in order to handle timeline blueprints which are stacked offscreen. + /// + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => timeline.ReceivePositionalInputAt(screenSpacePos); public TimelineBlueprintContainer(HitObjectComposer composer) : base(composer) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs index e0b21b2e22..0832dc02a9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 8520567fa9..cfc71256e8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Specialized; using System.Linq; using osu.Framework.Bindables; @@ -22,7 +24,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline controlPointGroups.UnbindAll(); controlPointGroups.BindTo(beatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((sender, args) => + controlPointGroups.BindCollectionChanged((_, args) => { switch (args.Action) { @@ -38,7 +40,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline case NotifyCollectionChangedAction.Remove: foreach (var group in args.OldItems.OfType()) { - var matching = Children.SingleOrDefault(gv => gv.Group == group); + var matching = Children.SingleOrDefault(gv => ReferenceEquals(gv.Group, group)); matching?.Expire(); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs index 9610f6424c..10355045be 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -32,7 +34,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline base.LoadComplete(); controlPoints.BindTo(Group.ControlPoints); - controlPoints.BindCollectionChanged((_, __) => + controlPoints.BindCollectionChanged((_, _) => { ClearInternal(); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs index 8aad8aa6dc..c026c169d6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 33ea137d51..32ebc9c3c1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -203,7 +205,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline updateRepeats(repeats); } - if (difficultyControlPoint != Item.DifficultyControlPoint) + if (!ReferenceEquals(difficultyControlPoint, Item.DifficultyControlPoint)) { difficultyControlPoint = Item.DifficultyControlPoint; difficultyOverrideDisplay?.Expire(); @@ -218,7 +220,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - if (sampleControlPoint != Item.SampleControlPoint) + if (!ReferenceEquals(sampleControlPoint, Item.SampleControlPoint)) { sampleControlPoint = Item.SampleControlPoint; sampleOverrideDisplay?.Expire(); @@ -391,7 +393,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (e.CurrentState.Keyboard.ShiftPressed) { - if (hitObject.DifficultyControlPoint == DifficultyControlPoint.DEFAULT) + if (ReferenceEquals(hitObject.DifficultyControlPoint, DifficultyControlPoint.DEFAULT)) hitObject.DifficultyControlPoint = new DifficultyControlPoint(); double newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs index e98cf8332f..d91b95888b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineSelectionHandler.cs @@ -1,28 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using JetBrains.Annotations; -using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; -using osuTK; using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { internal class TimelineSelectionHandler : EditorSelectionHandler { - [Resolved] - private Timeline timeline { get; set; } - - public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => timeline.ScreenSpaceDrawQuad.Contains(screenSpacePos); - // for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation public override bool HandleMovement(MoveSelectionEvent moveEvent) => true; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 9904d91653..076ce224f0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs index 2df4ef001c..cf62707839 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs index 60a9e1ed66..28ae77c931 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TopPointPiece.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index d008368b69..96f6ef6d02 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -66,8 +68,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline minZoom = value; - if (Zoom < value) - Zoom = value; + // ensure zoom range is in valid state before updating zoom. + if (MinZoom < MaxZoom) + updateZoom(); } } @@ -86,8 +89,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline maxZoom = value; - if (Zoom > value) - Zoom = value; + // ensure zoom range is in valid state before updating zoom. + if (MaxZoom > MinZoom) + updateZoom(); } } @@ -97,15 +101,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public float Zoom { get => zoomTarget; - set - { - value = Math.Clamp(value, MinZoom, MaxZoom); + set => updateZoom(value); + } - if (IsLoaded) - setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); - else - currentZoom = zoomTarget = value; - } + private void updateZoom(float? value = null) + { + float newZoom = Math.Clamp(value ?? Zoom, MinZoom, MaxZoom); + + if (IsLoaded) + setZoomTarget(newZoom, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); + else + currentZoom = zoomTarget = newZoom; } protected override void Update() @@ -121,7 +127,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (e.AltPressed) { // zoom when holding alt. - setZoomTarget(zoomTarget + e.ScrollDelta.Y, zoomedContent.ToLocalSpace(e.ScreenSpaceMousePosition).X); + AdjustZoomRelatively(e.ScrollDelta.Y, zoomedContent.ToLocalSpace(e.ScreenSpaceMousePosition).X); return true; } @@ -139,12 +145,19 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline zoomedContentWidthCache.Validate(); } + public void AdjustZoomRelatively(float change, float? focusPoint = null) + { + const float zoom_change_sensitivity = 0.02f; + + setZoomTarget(zoomTarget + change * (MaxZoom - minZoom) * zoom_change_sensitivity, focusPoint); + } + private float zoomTarget = 1; - private void setZoomTarget(float newZoom, float focusPoint) + private void setZoomTarget(float newZoom, float? focusPoint = null) { zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom); - transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); + transformZoomTo(zoomTarget, focusPoint ?? DrawWidth / 2, ZoomDuration, ZoomEasing); OnZoomChanged(); } diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 2cde962b12..3d18b00e75 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; @@ -87,7 +89,7 @@ namespace osu.Game.Screens.Edit.Compose if (composer == null) return; - EditorBeatmap.SelectedHitObjects.BindCollectionChanged((_, __) => updateClipboardActionAvailability()); + EditorBeatmap.SelectedHitObjects.BindCollectionChanged((_, _) => updateClipboardActionAvailability()); clipboard.BindValueChanged(_ => updateClipboardActionAvailability()); composer.OnLoadComplete += _ => updateClipboardActionAvailability(); updateClipboardActionAvailability(); diff --git a/osu.Game/Screens/Edit/Compose/HitObjectUsageEventBuffer.cs b/osu.Game/Screens/Edit/Compose/HitObjectUsageEventBuffer.cs index 621c901fb9..3df5139924 100644 --- a/osu.Game/Screens/Edit/Compose/HitObjectUsageEventBuffer.cs +++ b/osu.Game/Screens/Edit/Compose/HitObjectUsageEventBuffer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs index 59eb13cae5..46d9555e0c 100644 --- a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs +++ b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs index aa6ca280ee..36c4e397a7 100644 --- a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs +++ b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Screens/Edit/Design/DesignScreen.cs b/osu.Game/Screens/Edit/Design/DesignScreen.cs index f15639733c..546a07f17d 100644 --- a/osu.Game/Screens/Edit/Design/DesignScreen.cs +++ b/osu.Game/Screens/Edit/Design/DesignScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Edit.Design { public class DesignScreen : EditorScreen diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 1414644a54..3e3940c5ba 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -16,9 +18,11 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -28,15 +32,17 @@ using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -using osu.Game.Resources.Localisation.Web; +using osu.Game.Overlays.OSD; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose; +using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Screens.Edit.Design; using osu.Game.Screens.Edit.GameplayTest; using osu.Game.Screens.Edit.Setup; @@ -46,6 +52,7 @@ using osu.Game.Screens.Play; using osu.Game.Users; using osuTK.Graphics; using osuTK.Input; +using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings; namespace osu.Game.Screens.Edit { @@ -63,6 +70,8 @@ namespace osu.Game.Screens.Edit public override bool? AllowTrackAdjustments => false; + protected override bool PlayExitSound => !ExitConfirmed && !switchingDifficulty; + protected bool HasUnsavedChanges { get @@ -93,12 +102,38 @@ namespace osu.Game.Screens.Edit public IBindable SamplePlaybackDisabled => samplePlaybackDisabled; + /// + /// Ensure all asynchronously loading pieces of the editor are in a good state. + /// This exists here for convenience for tests, not for actual use. + /// Eventually we'd probably want a better way to signal this. + /// + public bool ReadyForUse + { + get + { + if (!workingBeatmapUpdated) + return false; + + if (currentScreen?.IsLoaded != true) + return false; + + if (currentScreen is EditorScreenWithTimeline) + return currentScreen.ChildrenOfType().FirstOrDefault()?.IsLoaded == true; + + return true; + } + } + + private bool workingBeatmapUpdated; + private readonly Bindable samplePlaybackDisabled = new Bindable(); private bool canSave; protected bool ExitConfirmed { get; private set; } + private bool switchingDifficulty; + private string lastSavedHash; private Container screenContainer; @@ -137,6 +172,9 @@ namespace osu.Game.Screens.Edit [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine); + [Resolved(canBeNull: true)] + private OnScreenDisplay onScreenDisplay { get; set; } + public Editor(EditorLoader loader = null) { this.loader = loader; @@ -154,7 +192,7 @@ namespace osu.Game.Screens.Edit loadableBeatmap = beatmapManager.CreateNew(Ruleset.Value, api.LocalUser.Value); // required so we can get the track length in EditorClock. - // this is safe as nothing has yet got a reference to this new beatmap. + // this is ONLY safe because the track being provided is a `TrackVirtual` which we don't really care about disposing. loadableBeatmap.LoadTrack(); // this is a bit haphazard, but guards against setting the lease Beatmap bindable if @@ -213,6 +251,7 @@ namespace osu.Game.Screens.Edit // this assumes that nothing during the rest of this load() method is accessing Beatmap.Value (loadableBeatmap should be preferred). // generally this is quite safe, as the actual load of editor content comes after menuBar.Mode.ValueChanged is fired in its own LoadComplete. Beatmap.Value = loadableBeatmap; + workingBeatmapUpdated = true; }); OsuMenuItem undoMenuItem; @@ -372,6 +411,7 @@ namespace osu.Game.Screens.Edit // no longer new after first user-triggered save. isNewBeatmap = false; updateLastSavedHash(); + onScreenDisplay?.Display(new BeatmapEditorToast(ToastStrings.BeatmapSaved, editorBeatmap.BeatmapInfo.GetDisplayTitle())); return true; } @@ -422,6 +462,8 @@ namespace osu.Game.Screens.Edit protected override bool OnKeyDown(KeyDownEvent e) { + if (e.ControlPressed || e.AltPressed || e.SuperPressed) return false; + switch (e.Key) { case Key.Left: @@ -622,9 +664,7 @@ namespace osu.Game.Screens.Edit // To update the game-wide beatmap with any changes, perform a re-fetch on exit/suspend. // This is required as the editor makes its local changes via EditorBeatmap // (which are not propagated outwards to a potentially cached WorkingBeatmap). - ((IWorkingBeatmapCache)beatmapManager).Invalidate(Beatmap.Value.BeatmapInfo); - var refetchedBeatmapInfo = beatmapManager.QueryBeatmap(b => b.ID == Beatmap.Value.BeatmapInfo.ID); - var refetchedBeatmap = beatmapManager.GetWorkingBeatmap(refetchedBeatmapInfo); + var refetchedBeatmap = beatmapManager.GetWorkingBeatmap(Beatmap.Value.BeatmapInfo, true); if (!(refetchedBeatmap is DummyWorkingBeatmap)) { @@ -790,10 +830,11 @@ namespace osu.Game.Screens.Edit if (trackPlaying) { - // generally users are not looking to perform tiny seeks when the track is playing, - // so seeks should always be by one full beat, bypassing the beatDivisor. + // generally users are not looking to perform tiny seeks when the track is playing. // this multiplication undoes the division that will be applied in the underlying seek operation. - amount *= beatDivisor.Value; + // scale by BPM to keep the seek amount constant across all BPMs. + var timingPoint = editorBeatmap.ControlPointInfo.TimingPointAt(clock.CurrentTimeAccurate); + amount *= beatDivisor.Value * (timingPoint.BPM / 120); } if (direction < 1) @@ -855,7 +896,10 @@ namespace osu.Game.Screens.Edit } private void switchToNewDifficulty(RulesetInfo rulesetInfo, bool createCopy) - => loader?.ScheduleSwitchToNewDifficulty(editorBeatmap.BeatmapInfo, rulesetInfo, createCopy, GetState(rulesetInfo)); + { + switchingDifficulty = true; + loader?.ScheduleSwitchToNewDifficulty(editorBeatmap.BeatmapInfo, rulesetInfo, createCopy, GetState(rulesetInfo)); + } private EditorMenuItem createDifficultySwitchMenu() { @@ -884,7 +928,7 @@ namespace osu.Game.Screens.Edit private void cancelExit() { - samplePlaybackDisabled.Value = false; + updateSampleDisabledState(); loader?.CancelPendingDifficultySwitch(); } @@ -896,6 +940,14 @@ namespace osu.Game.Screens.Edit ControlPointInfo IBeatSyncProvider.ControlPoints => editorBeatmap.ControlPointInfo; IClock IBeatSyncProvider.Clock => clock; - ChannelAmplitudes? IBeatSyncProvider.Amplitudes => Beatmap.Value.TrackLoaded ? Beatmap.Value.Track.CurrentAmplitudes : (ChannelAmplitudes?)null; + ChannelAmplitudes? IBeatSyncProvider.Amplitudes => Beatmap.Value.TrackLoaded ? Beatmap.Value.Track.CurrentAmplitudes : null; + + private class BeatmapEditorToast : Toast + { + public BeatmapEditorToast(LocalisableString value, string beatmapDisplayName) + : base(InputSettingsStrings.EditorSection, value, beatmapDisplayName) + { + } + } } } diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index c9449f3259..96425e8bc8 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections; using System.Collections.Generic; @@ -71,31 +73,7 @@ namespace osu.Game.Screens.Edit public EditorBeatmap(IBeatmap playableBeatmap, ISkin beatmapSkin = null, BeatmapInfo beatmapInfo = null) { PlayableBeatmap = playableBeatmap; - - // ensure we are not working with legacy control points. - // if we leave the legacy points around they will be applied over any local changes on - // ApplyDefaults calls. this should eventually be removed once the default logic is moved to the decoder/converter. - if (PlayableBeatmap.ControlPointInfo is LegacyControlPointInfo) - { - var newControlPoints = new ControlPointInfo(); - - foreach (var controlPoint in PlayableBeatmap.ControlPointInfo.AllControlPoints) - { - switch (controlPoint) - { - case DifficultyControlPoint _: - case SampleControlPoint _: - // skip legacy types. - continue; - - default: - newControlPoints.Add(controlPoint.Time, controlPoint); - break; - } - } - - playableBeatmap.ControlPointInfo = newControlPoints; - } + PlayableBeatmap.ControlPointInfo = ConvertControlPoints(PlayableBeatmap.ControlPointInfo); this.beatmapInfo = beatmapInfo ?? playableBeatmap.BeatmapInfo; @@ -108,10 +86,43 @@ namespace osu.Game.Screens.Edit trackStartTime(obj); } + /// + /// Converts a such that the resultant is non-legacy. + /// + /// The to convert. + /// The non-legacy . is returned if already non-legacy. + public static ControlPointInfo ConvertControlPoints(ControlPointInfo incoming) + { + // ensure we are not working with legacy control points. + // if we leave the legacy points around they will be applied over any local changes on + // ApplyDefaults calls. this should eventually be removed once the default logic is moved to the decoder/converter. + if (!(incoming is LegacyControlPointInfo)) + return incoming; + + var newControlPoints = new ControlPointInfo(); + + foreach (var controlPoint in incoming.AllControlPoints) + { + switch (controlPoint) + { + case DifficultyControlPoint: + case SampleControlPoint: + // skip legacy types. + continue; + + default: + newControlPoints.Add(controlPoint.Time, controlPoint); + break; + } + } + + return newControlPoints; + } + public BeatmapInfo BeatmapInfo { get => beatmapInfo; - set => throw new InvalidOperationException(); + set => throw new InvalidOperationException($"Can't set {nameof(BeatmapInfo)} on {nameof(EditorBeatmap)}"); } public BeatmapMetadata Metadata => beatmapInfo.Metadata; diff --git a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs index f650ffa5a3..475c894b30 100644 --- a/osu.Game/Screens/Edit/EditorBeatmapSkin.cs +++ b/osu.Game/Screens/Edit/EditorBeatmapSkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Audio.Sample; @@ -39,7 +41,7 @@ namespace osu.Game.Screens.Edit ComboColours = new BindableList(); if (Skin.Configuration.ComboColours != null) ComboColours.AddRange(Skin.Configuration.ComboColours.Select(c => (Colour4)c)); - ComboColours.BindCollectionChanged((_, __) => updateColours()); + ComboColours.BindCollectionChanged((_, _) => updateColours()); } private void invokeSkinChanged() => BeatmapSkinChanged?.Invoke(); diff --git a/osu.Game/Screens/Edit/EditorChangeHandler.cs b/osu.Game/Screens/Edit/EditorChangeHandler.cs index 333c518d3a..1a93f3f101 100644 --- a/osu.Game/Screens/Edit/EditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/EditorChangeHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Screens/Edit/EditorClipboard.cs b/osu.Game/Screens/Edit/EditorClipboard.cs index f6f0c09e00..f749f4bad6 100644 --- a/osu.Game/Screens/Edit/EditorClipboard.cs +++ b/osu.Game/Screens/Edit/EditorClipboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; namespace osu.Game.Screens.Edit diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 86e5729196..c3b29afd30 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Audio.Track; @@ -139,7 +141,7 @@ namespace osu.Game.Screens.Edit seekTime = timingPoint.Time + closestBeat * seekAmount; } - if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First()) + if (seekTime < timingPoint.Time && !ReferenceEquals(timingPoint, ControlPointInfo.TimingPoints.First())) seekTime = timingPoint.Time; SeekSmoothlyTo(seekTime); diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index 0a2b8437fa..d6af990b52 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -63,6 +65,8 @@ namespace osu.Game.Screens.Edit base.LoadComplete(); // will be restored via lease, see `DisallowExternalBeatmapRulesetChanges`. + if (!(Beatmap.Value is DummyWorkingBeatmap)) + Ruleset.Value = Beatmap.Value.BeatmapInfo.Ruleset; Mods.Value = Array.Empty(); } diff --git a/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs b/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs index 94a83a82aa..013971960b 100644 --- a/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs +++ b/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs b/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs index 25d7dfbb4a..be1545cac8 100644 --- a/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs +++ b/osu.Game/Screens/Edit/EditorRoundedScreenSettingsSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 31c34edd7c..92709484ff 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/EditorScreenMode.cs b/osu.Game/Screens/Edit/EditorScreenMode.cs index ecd39f9b57..81fcf23cdf 100644 --- a/osu.Game/Screens/Edit/EditorScreenMode.cs +++ b/osu.Game/Screens/Edit/EditorScreenMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Screens.Edit diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 0b80af68f2..b3aafb9730 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs index 694d0253e0..d4387a0263 100644 --- a/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs +++ b/osu.Game/Screens/Edit/EditorSkinProvidingContainer.cs @@ -3,8 +3,6 @@ using osu.Game.Skinning; -#nullable enable - namespace osu.Game.Screens.Edit { /// diff --git a/osu.Game/Screens/Edit/EditorState.cs b/osu.Game/Screens/Edit/EditorState.cs index 4690074e3d..1751de4d3e 100644 --- a/osu.Game/Screens/Edit/EditorState.cs +++ b/osu.Game/Screens/Edit/EditorState.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.Screens.Edit { /// diff --git a/osu.Game/Screens/Edit/EditorTable.cs b/osu.Game/Screens/Edit/EditorTable.cs index 26819dcfe7..a290cce708 100644 --- a/osu.Game/Screens/Edit/EditorTable.cs +++ b/osu.Game/Screens/Edit/EditorTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; @@ -95,7 +97,7 @@ namespace osu.Game.Screens.Edit [BackgroundDependencyLoader] private void load(OverlayColourProvider colours) { - hoveredBackground.Colour = colourHover = colours.Background1; + colourHover = colours.Background1; colourSelected = colours.Colour3; } @@ -103,8 +105,7 @@ namespace osu.Game.Screens.Edit { base.LoadComplete(); - // Reduce flicker of rows when offset is being changed rapidly. - // Probably need to reconsider this. + updateState(); FinishTransforms(true); } diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs index f7e450b0e2..fd230a97bc 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -33,7 +35,13 @@ namespace osu.Game.Screens.Edit.GameplayTest ScoreProcessor.HasCompleted.BindValueChanged(completed => { if (completed.NewValue) - Scheduler.AddDelayed(this.Exit, RESULTS_DISPLAY_DELAY); + { + Scheduler.AddDelayed(() => + { + if (this.IsCurrentScreen()) + this.Exit(); + }, RESULTS_DISPLAY_DELAY); + } }); } diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs index c16bb8677c..d3260f1e7d 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs b/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs index 9334c74706..37e1c99d98 100644 --- a/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs +++ b/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs b/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs index fb7ab39f7a..3e1e0c4cfe 100644 --- a/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs +++ b/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Screens/Edit/IEditorChangeHandler.cs b/osu.Game/Screens/Edit/IEditorChangeHandler.cs index 0283421b8c..e7abc1c43d 100644 --- a/osu.Game/Screens/Edit/IEditorChangeHandler.cs +++ b/osu.Game/Screens/Edit/IEditorChangeHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index 3ed2a7efe2..b4647c2b64 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -1,15 +1,20 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; +using System.Linq; using System.Text; using DiffPlex; +using DiffPlex.Model; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Formats; using osu.Game.IO; using osu.Game.Skinning; using Decoder = osu.Game.Beatmaps.Formats.Decoder; @@ -32,61 +37,107 @@ namespace osu.Game.Screens.Edit { // Diff the beatmaps var result = new Differ().CreateLineDiffs(readString(currentState), readString(newState), true, false); + IBeatmap newBeatmap = null; - // Find the index of [HitObject] sections. Lines changed prior to this index are ignored. - int oldHitObjectsIndex = Array.IndexOf(result.PiecesOld, "[HitObjects]"); - int newHitObjectsIndex = Array.IndexOf(result.PiecesNew, "[HitObjects]"); + editorBeatmap.BeginChange(); + processHitObjects(result, () => newBeatmap ??= readBeatmap(newState)); + processTimingPoints(() => newBeatmap ??= readBeatmap(newState)); + editorBeatmap.EndChange(); + } - Debug.Assert(oldHitObjectsIndex >= 0); - Debug.Assert(newHitObjectsIndex >= 0); + private void processTimingPoints(Func getNewBeatmap) + { + ControlPointInfo newControlPoints = EditorBeatmap.ConvertControlPoints(getNewBeatmap().ControlPointInfo); - var toRemove = new List(); - var toAdd = new List(); + // Remove all groups from the current beatmap which don't have a corresponding equal group in the new beatmap. + foreach (var oldGroup in editorBeatmap.ControlPointInfo.Groups.ToArray()) + { + var newGroup = newControlPoints.GroupAt(oldGroup.Time); + + if (!oldGroup.Equals(newGroup)) + editorBeatmap.ControlPointInfo.RemoveGroup(oldGroup); + } + + // Add all groups from the new beatmap which don't have a corresponding equal group in the old beatmap. + foreach (var newGroup in newControlPoints.Groups) + { + var oldGroup = editorBeatmap.ControlPointInfo.GroupAt(newGroup.Time); + + if (!newGroup.Equals(oldGroup)) + { + foreach (var point in newGroup.ControlPoints) + editorBeatmap.ControlPointInfo.Add(newGroup.Time, point); + } + } + } + + private void processHitObjects(DiffResult result, Func getNewBeatmap) + { + findChangedIndices(result, LegacyDecoder.Section.HitObjects, out var removedIndices, out var addedIndices); + + for (int i = removedIndices.Count - 1; i >= 0; i--) + editorBeatmap.RemoveAt(removedIndices[i]); + + if (addedIndices.Count > 0) + { + var newBeatmap = getNewBeatmap(); + + foreach (int i in addedIndices) + editorBeatmap.Insert(i, newBeatmap.HitObjects[i]); + } + } + + private void findChangedIndices(DiffResult result, LegacyDecoder.Section section, out List removedIndices, out List addedIndices) + { + removedIndices = new List(); + addedIndices = new List(); + + // Find the start and end indices of the relevant section headers in both the old and the new beatmap file. Lines changed outside of the modified ranges are ignored. + int oldSectionStartIndex = Array.IndexOf(result.PiecesOld, $"[{section}]"); + if (oldSectionStartIndex == -1) + return; + + int oldSectionEndIndex = Array.FindIndex(result.PiecesOld, oldSectionStartIndex + 1, s => s.StartsWith('[')); + if (oldSectionEndIndex == -1) + oldSectionEndIndex = result.PiecesOld.Length; + + int newSectionStartIndex = Array.IndexOf(result.PiecesNew, $"[{section}]"); + if (newSectionStartIndex == -1) + return; + + int newSectionEndIndex = Array.FindIndex(result.PiecesNew, newSectionStartIndex + 1, s => s.StartsWith('[')); + if (newSectionEndIndex == -1) + newSectionEndIndex = result.PiecesNew.Length; foreach (var block in result.DiffBlocks) { - // Removed hitobjects + // Removed indices for (int i = 0; i < block.DeleteCountA; i++) { - int hoIndex = block.DeleteStartA + i - oldHitObjectsIndex - 1; + int objectIndex = block.DeleteStartA + i; - if (hoIndex < 0) + if (objectIndex <= oldSectionStartIndex || objectIndex >= oldSectionEndIndex) continue; - toRemove.Add(hoIndex); + removedIndices.Add(objectIndex - oldSectionStartIndex - 1); } - // Added hitobjects + // Added indices for (int i = 0; i < block.InsertCountB; i++) { - int hoIndex = block.InsertStartB + i - newHitObjectsIndex - 1; + int objectIndex = block.InsertStartB + i; - if (hoIndex < 0) + if (objectIndex <= newSectionStartIndex || objectIndex >= newSectionEndIndex) continue; - toAdd.Add(hoIndex); + addedIndices.Add(objectIndex - newSectionStartIndex - 1); } } // Sort the indices to ensure that removal + insertion indices don't get jumbled up post-removal or post-insertion. // This isn't strictly required, but the differ makes no guarantees about order. - toRemove.Sort(); - toAdd.Sort(); - - editorBeatmap.BeginChange(); - - // Apply the changes. - for (int i = toRemove.Count - 1; i >= 0; i--) - editorBeatmap.RemoveAt(toRemove[i]); - - if (toAdd.Count > 0) - { - IBeatmap newBeatmap = readBeatmap(newState); - foreach (int i in toAdd) - editorBeatmap.Insert(i, newBeatmap.HitObjects[i]); - } - - editorBeatmap.EndChange(); + removedIndices.Sort(); + addedIndices.Sort(); } private string readString(byte[] state) => Encoding.UTF8.GetString(state); diff --git a/osu.Game/Screens/Edit/PromptForSaveDialog.cs b/osu.Game/Screens/Edit/PromptForSaveDialog.cs index 4f70491ade..59a697d91c 100644 --- a/osu.Game/Screens/Edit/PromptForSaveDialog.cs +++ b/osu.Game/Screens/Edit/PromptForSaveDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Screens/Edit/Setup/ColoursSection.cs b/osu.Game/Screens/Edit/Setup/ColoursSection.cs index 05d9855a24..621abf5580 100644 --- a/osu.Game/Screens/Edit/Setup/ColoursSection.cs +++ b/osu.Game/Screens/Edit/Setup/ColoursSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Screens/Edit/Setup/DesignSection.cs b/osu.Game/Screens/Edit/Setup/DesignSection.cs index d5d93db050..40bbfeaf7d 100644 --- a/osu.Game/Screens/Edit/Setup/DesignSection.cs +++ b/osu.Game/Screens/Edit/Setup/DesignSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using System.Linq; @@ -98,7 +100,7 @@ namespace osu.Game.Screens.Edit.Setup EnableCountdown.Current.BindValueChanged(_ => updateBeatmap()); CountdownSpeed.Current.BindValueChanged(_ => updateBeatmap()); - CountdownOffset.OnCommit += (_, __) => onOffsetCommitted(); + CountdownOffset.OnCommit += (_, _) => onOffsetCommitted(); widescreenSupport.Current.BindValueChanged(_ => updateBeatmap()); epilepsyWarning.Current.BindValueChanged(_ => updateBeatmap()); diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index e799081115..5ce5d05d64 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs deleted file mode 100644 index fd916894ea..0000000000 --- a/osu.Game/Screens/Edit/Setup/FileChooserLabelledTextBox.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using osu.Framework.Allocation; -using osu.Framework.Bindables; -using osu.Framework.Extensions; -using osu.Framework.Extensions.ObjectExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Database; -using osu.Game.Graphics.UserInterfaceV2; -using osuTK; - -namespace osu.Game.Screens.Edit.Setup -{ - /// - /// A labelled textbox which reveals an inline file chooser when clicked. - /// - internal class FileChooserLabelledTextBox : LabelledTextBoxWithPopover, ICanAcceptFiles - { - private readonly string[] handledExtensions; - - public IEnumerable HandledExtensions => handledExtensions; - - private readonly Bindable currentFile = new Bindable(); - - [Resolved] - private OsuGameBase game { get; set; } = null!; - - public FileChooserLabelledTextBox(params string[] handledExtensions) - { - this.handledExtensions = handledExtensions; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - game.RegisterImportHandler(this); - currentFile.BindValueChanged(onFileSelected); - } - - private void onFileSelected(ValueChangedEvent file) - { - if (file.NewValue == null) - return; - - this.HidePopover(); - Current.Value = file.NewValue.FullName; - } - - Task ICanAcceptFiles.Import(params string[] paths) - { - Schedule(() => currentFile.Value = new FileInfo(paths.First())); - return Task.CompletedTask; - } - - Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException(); - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (game.IsNotNull()) - game.UnregisterImportHandler(this); - } - - public override Popover GetPopover() => new FileChooserPopover(handledExtensions, currentFile); - - private class FileChooserPopover : OsuPopover - { - public FileChooserPopover(string[] handledExtensions, Bindable currentFile) - { - Child = new Container - { - Size = new Vector2(600, 400), - Child = new OsuFileSelector(currentFile.Value?.DirectoryName, handledExtensions) - { - RelativeSizeAxes = Axes.Both, - CurrentFile = { BindTarget = currentFile } - }, - }; - } - } - } -} diff --git a/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs b/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs new file mode 100644 index 0000000000..efc8b6978e --- /dev/null +++ b/osu.Game/Screens/Edit/Setup/LabelledFileChooser.cs @@ -0,0 +1,131 @@ +// Copyright (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.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; +using osu.Framework.Platform; +using osu.Game.Database; +using osu.Game.Graphics.UserInterfaceV2; +using osuTK; + +namespace osu.Game.Screens.Edit.Setup +{ + /// + /// A labelled drawable displaying file chooser on click, with placeholder text support. + /// todo: this should probably not use PopoverTextBox just to display placeholder text, but is the best way for now. + /// + internal class LabelledFileChooser : LabelledDrawable, IHasCurrentValue, ICanAcceptFiles, IHasPopover + { + private readonly string[] handledExtensions; + + public IEnumerable HandledExtensions => handledExtensions; + + [Resolved] + private OsuGameBase game { get; set; } = null!; + + /// + /// The initial path to use when displaying the . + /// + /// + /// Uses a value before the first selection is made + /// to ensure that the first selection starts at . + /// + private string? initialChooserPath; + + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + + public LocalisableString Text + { + get => Component.PlaceholderText; + set => Component.PlaceholderText = value; + } + + public CompositeDrawable TabbableContentContainer + { + set => Component.TabbableContentContainer = value; + } + + public LabelledFileChooser(params string[] handledExtensions) + : base(false) + { + this.handledExtensions = handledExtensions; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + game.RegisterImportHandler(this); + Current.BindValueChanged(onFileSelected); + } + + private void onFileSelected(ValueChangedEvent file) + { + if (file.NewValue != null) + this.HidePopover(); + + initialChooserPath = file.NewValue?.DirectoryName; + } + + Task ICanAcceptFiles.Import(params string[] paths) + { + Schedule(() => Current.Value = new FileInfo(paths.First())); + return Task.CompletedTask; + } + + Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException(); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (game.IsNotNull()) + game.UnregisterImportHandler(this); + } + + protected override LabelledTextBoxWithPopover.PopoverTextBox CreateComponent() => new LabelledTextBoxWithPopover.PopoverTextBox + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + CornerRadius = CORNER_RADIUS, + OnFocused = this.ShowPopover, + }; + + public Popover GetPopover() => new FileChooserPopover(handledExtensions, Current, initialChooserPath); + + private class FileChooserPopover : OsuPopover + { + public FileChooserPopover(string[] handledExtensions, Bindable currentFile, string? chooserPath) + { + Child = new Container + { + Size = new Vector2(600, 400), + Child = new OsuFileSelector(chooserPath, handledExtensions) + { + RelativeSizeAxes = Axes.Both, + CurrentFile = { BindTarget = currentFile } + }, + }; + } + } + } +} diff --git a/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs b/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs index c39b4d6f41..a9cf5357c8 100644 --- a/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/LabelledRomanisedTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs b/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs index 799311dd2d..0eb74df575 100644 --- a/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs +++ b/osu.Game/Screens/Edit/Setup/LabelledTextBoxWithPopover.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Setup/MetadataSection.cs b/osu.Game/Screens/Edit/Setup/MetadataSection.cs index 6262b4c18b..854dec2001 100644 --- a/osu.Game/Screens/Edit/Setup/MetadataSection.cs +++ b/osu.Game/Screens/Edit/Setup/MetadataSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs index 1e97218074..1f8381e1ed 100644 --- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs +++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using osu.Framework.Allocation; @@ -8,15 +10,14 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Beatmaps; -using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; namespace osu.Game.Screens.Edit.Setup { internal class ResourcesSection : SetupSection { - private LabelledTextBox audioTrackTextBox; - private LabelledTextBox backgroundTextBox; + private LabelledFileChooser audioTrackChooser; + private LabelledFileChooser backgroundChooser; public override LocalisableString Title => "Resources"; @@ -40,76 +41,81 @@ namespace osu.Game.Screens.Edit.Setup { Children = new Drawable[] { - backgroundTextBox = new FileChooserLabelledTextBox(".jpg", ".jpeg", ".png") + backgroundChooser = new LabelledFileChooser(".jpg", ".jpeg", ".png") { Label = "Background", FixedLabelWidth = LABEL_WIDTH, - PlaceholderText = "Click to select a background image", - Current = { Value = working.Value.Metadata.BackgroundFile }, TabbableContentContainer = this }, - audioTrackTextBox = new FileChooserLabelledTextBox(".mp3", ".ogg") + audioTrackChooser = new LabelledFileChooser(".mp3", ".ogg") { Label = "Audio Track", FixedLabelWidth = LABEL_WIDTH, - PlaceholderText = "Click to select a track", - Current = { Value = working.Value.Metadata.AudioFile }, TabbableContentContainer = this }, }; - backgroundTextBox.Current.BindValueChanged(backgroundChanged); - audioTrackTextBox.Current.BindValueChanged(audioTrackChanged); + if (!string.IsNullOrEmpty(working.Value.Metadata.BackgroundFile)) + backgroundChooser.Current.Value = new FileInfo(working.Value.Metadata.BackgroundFile); + + if (!string.IsNullOrEmpty(working.Value.Metadata.AudioFile)) + audioTrackChooser.Current.Value = new FileInfo(working.Value.Metadata.AudioFile); + + backgroundChooser.Current.BindValueChanged(backgroundChanged); + audioTrackChooser.Current.BindValueChanged(audioTrackChanged); + + updatePlaceholderText(); } - public bool ChangeBackgroundImage(string path) + public bool ChangeBackgroundImage(FileInfo source) { - var info = new FileInfo(path); - - if (!info.Exists) + if (!source.Exists) return false; var set = working.Value.BeatmapSetInfo; + var destination = new FileInfo($@"bg{source.Extension}"); + // remove the previous background for now. // in the future we probably want to check if this is being used elsewhere (other difficulties?) var oldFile = set.Files.FirstOrDefault(f => f.Filename == working.Value.Metadata.BackgroundFile); - using (var stream = info.OpenRead()) + using (var stream = source.OpenRead()) { if (oldFile != null) beatmaps.DeleteFile(set, oldFile); - beatmaps.AddFile(set, stream, info.Name); + beatmaps.AddFile(set, stream, destination.Name); } - working.Value.Metadata.BackgroundFile = info.Name; + working.Value.Metadata.BackgroundFile = destination.Name; header.Background.UpdateBackground(); return true; } - public bool ChangeAudioTrack(string path) + public bool ChangeAudioTrack(FileInfo source) { - var info = new FileInfo(path); - - if (!info.Exists) + if (!source.Exists) return false; var set = working.Value.BeatmapSetInfo; + var destination = new FileInfo($@"audio{source.Extension}"); + // remove the previous audio track for now. // in the future we probably want to check if this is being used elsewhere (other difficulties?) var oldFile = set.Files.FirstOrDefault(f => f.Filename == working.Value.Metadata.AudioFile); - using (var stream = info.OpenRead()) + using (var stream = source.OpenRead()) { if (oldFile != null) beatmaps.DeleteFile(set, oldFile); - beatmaps.AddFile(set, stream, info.Name); + + beatmaps.AddFile(set, stream, destination.Name); } - working.Value.Metadata.AudioFile = info.Name; + working.Value.Metadata.AudioFile = destination.Name; music.ReloadCurrentTrack(); @@ -117,16 +123,31 @@ namespace osu.Game.Screens.Edit.Setup return true; } - private void backgroundChanged(ValueChangedEvent filePath) + private void backgroundChanged(ValueChangedEvent file) { - if (!ChangeBackgroundImage(filePath.NewValue)) - backgroundTextBox.Current.Value = filePath.OldValue; + if (!ChangeBackgroundImage(file.NewValue)) + backgroundChooser.Current.Value = file.OldValue; + + updatePlaceholderText(); } - private void audioTrackChanged(ValueChangedEvent filePath) + private void audioTrackChanged(ValueChangedEvent file) { - if (!ChangeAudioTrack(filePath.NewValue)) - audioTrackTextBox.Current.Value = filePath.OldValue; + if (!ChangeAudioTrack(file.NewValue)) + audioTrackChooser.Current.Value = file.OldValue; + + updatePlaceholderText(); + } + + private void updatePlaceholderText() + { + audioTrackChooser.Text = audioTrackChooser.Current.Value == null + ? "Click to select a track" + : "Click to replace the track"; + + backgroundChooser.Text = backgroundChooser.Current.Value == null + ? "Click to select a background image" + : "Click to replace the background image"; } } } diff --git a/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs b/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs index 935842ff99..db0641feba 100644 --- a/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs +++ b/osu.Game/Screens/Edit/Setup/RulesetSetupSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osu.Game.Rulesets; diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs index e0fc5f1aff..036202a503 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs b/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs index 2412f1c4ed..c531f1da90 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs b/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs index 17fb97d41f..5680d75f4e 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreenHeaderBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Setup/SetupSection.cs b/osu.Game/Screens/Edit/Setup/SetupSection.cs index 02bb05d227..727a94a590 100644 --- a/osu.Game/Screens/Edit/Setup/SetupSection.cs +++ b/osu.Game/Screens/Edit/Setup/SetupSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs index 938c7f9cf0..1f95156aba 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 77d875b67f..b51da2c53d 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -52,6 +54,8 @@ namespace osu.Game.Screens.Edit.Timing Columns = createHeaders(); Content = value.Select(createContent).ToArray().ToRectangular(); + + updateSelectedGroup(); } } @@ -59,13 +63,20 @@ namespace osu.Game.Screens.Edit.Timing { base.LoadComplete(); - selectedGroup.BindValueChanged(group => + selectedGroup.BindValueChanged(_ => { // TODO: This should scroll the selected row into view. - foreach (var b in BackgroundFlow) b.Selected = b.Item == group.NewValue; + updateSelectedGroup(); }, true); } + private void updateSelectedGroup() + { + // TODO: This should scroll the selected row into view. + foreach (var b in BackgroundFlow) + b.Selected = ReferenceEquals(b.Item, selectedGroup?.Value); + } + private TableColumn[] createHeaders() { var columns = new List @@ -142,7 +153,7 @@ namespace osu.Game.Screens.Edit.Timing protected override void LoadComplete() { base.LoadComplete(); - controlPoints.CollectionChanged += (_, __) => createChildren(); + controlPoints.CollectionChanged += (_, _) => createChildren(); } private void createChildren() diff --git a/osu.Game/Screens/Edit/Timing/EffectSection.cs b/osu.Game/Screens/Edit/Timing/EffectSection.cs index c9f73411f1..f7e59a75f1 100644 --- a/osu.Game/Screens/Edit/Timing/EffectSection.cs +++ b/osu.Game/Screens/Edit/Timing/EffectSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Timing/GroupSection.cs b/osu.Game/Screens/Edit/Timing/GroupSection.cs index f613488aae..e78cd18024 100644 --- a/osu.Game/Screens/Edit/Timing/GroupSection.cs +++ b/osu.Game/Screens/Edit/Timing/GroupSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs index 16a04982f5..ea6c6f31e4 100644 --- a/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/IndeterminateSliderWithTextBoxInput.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs b/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs index 51b58bd3dc..998e49a6ab 100644 --- a/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs +++ b/osu.Game/Screens/Edit/Timing/LabelledTimeSignature.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -74,7 +76,7 @@ namespace osu.Game.Screens.Edit.Timing base.LoadComplete(); Current.BindValueChanged(_ => updateFromCurrent(), true); - numeratorBox.OnCommit += (_, __) => updateFromNumeratorBox(); + numeratorBox.OnCommit += (_, _) => updateFromNumeratorBox(); } private void updateFromCurrent() diff --git a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs index 2ecd66a05f..3895959982 100644 --- a/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/MetronomeDisplay.cs @@ -1,7 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -12,6 +15,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Threading; using osu.Framework.Timing; using osu.Framework.Utils; using osu.Game.Beatmaps.ControlPoints; @@ -33,17 +37,29 @@ namespace osu.Game.Screens.Edit.Timing private IAdjustableClock metronomeClock; - private Sample clunk; + private Sample sampleTick; + private Sample sampleTickDownbeat; + private Sample sampleLatch; + + [CanBeNull] + private ScheduledDelegate tickPlaybackDelegate; [Resolved] private OverlayColourProvider overlayColourProvider { get; set; } public bool EnableClicking { get; set; } = true; + public MetronomeDisplay() + { + AllowMistimedEventFiring = false; + } + [BackgroundDependencyLoader] private void load(AudioManager audio) { - clunk = audio.Samples.Get(@"Multiplayer/countdown-tick"); + sampleTick = audio.Samples.Get(@"UI/metronome-tick"); + sampleTickDownbeat = audio.Samples.Get(@"UI/metronome-tick-downbeat"); + sampleLatch = audio.Samples.Get(@"UI/metronome-latch"); const float taper = 25; const float swing_vertical_offset = -23; @@ -215,6 +231,8 @@ namespace osu.Game.Screens.Edit.Timing private readonly BindableInt interpolatedBpm = new BindableInt(); + private ScheduledDelegate latchDelegate; + protected override void LoadComplete() { base.LoadComplete(); @@ -249,13 +267,28 @@ namespace osu.Game.Screens.Edit.Timing { swing.ClearTransforms(true); - using (swing.BeginDelayedSequence(350)) + isSwinging = false; + + tickPlaybackDelegate?.Cancel(); + tickPlaybackDelegate = null; + + // instantly latch if pendulum arm is close enough to center (to prevent awkward delayed playback of latch sound) + if (Precision.AlmostEquals(swing.Rotation, 0, 1)) + { + swing.RotateTo(0, 60, Easing.OutQuint); + stick.FadeColour(overlayColourProvider.Colour2, 1000, Easing.OutQuint); + sampleLatch?.Play(); + return; + } + + using (BeginDelayedSequence(350)) { swing.RotateTo(0, 1000, Easing.OutQuint); stick.FadeColour(overlayColourProvider.Colour2, 1000, Easing.OutQuint); - } - isSwinging = false; + using (BeginDelayedSequence(380)) + latchDelegate = Schedule(() => sampleLatch?.Play()); + } } } @@ -270,6 +303,9 @@ namespace osu.Game.Screens.Edit.Timing isSwinging = true; + latchDelegate?.Cancel(); + latchDelegate = null; + float currentAngle = swing.Rotation; float targetAngle = currentAngle > 0 ? -angle : angle; @@ -281,18 +317,18 @@ namespace osu.Game.Screens.Edit.Timing { stick.FlashColour(overlayColourProvider.Content1, beatLength, Easing.OutQuint); - Schedule(() => + tickPlaybackDelegate = Schedule(() => { if (!EnableClicking) return; - var channel = clunk?.GetChannel(); + var channel = beatIndex % timingPoint.TimeSignature.Numerator == 0 ? sampleTickDownbeat?.GetChannel() : sampleTick?.GetChannel(); - if (channel != null) - { - channel.Frequency.Value = RNG.NextDouble(0.98f, 1.02f); - channel.Play(); - } + if (channel == null) + return; + + channel.Frequency.Value = RNG.NextDouble(0.98f, 1.02f); + channel.Play(); }); } } diff --git a/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs b/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs index 595305b20f..cd3ced53da 100644 --- a/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs +++ b/osu.Game/Screens/Edit/Timing/RepeatingButtonBehaviour.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -23,6 +25,9 @@ namespace osu.Game.Screens.Edit.Timing private Sample sample; + public Action RepeatBegan; + public Action RepeatEnded; + /// /// An additive modifier for the frequency of the sample played on next actuation. /// This can be adjusted during the button's event to affect the repeat sample playback of that click. @@ -44,6 +49,7 @@ namespace osu.Game.Screens.Edit.Timing protected override bool OnMouseDown(MouseDownEvent e) { + RepeatBegan?.Invoke(); beginRepeat(); return true; } @@ -51,6 +57,7 @@ namespace osu.Game.Screens.Edit.Timing protected override void OnMouseUp(MouseUpEvent e) { adjustDelegate?.Cancel(); + RepeatEnded?.Invoke(); base.OnMouseUp(e); } diff --git a/osu.Game/Screens/Edit/Timing/RowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttribute.cs index 46bb62c9e0..e73a343583 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs index 6f7e790489..a8d2172f58 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeProgressBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs index d0a51f9faa..d65ef1799a 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/AttributeText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs index a8de476d67..17f8b01d07 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/DifficultyRowAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs index 1b33fd62aa..ef682dd3ad 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/EffectRowAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs index ac0797dba1..e06f6b7bfb 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/SampleRowAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs b/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs index 8a07088545..0b498650d4 100644 --- a/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs +++ b/osu.Game/Screens/Edit/Timing/RowAttributes/TimingRowAttribute.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; diff --git a/osu.Game/Screens/Edit/Timing/Section.cs b/osu.Game/Screens/Edit/Timing/Section.cs index 17147c21f4..02789c0cbf 100644 --- a/osu.Game/Screens/Edit/Timing/Section.cs +++ b/osu.Game/Screens/Edit/Timing/Section.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs index 9f036f0215..4dcb5ad2ba 100644 --- a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using osu.Framework.Bindables; @@ -68,7 +70,7 @@ namespace osu.Game.Screens.Edit.Timing Current.TriggerChange(); }; - Current.BindValueChanged(val => + Current.BindValueChanged(_ => { decimal decimalValue = slider.Current.Value.ToDecimal(NumberFormatInfo.InvariantInfo); textBox.Text = decimalValue.ToString($@"N{FormatUtils.FindPrecision(decimalValue)}"); diff --git a/osu.Game/Screens/Edit/Timing/TapButton.cs b/osu.Game/Screens/Edit/Timing/TapButton.cs index a6227cbe27..151c3cea2e 100644 --- a/osu.Game/Screens/Edit/Timing/TapButton.cs +++ b/osu.Game/Screens/Edit/Timing/TapButton.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs index 9b5574d3cb..abc73851e4 100644 --- a/osu.Game/Screens/Edit/Timing/TapTimingControl.cs +++ b/osu.Game/Screens/Edit/Timing/TapTimingControl.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -197,6 +195,8 @@ namespace osu.Game.Screens.Edit.Timing private void adjustOffset(double adjust) { + bool wasAtStart = editorClock.CurrentTimeAccurate == selectedGroup.Value.Time; + // VERY TEMPORARY var currentGroupItems = selectedGroup.Value.ControlPoints.ToArray(); @@ -210,7 +210,7 @@ namespace osu.Game.Screens.Edit.Timing // the control point might not necessarily exist yet, if currentGroupItems was empty. selectedGroup.Value = beatmap.ControlPointInfo.GroupAt(newOffset, true); - if (!editorClock.IsRunning) + if (!editorClock.IsRunning && wasAtStart) editorClock.Seek(newOffset); } diff --git a/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs b/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs index 9540547d89..16dea328da 100644 --- a/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs +++ b/osu.Game/Screens/Edit/Timing/TimingAdjustButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -44,6 +46,9 @@ namespace osu.Game.Screens.Edit.Timing [Resolved] private OverlayColourProvider colourProvider { get; set; } + [Resolved] + private EditorBeatmap editorBeatmap { get; set; } + public TimingAdjustButton(double adjustAmount) { this.adjustAmount = adjustAmount; @@ -72,7 +77,11 @@ namespace osu.Game.Screens.Edit.Timing } }); - AddInternal(repeatBehaviour = new RepeatingButtonBehaviour(this)); + AddInternal(repeatBehaviour = new RepeatingButtonBehaviour(this) + { + RepeatBegan = () => editorBeatmap.BeginChange(), + RepeatEnded = () => editorBeatmap.EndChange() + }); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Edit/Timing/TimingScreen.cs b/osu.Game/Screens/Edit/Timing/TimingScreen.cs index f498aa917e..fd218209d4 100644 --- a/osu.Game/Screens/Edit/Timing/TimingScreen.cs +++ b/osu.Game/Screens/Edit/Timing/TimingScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -135,7 +137,7 @@ namespace osu.Game.Screens.Edit.Timing }, true); controlPointGroups.BindTo(Beatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((sender, args) => + controlPointGroups.BindCollectionChanged((_, _) => { table.ControlGroups = controlPointGroups; changeHandler?.SaveState(); @@ -220,7 +222,7 @@ namespace osu.Game.Screens.Edit.Timing // Try and create matching types from the currently selected control point. var selected = selectedGroup.Value; - if (selected != null && selected != group) + if (selected != null && !ReferenceEquals(selected, group)) { foreach (var controlPoint in selected.ControlPoints) { diff --git a/osu.Game/Screens/Edit/Timing/TimingSection.cs b/osu.Game/Screens/Edit/Timing/TimingSection.cs index 1a97058d73..9b86969db1 100644 --- a/osu.Game/Screens/Edit/Timing/TimingSection.cs +++ b/osu.Game/Screens/Edit/Timing/TimingSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -75,7 +77,7 @@ namespace osu.Game.Screens.Edit.Timing { Label = "BPM"; - OnCommit += (val, isNew) => + OnCommit += (_, isNew) => { if (!isNew) return; diff --git a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs index 0745187e43..2956a28547 100644 --- a/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs +++ b/osu.Game/Screens/Edit/Timing/WaveformComparisonDisplay.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Linq; using osu.Framework.Allocation; @@ -93,7 +91,7 @@ namespace osu.Game.Screens.Edit.Timing selectedGroup.BindValueChanged(_ => updateTimingGroup(), true); controlPointGroups.BindTo(editorBeatmap.ControlPointInfo.Groups); - controlPointGroups.BindCollectionChanged((_, __) => updateTimingGroup()); + controlPointGroups.BindCollectionChanged((_, _) => updateTimingGroup()); beatLength.BindValueChanged(_ => regenerateDisplay(true), true); @@ -130,7 +128,7 @@ namespace osu.Game.Screens.Edit.Timing double? offsetChange = newStartTime - selectedGroupStartTime; var nextGroup = editorBeatmap.ControlPointInfo.TimingPoints - .SkipWhile(g => g != tcp) + .SkipWhile(g => !ReferenceEquals(g, tcp)) .Skip(1) .FirstOrDefault(); diff --git a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs index 3d3539ee2f..78d052702a 100644 --- a/osu.Game/Screens/Edit/TransactionalCommitComponent.cs +++ b/osu.Game/Screens/Edit/TransactionalCommitComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Verify/InterpretationSection.cs b/osu.Game/Screens/Edit/Verify/InterpretationSection.cs index 9548f8aaa9..276c2a3ea9 100644 --- a/osu.Game/Screens/Edit/Verify/InterpretationSection.cs +++ b/osu.Game/Screens/Edit/Verify/InterpretationSection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs index 84b2609a61..bffda4ec41 100644 --- a/osu.Game/Screens/Edit/Verify/IssueList.cs +++ b/osu.Game/Screens/Edit/Verify/IssueList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -85,7 +87,7 @@ namespace osu.Game.Screens.Edit.Verify base.LoadComplete(); verify.InterpretedDifficulty.BindValueChanged(_ => refresh()); - verify.HiddenIssueTypes.BindCollectionChanged((_, __) => refresh()); + verify.HiddenIssueTypes.BindCollectionChanged((_, _) => refresh()); refresh(); } diff --git a/osu.Game/Screens/Edit/Verify/IssueSettings.cs b/osu.Game/Screens/Edit/Verify/IssueSettings.cs index ae3ef7e0b0..70065f6f0d 100644 --- a/osu.Game/Screens/Edit/Verify/IssueSettings.cs +++ b/osu.Game/Screens/Edit/Verify/IssueSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Verify/IssueTable.cs b/osu.Game/Screens/Edit/Verify/IssueTable.cs index b38a62d838..f1a76dcbf5 100644 --- a/osu.Game/Screens/Edit/Verify/IssueTable.cs +++ b/osu.Game/Screens/Edit/Verify/IssueTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs index 56e16bb746..3030018138 100644 --- a/osu.Game/Screens/Edit/Verify/VerifyScreen.cs +++ b/osu.Game/Screens/Edit/Verify/VerifyScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -29,7 +31,7 @@ namespace osu.Game.Screens.Edit.Verify [BackgroundDependencyLoader] private void load() { - InterpretedDifficulty.Default = BeatmapDifficultyCache.GetDifficultyRating(EditorBeatmap.BeatmapInfo.StarRating); + InterpretedDifficulty.Default = StarDifficulty.GetDifficultyRating(EditorBeatmap.BeatmapInfo.StarRating); InterpretedDifficulty.SetDefault(); Child = new Container diff --git a/osu.Game/Screens/Edit/Verify/VisibilitySection.cs b/osu.Game/Screens/Edit/Verify/VisibilitySection.cs index 0bdc8c0efd..fbf6982984 100644 --- a/osu.Game/Screens/Edit/Verify/VisibilitySection.cs +++ b/osu.Game/Screens/Edit/Verify/VisibilitySection.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs index 7e095f526e..3d3f67e70e 100644 --- a/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs +++ b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/IHandlePresentBeatmap.cs b/osu.Game/Screens/IHandlePresentBeatmap.cs index 60801fb3eb..62cd2c3d3e 100644 --- a/osu.Game/Screens/IHandlePresentBeatmap.cs +++ b/osu.Game/Screens/IHandlePresentBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets; diff --git a/osu.Game/Screens/IHasSubScreenStack.cs b/osu.Game/Screens/IHasSubScreenStack.cs index c5e2015109..325702313b 100644 --- a/osu.Game/Screens/IHasSubScreenStack.cs +++ b/osu.Game/Screens/IHasSubScreenStack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Screens; namespace osu.Game.Screens diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 910a0c7d61..7d8657a3df 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/IPerformFromScreenRunner.cs b/osu.Game/Screens/IPerformFromScreenRunner.cs index 655bebdeb0..c12a52a784 100644 --- a/osu.Game/Screens/IPerformFromScreenRunner.cs +++ b/osu.Game/Screens/IPerformFromScreenRunner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Import/FileImportScreen.cs b/osu.Game/Screens/Import/FileImportScreen.cs index 32ce54aa29..e3d8de2dfd 100644 --- a/osu.Game/Screens/Import/FileImportScreen.cs +++ b/osu.Game/Screens/Import/FileImportScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using System.Linq; using System.Threading.Tasks; diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 52e83c9e98..dbb1278d76 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index d59996a4eb..bf6e0cee83 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index b48aef330a..04bffda81b 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -189,20 +191,48 @@ namespace osu.Game.Screens.Menu State = ButtonSystemState.Initial; } - protected override bool OnKeyDown(KeyDownEvent e) + /// + /// Triggers the if the current is . + /// + /// true if the was triggered, false otherwise. + private bool triggerInitialOsuLogo() { - if (e.Repeat || e.ControlPressed || e.ShiftPressed || e.AltPressed || e.SuperPressed) - return false; - if (State == ButtonSystemState.Initial) { logo?.TriggerClick(); return true; } + return false; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.Repeat || e.ControlPressed || e.ShiftPressed || e.AltPressed || e.SuperPressed) + return false; + + if (triggerInitialOsuLogo()) + return true; + return base.OnKeyDown(e); } + protected override bool OnJoystickPress(JoystickPressEvent e) + { + if (triggerInitialOsuLogo()) + return true; + + return base.OnJoystickPress(e); + } + + protected override bool OnMidiDown(MidiDownEvent e) + { + if (triggerInitialOsuLogo()) + return true; + + return base.OnMidiDown(e); + } + public bool OnPressed(KeyBindingPressEvent e) { if (e.Repeat) diff --git a/osu.Game/Screens/Menu/ConfirmExitDialog.cs b/osu.Game/Screens/Menu/ConfirmExitDialog.cs index 6488a2fd63..734ff6b23f 100644 --- a/osu.Game/Screens/Menu/ConfirmExitDialog.cs +++ b/osu.Game/Screens/Menu/ConfirmExitDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 24412cd85e..a81658a4b6 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -146,16 +148,17 @@ namespace osu.Game.Screens.Menu supportFlow.AddText(" to help support osu!'s development", formatSemiBold); } - heart = supportFlow.AddIcon(FontAwesome.Solid.Heart, t => + supportFlow.AddIcon(FontAwesome.Solid.Heart, t => { + heart = t; + t.Padding = new MarginPadding { Left = 5, Top = 3 }; t.Font = t.Font.With(size: 20); t.Origin = Anchor.Centre; t.Colour = colours.Pink; - }).Drawables.First(); - if (IsLoaded) - animateHeart(); + Schedule(() => heart?.FlashColour(Color4.White, 750, Easing.OutQuint).Loop()); + }); if (supportFlow.IsPresent) supportFlow.FadeInFromZero(500); @@ -171,6 +174,14 @@ namespace osu.Game.Screens.Menu ((IBindable)currentUser).BindTo(api.LocalUser); } + public override void OnSuspending(ScreenTransitionEvent e) + { + base.OnSuspending(e); + + // Once this screen has finished being displayed, we don't want to unnecessarily handle user change events. + currentUser.UnbindAll(); + } + public override void OnEntering(ScreenTransitionEvent e) { base.OnEntering(e); @@ -206,14 +217,12 @@ namespace osu.Game.Screens.Menu foreach (var c in textFlow.Children) c.FadeTo(0.001f).Delay(delay += 20).FadeIn(500); - animateHeart(); - this .FadeInFromZero(500) .Then(5500) .FadeOut(250) .ScaleTo(0.9f, 250, Easing.InQuint) - .Finally(d => + .Finally(_ => { if (nextScreen != null) this.Push(nextScreen); @@ -244,10 +253,5 @@ namespace osu.Game.Screens.Menu return tips[RNG.Next(0, tips.Length)]; } - - private void animateHeart() - { - heart.FlashColour(Color4.White, 750, Easing.OutQuint).Loop(); - } } } diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index a90b83c5fe..f82a6c9736 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index 8310ab06eb..24a365ffd1 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; diff --git a/osu.Game/Screens/Menu/IntroCircles.cs b/osu.Game/Screens/Menu/IntroCircles.cs index 00e2de62f0..faa9a267ce 100644 --- a/osu.Game/Screens/Menu/IntroCircles.cs +++ b/osu.Game/Screens/Menu/IntroCircles.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Menu/IntroScreen.cs b/osu.Game/Screens/Menu/IntroScreen.cs index d4072d6202..c1621ce78f 100644 --- a/osu.Game/Screens/Menu/IntroScreen.cs +++ b/osu.Game/Screens/Menu/IntroScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; @@ -17,7 +19,6 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Database; -using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -63,6 +64,8 @@ namespace osu.Game.Screens.Menu protected virtual string SeeyaSampleName => "Intro/seeya"; + protected override bool PlayExitSound => false; + private LeasedBindable beatmap; private OsuScreen nextScreen; @@ -85,6 +88,11 @@ namespace osu.Game.Screens.Menu /// protected bool UsingThemedIntro { get; private set; } + protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(false) + { + Colour = Color4.Black + }; + protected IntroScreen([CanBeNull] Func createNextScreen = null) { this.createNextScreen = createNextScreen; @@ -137,7 +145,7 @@ namespace osu.Game.Screens.Menu { // if we detect that the theme track or beatmap is unavailable this is either first startup or things are in a bad state. // this could happen if a user has nuked their files store. for now, reimport to repair this. - var import = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream($"Tracks/{BeatmapFile}"), BeatmapFile)).GetResultSafely(); + var import = beatmaps.Import(new ImportTask(game.Resources.GetStream($"Tracks/{BeatmapFile}"), BeatmapFile)).GetResultSafely(); import?.PerformWrite(b => b.Protected = true); @@ -198,6 +206,8 @@ namespace osu.Game.Screens.Menu { this.FadeIn(300); + ApplyToBackground(b => b.FadeColour(Color4.Black, 100)); + double fadeOutTime = exit_delay; var track = musicController.CurrentTrack; @@ -240,13 +250,22 @@ namespace osu.Game.Screens.Menu base.OnResuming(e); } + private bool backgroundFaded; + + protected void FadeInBackground(float duration = 0) + { + ApplyToBackground(b => b.FadeColour(Color4.White, duration)); + backgroundFaded = true; + } + public override void OnSuspending(ScreenTransitionEvent e) { base.OnSuspending(e); initialBeatmap = null; - } - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack(); + if (!backgroundFaded) + FadeInBackground(200); + } protected virtual void StartTrack() { diff --git a/osu.Game/Screens/Menu/IntroSequence.cs b/osu.Game/Screens/Menu/IntroSequence.cs index 3a5cd6857a..bc5aa83503 100644 --- a/osu.Game/Screens/Menu/IntroSequence.cs +++ b/osu.Game/Screens/Menu/IntroSequence.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Menu/IntroTriangles.cs b/osu.Game/Screens/Menu/IntroTriangles.cs index ba8314f103..6ad0350e43 100644 --- a/osu.Game/Screens/Menu/IntroTriangles.cs +++ b/osu.Game/Screens/Menu/IntroTriangles.cs @@ -1,24 +1,25 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; -using System.Collections.Generic; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Textures; -using osu.Framework.Utils; +using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Framework.Timing; +using osu.Framework.Utils; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; -using osu.Game.Screens.Backgrounds; using osuTK; using osuTK.Graphics; @@ -30,16 +31,9 @@ namespace osu.Game.Screens.Menu protected override string BeatmapFile => "triangles.osz"; - protected override BackgroundScreen CreateBackground() => background = new BackgroundScreenDefault(false) - { - Alpha = 0, - }; - [Resolved] private AudioManager audio { get; set; } - private BackgroundScreenDefault background; - private Sample welcome; private DecoupleableInterpolatingFramedClock decoupledClock; @@ -73,14 +67,22 @@ namespace osu.Game.Screens.Menu if (UsingThemedIntro) decoupledClock.ChangeSource(Track); - LoadComponentAsync(intro = new TrianglesIntroSequence(logo, background) + LoadComponentAsync(intro = new TrianglesIntroSequence(logo, () => FadeInBackground()) { RelativeSizeAxes = Axes.Both, Clock = decoupledClock, LoadMenu = LoadMenu - }, t => + }, _ => { - AddInternal(t); + AddInternal(intro); + + // There is a chance that the intro timed out before being displayed, and this scheduled callback could + // happen during the outro rather than intro. + // In such a scenario, we don't want to play the intro sample, nor attempt to start the intro track + // (that may have already been since disposed by MusicController). + if (DidLoadMenu) + return; + if (!UsingThemedIntro) welcome?.Play(); @@ -93,19 +95,10 @@ namespace osu.Game.Screens.Menu { base.OnSuspending(e); - // ensure the background is shown, even if the TriangleIntroSequence failed to do so. - background.ApplyToBackground(b => b.Show()); - // important as there is a clock attached to a track which will likely be disposed before returning to this screen. intro.Expire(); } - public override void OnResuming(ScreenTransitionEvent e) - { - base.OnResuming(e); - background.FadeOut(100); - } - protected override void StartTrack() { decoupledClock.Start(); @@ -114,7 +107,7 @@ namespace osu.Game.Screens.Menu private class TrianglesIntroSequence : CompositeDrawable { private readonly OsuLogo logo; - private readonly BackgroundScreenDefault background; + private readonly Action showBackgroundAction; private OsuSpriteText welcomeText; private RulesetFlow rulesets; @@ -126,10 +119,10 @@ namespace osu.Game.Screens.Menu public Action LoadMenu; - public TrianglesIntroSequence(OsuLogo logo, BackgroundScreenDefault background) + public TrianglesIntroSequence(OsuLogo logo, Action showBackgroundAction) { this.logo = logo; - this.background = background; + this.showBackgroundAction = showBackgroundAction; } [Resolved] @@ -203,7 +196,6 @@ namespace osu.Game.Screens.Menu rulesets.Hide(); lazerLogo.Hide(); - background.ApplyToBackground(b => b.Hide()); using (BeginAbsoluteSequence(0)) { @@ -265,7 +257,7 @@ namespace osu.Game.Screens.Menu logo.FadeIn(); - background.ApplyToBackground(b => b.Show()); + showBackgroundAction(); game.Add(new GameWideFlash()); @@ -338,24 +330,28 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - var modes = new List(); - - foreach (var ruleset in rulesets.AvailableRulesets) - { - var icon = new ConstrainedIconContainer - { - Icon = ruleset.CreateInstance().CreateIcon(), - Size = new Vector2(30), - }; - - modes.Add(icon); - } - AutoSizeAxes = Axes.Both; - Children = modes; Anchor = Anchor.Centre; Origin = Anchor.Centre; + + foreach (var ruleset in rulesets.AvailableRulesets) + { + try + { + var icon = new ConstrainedIconContainer + { + Icon = ruleset.CreateInstance().CreateIcon(), + Size = new Vector2(30), + }; + + Add(icon); + } + catch + { + Logger.Log($"Could not create ruleset icon for {ruleset.Name}. Please check for an update from the developer.", level: LogLevel.Error); + } + } } } diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index 9a6c949cad..9e56a3a0b7 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -1,13 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; -using osuTK; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -15,8 +15,8 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Audio; using osu.Game.Online.API; -using osu.Game.Screens.Backgrounds; using osu.Game.Skinning; +using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Menu @@ -33,13 +33,6 @@ namespace osu.Game.Screens.Menu private ISample pianoReverb; protected override string SeeyaSampleName => "Intro/Welcome/seeya"; - protected override BackgroundScreen CreateBackground() => background = new BackgroundScreenDefault(false) - { - Alpha = 0, - }; - - private BackgroundScreenDefault background; - public IntroWelcome([CanBeNull] Func createNextScreen = null) : base(createNextScreen) { @@ -98,7 +91,7 @@ namespace osu.Game.Screens.Menu logo.ScaleTo(1); logo.FadeIn(fade_in_time); - background.FadeIn(fade_in_time); + FadeInBackground(fade_in_time); LoadMenu(); }, delay_step_two); @@ -106,12 +99,6 @@ namespace osu.Game.Screens.Menu } } - public override void OnResuming(ScreenTransitionEvent e) - { - base.OnResuming(e); - background.FadeOut(100); - } - private class WelcomeIntroSequence : Container { private Drawable welcomeText; diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 34f1d46067..c66bd3639a 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 6fc8039413..066a37055c 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework.Allocation; @@ -8,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -62,9 +65,9 @@ namespace osu.Game.Screens.Menu [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } - private BackgroundScreenDefault background; + protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); - protected override BackgroundScreen CreateBackground() => background; + protected override bool PlayExitSound => false; private Bindable holdDelay; private Bindable loginDisplayed; @@ -143,7 +146,6 @@ namespace osu.Game.Screens.Menu Buttons.OnSettings = () => settings?.ToggleVisibility(); Buttons.OnBeatmapListing = () => beatmapListing?.ToggleVisibility(); - LoadComponentAsync(background = new BackgroundScreenDefault()); preloadSongSelect(); } @@ -298,6 +300,8 @@ namespace osu.Game.Screens.Menu public void PresentBeatmap(WorkingBeatmap beatmap, RulesetInfo ruleset) { + Logger.Log($"{nameof(MainMenu)} completing {nameof(PresentBeatmap)} with beatmap {beatmap} ruleset {ruleset}"); + Beatmap.Value = beatmap; Ruleset.Value = ruleset; diff --git a/osu.Game/Screens/Menu/MainMenuButton.cs b/osu.Game/Screens/Menu/MainMenuButton.cs index c07ada9419..f2b57b185e 100644 --- a/osu.Game/Screens/Menu/MainMenuButton.cs +++ b/osu.Game/Screens/Menu/MainMenuButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Menu/MenuLogoVisualisation.cs b/osu.Game/Screens/Menu/MenuLogoVisualisation.cs index f461136022..4324f02c84 100644 --- a/osu.Game/Screens/Menu/MenuLogoVisualisation.cs +++ b/osu.Game/Screens/Menu/MenuLogoVisualisation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Game.Skinning; using osu.Game.Online.API; diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index cd0c75c1a1..5214d87ee9 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index f5743c7d5a..0909f615f2 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -88,6 +90,8 @@ namespace osu.Game.Screens.Menu private const double early_activation = 60; + private const float triangles_paused_velocity = 0.5f; + public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; public OsuLogo() @@ -317,6 +321,11 @@ namespace osu.Game.Screens.Menu .FadeTo(visualizer_default_alpha * 1.8f * amplitudeAdjust, early_activation, Easing.Out).Then() .FadeTo(visualizer_default_alpha, beatLength); } + + this.Delay(early_activation).Schedule(() => + { + triangles.Velocity += amplitudeAdjust * (effectPoint.KiaiMode ? 6 : 3); + }); } public void PlayIntro() @@ -338,22 +347,17 @@ namespace osu.Game.Screens.Menu base.Update(); const float scale_adjust_cutoff = 0.4f; - const float velocity_adjust_cutoff = 0.98f; - const float paused_velocity = 0.5f; if (musicController.CurrentTrack.IsRunning) { float maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0; logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed)); - if (maxAmplitude > velocity_adjust_cutoff) - triangles.Velocity = 1 + Math.Max(0, maxAmplitude - velocity_adjust_cutoff) * 50; - else - triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, 1, 0.995f, Time.Elapsed); + triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, triangles_paused_velocity * (LastEffectPoint.KiaiMode ? 4 : 2), 0.995f, Time.Elapsed); } else { - triangles.Velocity = paused_velocity; + triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, triangles_paused_velocity, 0.9f, Time.Elapsed); } } diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index 237fe43168..6574c9a696 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Menu/StorageErrorDialog.cs b/osu.Game/Screens/Menu/StorageErrorDialog.cs index f4c77d5d8f..28ef413179 100644 --- a/osu.Game/Screens/Menu/StorageErrorDialog.cs +++ b/osu.Game/Screens/Menu/StorageErrorDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs index fb927411e6..7c48fc0871 100644 --- a/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs +++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Screens.Select; namespace osu.Game.Screens.OnlinePlay.Components diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs index 7cbe1a9017..39a887f820 100644 --- a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -25,7 +27,7 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - Playlist.CollectionChanged += (_, __) => updateText(); + Playlist.CollectionChanged += (_, _) => updateText(); updateText(); } diff --git a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs index 2b596da361..22839ab4d4 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs index f360a80599..c97e52c247 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs index 666d425f62..1ea84b60b9 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ListingPollingComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs b/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs index 89842e933b..9a48769405 100644 --- a/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs +++ b/osu.Game/Screens/OnlinePlay/Components/MatchBeatmapDetailArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -84,7 +86,7 @@ namespace osu.Game.Screens.OnlinePlay.Components switch (tab) { - case BeatmapDetailAreaPlaylistTabItem _: + case BeatmapDetailAreaPlaylistTabItem: playlistArea.Show(); break; diff --git a/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs b/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs deleted file mode 100644 index 8402619ebc..0000000000 --- a/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs +++ /dev/null @@ -1,76 +0,0 @@ -// 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; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps.Drawables; -using osu.Game.Rulesets; -using osuTK; - -namespace osu.Game.Screens.OnlinePlay.Components -{ - public class ModeTypeInfo : OnlinePlayComposite - { - private const float height = 28; - private const float transition_duration = 100; - - [Resolved] - private RulesetStore rulesets { get; set; } - - private Container drawableRuleset; - - public ModeTypeInfo() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - Container gameTypeContainer; - - InternalChild = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - LayoutDuration = 100, - Children = new[] - { - drawableRuleset = new Container - { - AutoSizeAxes = Axes.Both, - }, - gameTypeContainer = new Container - { - AutoSizeAxes = Axes.Both, - }, - }, - }; - - Type.BindValueChanged(type => gameTypeContainer.Child = new DrawableGameType(type.NewValue) { Size = new Vector2(height) }, true); - - Playlist.CollectionChanged += (_, __) => updateBeatmap(); - - updateBeatmap(); - } - - private void updateBeatmap() - { - var item = Playlist.FirstOrDefault(); - var ruleset = item == null ? null : rulesets.GetRuleset(item.RulesetID)?.CreateInstance(); - - if (item?.Beatmap != null && ruleset != null) - { - var mods = item.RequiredMods.Select(m => m.ToMod(ruleset)).ToArray(); - - drawableRuleset.FadeIn(transition_duration); - drawableRuleset.Child = new DifficultyIcon(item.Beatmap, ruleset.RulesetInfo, mods) { Size = new Vector2(height) }; - } - else - drawableRuleset.FadeOut(transition_duration); - } - } -} diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 9e964de31e..8c65649cc6 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -13,8 +13,6 @@ using osu.Game.Online.Rooms; using osuTK; using osuTK.Graphics; -#nullable enable - namespace osu.Game.Screens.OnlinePlay.Components { public abstract class OnlinePlayBackgroundScreen : BackgroundScreen diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index 2faa46e622..fe89eaf591 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps.Drawables; @@ -24,7 +26,7 @@ namespace osu.Game.Screens.OnlinePlay.Components InternalChild = sprite = CreateBackgroundSprite(); CurrentPlaylistItem.BindValueChanged(_ => updateBeatmap()); - Playlist.CollectionChanged += (_, __) => updateBeatmap(); + Playlist.CollectionChanged += (_, _) => updateBeatmap(); updateBeatmap(); } diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs index f667a3c1d2..b953136fdd 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs index 45b822d20a..a268d4d917 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components @@ -16,7 +18,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { base.LoadComplete(); - Playlist.BindCollectionChanged((_, __) => Details.Value = Playlist.GetTotalDuration(), true); + Playlist.BindCollectionChanged((_, _) => Details.Value = Playlist.GetTotalDuration(), true); } } } diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs index 53821da8fd..71b33bf247 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantCountDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs index c36d1a2e76..c66ae8b6d5 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs index 1d5552fa7d..2f38321e13 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -58,7 +60,7 @@ namespace osu.Game.Screens.OnlinePlay.Components [BackgroundDependencyLoader] private void load() { - RecentParticipants.CollectionChanged += (_, __) => updateParticipants(); + RecentParticipants.CollectionChanged += (_, _) => updateParticipants(); updateParticipants(); } diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs index 7e31591389..d882b3d97f 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index cdaa39d2be..0871fc9a72 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs b/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs index 3bad6cb183..cc517ca080 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomLocalUserInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index 4242886e66..35dc251e4d 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index cd224a7347..039e1d92b7 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Online; using osu.Game.Online.API; diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index e05bdf8c8e..3b8ba739d9 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; using osu.Game.Online.Rooms; diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 7425e46bd3..b6ef080e44 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -75,7 +77,7 @@ namespace osu.Game.Screens.OnlinePlay.Components base.LoadComplete(); DifficultyRange.BindValueChanged(_ => updateRange()); - Playlist.BindCollectionChanged((_, __) => updateRange(), true); + Playlist.BindCollectionChanged((_, _) => updateRange(), true); } private void updateRange() diff --git a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs index a7ea32ee7c..6122e7ec5e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs index 2a72fc6eb1..5193fe5cbf 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Bindables; @@ -179,7 +181,7 @@ namespace osu.Game.Screens.OnlinePlay // schedules added as the properties may change value while the drawable items haven't been created yet. SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(scrollToSelection)); - Items.BindCollectionChanged((_, __) => Scheduler.AddOnce(scrollToSelection), true); + Items.BindCollectionChanged((_, _) => Scheduler.AddOnce(scrollToSelection), true); } private void scrollToSelection() diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 39853a5c45..f38077a9a7 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -1,23 +1,28 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Collections; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -25,6 +30,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Online.Rooms; +using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; using osu.Game.Resources.Localisation.Web; using osu.Game.Rulesets; @@ -36,7 +42,7 @@ using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay { - public class DrawableRoomPlaylistItem : OsuRearrangeableListItem + public class DrawableRoomPlaylistItem : OsuRearrangeableListItem, IHasContextMenu { public const float HEIGHT = 50; @@ -91,6 +97,9 @@ namespace osu.Game.Screens.OnlinePlay [Resolved] private RulesetStore rulesets { get; set; } + [Resolved] + private BeatmapManager beatmaps { get; set; } + [Resolved] private OsuColour colours { get; set; } @@ -100,6 +109,15 @@ namespace osu.Game.Screens.OnlinePlay [Resolved] private BeatmapLookupCache beatmapLookupCache { get; set; } + [Resolved(CanBeNull = true)] + private BeatmapSetOverlay beatmapOverlay { get; set; } + + [Resolved(CanBeNull = true)] + private CollectionManager collectionManager { get; set; } + + [Resolved(CanBeNull = true)] + private ManageCollectionsDialog manageCollectionsDialog { get; set; } + protected override bool ShouldBeConsideredForInput(Drawable child) => AllowReordering || AllowDeletion || !AllowSelection || SelectedItem.Value == Model; public DrawableRoomPlaylistItem(PlaylistItem item) @@ -264,7 +282,7 @@ namespace osu.Game.Screens.OnlinePlay } if (beatmap != null) - difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) }; + difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset) { Size = new Vector2(icon_height) }; else difficultyIconContainer.Clear(); @@ -431,7 +449,7 @@ namespace osu.Game.Screens.OnlinePlay } } }, - } + }, }; } @@ -468,6 +486,31 @@ namespace osu.Game.Screens.OnlinePlay return true; } + public MenuItem[] ContextMenuItems + { + get + { + List items = new List(); + + if (beatmapOverlay != null) + items.Add(new OsuMenuItem("Details...", MenuItemType.Standard, () => beatmapOverlay.FetchAndShowBeatmap(Item.Beatmap.OnlineID))); + + if (collectionManager != null && beatmap != null) + { + if (beatmaps.QueryBeatmap(b => b.OnlineID == beatmap.OnlineID) is BeatmapInfo local && !local.BeatmapSet.AsNonNull().DeletePending) + { + var collectionItems = collectionManager.Collections.Select(c => new CollectionToggleMenuItem(c, beatmap)).Cast().ToList(); + if (manageCollectionsDialog != null) + collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show)); + + items.Add(new OsuMenuItem("Collections") { Items = collectionItems }); + } + } + + return items.ToArray(); + } + } + public class PlaylistEditButton : GrayButton { public PlaylistEditButton() diff --git a/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs b/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs index 834e82fcfd..9e589b362b 100644 --- a/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs +++ b/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs index 7c9184cc0f..0f02692eda 100644 --- a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Overlays; using System.Collections.Generic; @@ -9,7 +11,6 @@ using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; using osu.Game.Rulesets.Mods; -using osuTK.Input; namespace osu.Game.Screens.OnlinePlay { @@ -31,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay IsValidMod = _ => true; } - protected override ModColumn CreateModColumn(ModType modType, Key[] toggleKeys = null) => new ModColumn(modType, true, toggleKeys); + protected override ModColumn CreateModColumn(ModType modType) => new ModColumn(modType, true); protected override IEnumerable CreateFooterButtons() => base.CreateFooterButtons().Prepend( new SelectAllModsButton(this) diff --git a/osu.Game/Screens/OnlinePlay/Header.cs b/osu.Game/Screens/OnlinePlay/Header.cs index 2d4b5cc527..a9e9f046e2 100644 --- a/osu.Game/Screens/OnlinePlay/Header.cs +++ b/osu.Game/Screens/OnlinePlay/Header.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Humanizer; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -36,8 +38,8 @@ namespace osu.Game.Screens.OnlinePlay }; // unnecessary to unbind these as this header has the same lifetime as the screen stack we are attaching to. - stack.ScreenPushed += (_, __) => updateSubScreenTitle(); - stack.ScreenExited += (_, __) => updateSubScreenTitle(); + stack.ScreenPushed += (_, _) => updateSubScreenTitle(); + stack.ScreenExited += (_, _) => updateSubScreenTitle(); } private void updateSubScreenTitle() => title.Screen = stack.CurrentScreen as IOnlinePlaySubScreen; diff --git a/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs index a4762292a9..f32ead5a11 100644 --- a/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.OnlinePlay { public interface IOnlinePlaySubScreen : IOsuScreen diff --git a/osu.Game/Screens/OnlinePlay/IRoomManager.cs b/osu.Game/Screens/OnlinePlay/IRoomManager.cs index 6e1ffbda74..ed4fb7b15e 100644 --- a/osu.Game/Screens/OnlinePlay/IRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/IRoomManager.cs @@ -6,8 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Online.Rooms; -#nullable enable - namespace osu.Game.Screens.OnlinePlay { [Cached(typeof(IRoomManager))] diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 772232f6b4..7e39a52c0a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Threading; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs index 10bd534b89..995a0d3397 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs index 3207d373db..d951b42854 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs index 488af5d4de..3a687ad351 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/FilterCriteria.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets; namespace osu.Game.Screens.OnlinePlay.Lounge.Components @@ -11,5 +13,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public RoomStatusFilter Status; public string Category; public RulesetInfo Ruleset; + public RoomPermissionsFilter Permissions; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs index d104ede8f7..b2e527766a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index 109851a16b..b17873b1c8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index a6bbcd548d..474463d5f1 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using Humanizer; using osu.Framework.Allocation; @@ -42,7 +44,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components base.LoadComplete(); PlaylistItemStats.BindValueChanged(_ => updateCount()); - Playlist.BindCollectionChanged((_, __) => updateCount(), true); + Playlist.BindCollectionChanged((_, _) => updateCount(), true); } private void updateCount() diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs index 7501f0237b..85177ee32c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs index 42fe0bfecd..fa531a0d14 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RankRangePill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomPermissionsFilter.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomPermissionsFilter.cs new file mode 100644 index 0000000000..faef2a9d57 --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomPermissionsFilter.cs @@ -0,0 +1,12 @@ +// 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.OnlinePlay.Lounge.Components +{ + public enum RoomPermissionsFilter + { + All, + Public, + Private + } +} diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index 539af2ebaf..0f9bfb22e8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs index 0c8dc8832b..463b883f11 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Screens.OnlinePlay.Lounge.Components diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index 1d43f2dc65..f37ec9d9d4 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 0fd9290880..6142fc78a8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; @@ -85,9 +87,29 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components matchingFilter &= r.FilterTerms.Any(term => term.ToString().Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase)); } + matchingFilter &= matchPermissions(r, criteria.Permissions); + r.MatchingFilter = matchingFilter; } }); + + static bool matchPermissions(DrawableLoungeRoom room, RoomPermissionsFilter accessType) + { + switch (accessType) + { + case RoomPermissionsFilter.All: + return true; + + case RoomPermissionsFilter.Public: + return !room.Room.HasPassword.Value; + + case RoomPermissionsFilter.Private: + return room.Room.HasPassword.Value; + + default: + throw new ArgumentOutOfRangeException(nameof(accessType), accessType, $"Unsupported {nameof(RoomPermissionsFilter)} in filter"); + } + } } private void roomsChanged(object sender, NotifyCollectionChangedEventArgs args) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 0015cf8bf9..8a2aeb9e5e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -248,7 +250,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge base.LoadComplete(); ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(passwordTextBox)); - passwordTextBox.OnCommit += (_, __) => performJoin(); + passwordTextBox.OnCommit += (_, _) => performJoin(); } private void performJoin() diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs index 52a902f5da..58ccb24f7a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Online.Rooms; @@ -19,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge public LoungeBackgroundScreen() { SelectedRoom.BindValueChanged(onSelectedRoomChanged); - playlist.BindCollectionChanged((_, __) => PlaylistItem = playlist.GetCurrentItem()); + playlist.BindCollectionChanged((_, _) => PlaylistItem = playlist.GetCurrentItem()); } private void onSelectedRoomChanged(ValueChangedEvent room) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs index f2429c1944..09bc496da5 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Collections.Generic; @@ -37,6 +39,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { public override string Title => "Lounge"; + protected override bool PlayExitSound => false; + protected override BackgroundScreen CreateBackground() => new LoungeBackgroundScreen { SelectedRoom = { BindTarget = SelectedRoom } @@ -300,7 +304,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge joiningRoomOperation = ongoingOperationTracker?.BeginOperation(); - RoomManager?.JoinRoom(room, password, r => + RoomManager?.JoinRoom(room, password, _ => { Open(room); joiningRoomOperation?.Dispose(); diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs index 81e1cb2406..3d0c181d9d 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Input; using osu.Framework.Input.Bindings; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs index 0396562959..880bba895a 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Online.Chat; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs index b92c197f5a..64644be965 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs index 799983342b..5bd8f9e066 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchLeaderboardScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs index 216734e55e..91477879c6 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchTypePicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs index 28e8961a9a..5c751f238f 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/PurpleTriangleButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs index 677a5be0d9..408742d8e1 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomAvailabilityPicker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index c15b5b443a..71447b15e2 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -133,7 +135,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), - Text = title.ToUpper(), + Text = title.ToUpperInvariant(), }, content = new Container { diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index 1828a072f8..7c444b9bbd 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs index 2e5f25370f..74c37b865c 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index a612b6a0e6..f5af110372 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -84,7 +86,7 @@ namespace osu.Game.Screens.OnlinePlay.Match public readonly Room Room; private readonly bool allowEdit; - private ModSelectOverlay userModsSelectOverlay; + internal ModSelectOverlay UserModsSelectOverlay { get; private set; } [CanBeNull] private IDisposable userModsSelectOverlayRegistration; @@ -234,7 +236,7 @@ namespace osu.Game.Screens.OnlinePlay.Match } }; - LoadComponent(userModsSelectOverlay = new UserModSelectOverlay(OverlayColourScheme.Plum) + LoadComponent(UserModsSelectOverlay = new UserModSelectOverlay(OverlayColourScheme.Plum) { SelectedMods = { BindTarget = UserMods }, IsValidMod = _ => false @@ -267,7 +269,7 @@ namespace osu.Game.Screens.OnlinePlay.Match beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem); beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap()); - userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(userModsSelectOverlay); + userModsSelectOverlayRegistration = overlayManager?.RegisterBlockingOverlay(UserModsSelectOverlay); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -287,9 +289,9 @@ namespace osu.Game.Screens.OnlinePlay.Match return base.OnBackButton(); } - if (userModsSelectOverlay.State.Value == Visibility.Visible) + if (UserModsSelectOverlay.State.Value == Visibility.Visible) { - userModsSelectOverlay.Hide(); + UserModsSelectOverlay.Hide(); return true; } @@ -302,7 +304,7 @@ namespace osu.Game.Screens.OnlinePlay.Match return base.OnBackButton(); } - protected void ShowUserModSelect() => userModsSelectOverlay.Show(); + protected void ShowUserModSelect() => UserModsSelectOverlay.Show(); public override void OnEntering(ScreenTransitionEvent e) { @@ -312,6 +314,9 @@ namespace osu.Game.Screens.OnlinePlay.Match public override void OnSuspending(ScreenTransitionEvent e) { + // Should be a noop in most cases, but let's ensure beyond doubt that the beatmap is in a correct state. + updateWorkingBeatmap(); + onLeaving(); base.OnSuspending(e); } @@ -383,13 +388,13 @@ namespace osu.Game.Screens.OnlinePlay.Match if (!selected.AllowedMods.Any()) { UserModsSection?.Hide(); - userModsSelectOverlay.Hide(); - userModsSelectOverlay.IsValidMod = _ => false; + UserModsSelectOverlay.Hide(); + UserModsSelectOverlay.IsValidMod = _ => false; } else { UserModsSection?.Show(); - userModsSelectOverlay.IsValidMod = m => allowedMods.Any(a => a.GetType() == m.GetType()); + UserModsSelectOverlay.IsValidMod = m => allowedMods.Any(a => a.GetType() == m.GetType()); } } @@ -428,7 +433,7 @@ namespace osu.Game.Screens.OnlinePlay.Match private void onLeaving() { - userModsSelectOverlay.Hide(); + UserModsSelectOverlay.Hide(); endHandlingTrack(); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs index e80923ed47..fd535f979d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/CreateMultiplayerMatchButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs index d08a63e21f..270f15a98d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayChatDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs index 20a88545c5..c7fb6a82d5 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Screens.Play.HUD; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs index d048676872..501c76f65b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MatchStartControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs index 1a51aebb76..14bf1a8375 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Humanizer; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs index a07c95bca8..c28bd4892a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchFooter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index a103d71120..3aa879dde0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.ComponentModel; using System.Diagnostics; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs index 62310bcaac..c5d6da1ebc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; @@ -59,7 +61,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match switch (room?.Countdown) { - case MatchStartCountdown _: + case MatchStartCountdown: newCountdown = room.Countdown; break; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs index d939fbf400..b55a7d0731 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerSpectateButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -39,7 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { var clickOperation = ongoingOperationTracker.BeginOperation(); - Client.ToggleSpectate().ContinueWith(t => endOperation()); + Client.ToggleSpectate().ContinueWith(_ => endOperation()); void endOperation() => clickOperation?.Dispose(); } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs index 32d355d149..3def73accb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs index 41f548a630..bc96bd61d7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs index cc3dca6a34..1672f98637 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist { /// diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs index 583a05839f..f7abc91227 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; @@ -32,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist protected override void LoadComplete() { base.LoadComplete(); - QueueItems.BindCollectionChanged((_, __) => Text.Text = QueueItems.Count > 0 ? $"Queue ({QueueItems.Count})" : "Queue", true); + QueueItems.BindCollectionChanged((_, _) => Text.Text = QueueItems.Count > 0 ? $"Queue ({QueueItems.Count})" : "Queue", true); } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs index d72ce5e960..39740e650f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerQueueList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -39,7 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist protected override void LoadComplete() { base.LoadComplete(); - roomPlaylist.BindCollectionChanged((_, __) => InvalidateLayout()); + roomPlaylist.BindCollectionChanged((_, _) => InvalidateLayout()); } public override IEnumerable FlowingChildren => base.FlowingChildren.OfType>().OrderBy(item => item.Model.PlaylistOrder); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 53d081a108..03a2f00c0d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Logging; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs index a05f248d3a..37b977cff7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerLoungeSubScreen.cs @@ -1,11 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Framework.Graphics; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; @@ -25,6 +31,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } + private Dropdown roomAccessTypeDropdown; + public override void OnResuming(ScreenTransitionEvent e) { base.OnResuming(e); @@ -38,10 +46,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } } + protected override IEnumerable CreateFilterControls() + { + roomAccessTypeDropdown = new SlimEnumDropdown + { + RelativeSizeAxes = Axes.None, + Width = 160, + }; + + roomAccessTypeDropdown.Current.BindValueChanged(_ => UpdateFilter()); + + return base.CreateFilterControls().Prepend(roomAccessTypeDropdown); + } + protected override FilterCriteria CreateFilterCriteria() { var criteria = base.CreateFilterCriteria(); criteria.Category = @"realtime"; + criteria.Permissions = roomAccessTypeDropdown.Current.Value; return criteria; } @@ -79,7 +101,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private void load() { isConnected.BindTo(client.IsConnected); - isConnected.BindValueChanged(c => Scheduler.AddOnce(poll), true); + isConnected.BindValueChanged(_ => Scheduler.AddOnce(poll), true); } private void poll() diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs index 929c3ee321..dbd679104e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs @@ -1,9 +1,12 @@ // Copyright (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.Bindables; +using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; @@ -18,11 +21,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public class MultiplayerMatchSongSelect : OnlinePlaySongSelect { [Resolved] - private MultiplayerClient client { get; set; } + private MultiplayerClient client { get; set; } = null!; + [Resolved] + private OngoingOperationTracker operationTracker { get; set; } = null!; + + private readonly IBindable operationInProgress = new Bindable(); private readonly long? itemToEdit; - private LoadingLayer loadingLayer; + private LoadingLayer loadingLayer = null!; + private IDisposable? selectionOperation; /// /// Construct a new instance of multiplayer song select. @@ -31,7 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer /// The item to be edited. May be null, in which case a new item will be added to the playlist. /// An optional initial beatmap selection to perform. /// An optional initial ruleset selection to perform. - public MultiplayerMatchSongSelect(Room room, long? itemToEdit = null, WorkingBeatmap beatmap = null, RulesetInfo ruleset = null) + public MultiplayerMatchSongSelect(Room room, long? itemToEdit = null, WorkingBeatmap? beatmap = null, RulesetInfo? ruleset = null) : base(room) { this.itemToEdit = itemToEdit; @@ -52,13 +60,35 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer AddInternal(loadingLayer = new LoadingLayer(true)); } - protected override void SelectItem(PlaylistItem item) + protected override void LoadComplete() { + base.LoadComplete(); + + operationInProgress.BindTo(operationTracker.InProgress); + operationInProgress.BindValueChanged(_ => updateLoadingLayer(), true); + } + + private void updateLoadingLayer() + { + if (operationInProgress.Value) + loadingLayer.Show(); + else + loadingLayer.Hide(); + } + + protected override bool SelectItem(PlaylistItem item) + { + if (operationInProgress.Value) + { + Logger.Log($"{nameof(SelectedItem)} aborted due to {nameof(operationInProgress)}"); + return false; + } + // If the client is already in a room, update via the client. // Otherwise, update the playlist directly in preparation for it to be submitted to the API on match creation. if (client.Room != null) { - loadingLayer.Show(); + selectionOperation = operationTracker.BeginOperation(); var multiplayerItem = new MultiplayerPlaylistItem { @@ -72,18 +102,25 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Task task = itemToEdit != null ? client.EditPlaylistItem(multiplayerItem) : client.AddPlaylistItem(multiplayerItem); - task.FireAndForget(onSuccess: () => Schedule(() => + task.FireAndForget(onSuccess: () => { - loadingLayer.Hide(); + selectionOperation.Dispose(); - // If an error or server side trigger occurred this screen may have already exited by external means. - if (this.IsCurrentScreen()) - this.Exit(); - }), onError: _ => Schedule(() => + Schedule(() => + { + // If an error or server side trigger occurred this screen may have already exited by external means. + if (this.IsCurrentScreen()) + this.Exit(); + }); + }, onError: _ => { - loadingLayer.Hide(); - Carousel.AllowSelection = true; - })); + selectionOperation.Dispose(); + + Schedule(() => + { + Carousel.AllowSelection = true; + }); + }); } else { @@ -91,6 +128,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer Playlist.Add(item); this.Exit(); } + + return true; } protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 769873f74c..ceadfa1527 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -13,6 +15,7 @@ using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Graphics.Cursor; using osu.Game.Online; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; @@ -41,9 +44,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public override string ShortTitle => "room"; + protected override bool PlayExitSound => !exitConfirmed; + [Resolved] private MultiplayerClient client { get; set; } + [Resolved] + private BeatmapManager beatmapManager { get; set; } + private readonly IBindable isConnected = new Bindable(); private AddItemButton addItemButton; @@ -65,146 +73,146 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer client.LoadRequested += onLoadRequested; client.RoomUpdated += onRoomUpdated; - isConnected.BindTo(client.IsConnected); - isConnected.BindValueChanged(connected => - { - if (!connected.NewValue) - handleRoomLost(); - }, true); + if (!client.IsConnected.Value) + handleRoomLost(); } protected override Drawable CreateMainContent() => new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = 5, Vertical = 10 }, - Child = new GridContainer + Child = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Child = new GridContainer { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 10), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 10), - new Dimension(), - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - // Participants column - new GridContainer + new Dimension(), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension(), + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + // Participants column + new GridContainer { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] { new ParticipantsListHeader() }, - new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - new ParticipantsList - { - RelativeSizeAxes = Axes.Both - }, - } - } - }, - // Spacer - null, - // Beatmap column - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { new OverlinedHeader("Beatmap") }, - new Drawable[] - { - addItemButton = new AddItemButton - { - RelativeSizeAxes = Axes.X, - Height = 40, - Text = "Add item", - Action = () => OpenSongSelection() - }, + new Dimension(GridSizeMode.AutoSize) }, - null, - new Drawable[] + Content = new[] { - new MultiplayerPlaylist + new Drawable[] { new ParticipantsListHeader() }, + new Drawable[] { - RelativeSizeAxes = Axes.Both, - RequestEdit = item => OpenSongSelection(item.ID) - } - }, - new[] - { - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 10 }, - Alpha = 0, - Children = new Drawable[] + new ParticipantsList { - new OverlinedHeader("Extra mods"), - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new UserModSelectButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } - }, + RelativeSizeAxes = Axes.Both + }, + } + } + }, + // Spacer + null, + // Beatmap column + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new OverlinedHeader("Beatmap") }, + new Drawable[] + { + addItemButton = new AddItemButton + { + RelativeSizeAxes = Axes.X, + Height = 40, + Text = "Add item", + Action = () => OpenSongSelection() + }, + }, + null, + new Drawable[] + { + new MultiplayerPlaylist + { + RelativeSizeAxes = Axes.Both, + RequestEdit = OpenSongSelection } }, + new[] + { + UserModsSection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Top = 10 }, + Alpha = 0, + Children = new Drawable[] + { + new OverlinedHeader("Extra mods"), + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new UserModSelectButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, + } + }, + } + }, + }, }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Absolute, 5), + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + } }, - RowDimensions = new[] + // Spacer + null, + // Main right column + new GridContainer { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, 5), - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - } - }, - // Spacer - null, - // Main right column - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { new OverlinedHeader("Chat") }, - new Drawable[] { new MatchChatDisplay(Room) { RelativeSizeAxes = Axes.Both } } + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new OverlinedHeader("Chat") }, + new Drawable[] { new MatchChatDisplay(Room) { RelativeSizeAxes = Axes.Both } } + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } - }, + } } } } @@ -214,12 +222,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer /// Opens the song selection screen to add or edit an item. /// /// An optional playlist item to edit. If null, a new item will be added instead. - internal void OpenSongSelection(long? itemToEdit = null) + internal void OpenSongSelection(PlaylistItem itemToEdit = null) { if (!this.IsCurrentScreen()) return; - this.Push(new MultiplayerMatchSongSelect(Room, itemToEdit)); + int id = itemToEdit?.Beatmap.OnlineID ?? Room.Playlist.Last().Beatmap.OnlineID; + var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineID == id); + + var workingBeatmap = localBeatmap == null ? null : beatmapManager.GetWorkingBeatmap(localBeatmap); + + this.Push(new MultiplayerMatchSongSelect(Room, itemToEdit?.ID, workingBeatmap)); } protected override Drawable CreateFooter() => new MultiplayerMatchFooter(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs index 43b128b971..a82da7b185 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; @@ -123,7 +125,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer client.GameplayStarted += onGameplayStarted; client.ResultsReady += onResultsReady; - ScoreProcessor.HasCompleted.BindValueChanged(completed => + ScoreProcessor.HasCompleted.BindValueChanged(_ => { // wait for server to tell us that results are ready (see SubmitScore implementation) loadingDisplay.Show(); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs index e9bf5339a9..f79af664d8 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayerLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading.Tasks; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index 140b3c45d8..d98b837883 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs index f6f815a3cb..1f80c47d13 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomComposite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 2d94b2328d..7e83d72c77 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs index 49b5b7fed9..1aafcea20c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs index 3f0f3e043c..6fbed03e44 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerTeamResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs index e091559046..3ef2f033b0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantPanel.cs @@ -1,6 +1,7 @@ // Copyright (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; @@ -20,6 +21,7 @@ using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; using osu.Game.Users; using osu.Game.Users.Drawables; @@ -33,18 +35,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants public readonly MultiplayerRoomUser User; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; [Resolved] - private IRulesetStore rulesets { get; set; } + private IRulesetStore rulesets { get; set; } = null!; - private SpriteIcon crown; + private SpriteIcon crown = null!; - private OsuSpriteText userRankText; - private ModDisplay userModsDisplay; - private StateDisplay userStateDisplay; + private OsuSpriteText userRankText = null!; + private ModDisplay userModsDisplay = null!; + private StateDisplay userStateDisplay = null!; - private IconButton kickButton; + private IconButton kickButton = null!; public ParticipantPanel(MultiplayerRoomUser user) { @@ -125,15 +127,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Size = new Vector2(30, 20), - Country = user?.Country + Size = new Vector2(28, 20), + CountryCode = user?.CountryCode ?? default }, new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), - Text = user?.Username + Text = user?.Username ?? string.Empty }, userRankText = new OsuSpriteText { @@ -186,7 +188,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants const double fade_time = 50; var currentItem = Playlist.GetCurrentItem(); - var ruleset = currentItem != null ? rulesets.GetRuleset(currentItem.RulesetID)?.CreateInstance() : null; + Ruleset? ruleset = currentItem != null ? rulesets.GetRuleset(currentItem.RulesetID)?.CreateInstance() : null; int? currentModeRank = ruleset != null ? User.User?.RulesetsStatistics?.GetValueOrDefault(ruleset.ShortName)?.GlobalRank : null; userRankText.Text = currentModeRank != null ? $"#{currentModeRank.Value:N0}" : string.Empty; @@ -203,10 +205,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants // If the mods are updated at the end of the frame, the flow container will skip a reflow cycle: https://github.com/ppy/osu-framework/issues/4187 // This looks particularly jarring here, so re-schedule the update to that start of our frame as a fix. - Schedule(() => userModsDisplay.Current.Value = User.Mods.Select(m => m.ToMod(ruleset)).ToList()); + Schedule(() => + { + userModsDisplay.Current.Value = ruleset != null ? User.Mods.Select(m => m.ToMod(ruleset)).ToList() : Array.Empty(); + }); } - public MenuItem[] ContextMenuItems + public MenuItem[]? ContextMenuItems { get { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs index 14b930f115..7c93c6084e 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs @@ -1,13 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Cursor; using osuTK; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants @@ -22,20 +23,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants [BackgroundDependencyLoader] private void load() { - InternalChild = new OsuContextMenuContainer + InternalChild = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, - Child = new OsuScrollContainer + ScrollbarVisible = false, + Child = panels = new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - ScrollbarVisible = false, - Child = panels = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 2) - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 2) } }; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs index ef84c4b4fa..b0acda03df 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Online.Multiplayer; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs index 658fc43e8d..9c05c19d1b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/StateDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs index aca2c6073a..5500d96eea 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/TeamDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs index 48d0b063ff..34388bf9b1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSpectatorPlayerClock.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Bindables; using osu.Framework.Timing; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs index b0fdeddd56..663025923c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/CatchUpSyncManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISpectatorPlayerClock.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISpectatorPlayerClock.cs index b2ecb105c2..194a3bdcc2 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISpectatorPlayerClock.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISpectatorPlayerClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Timing; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs index 3c644ccb78..577100d4ba 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/ISyncManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Timing; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs index 8982d1669d..92dbde9f08 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { public enum MasterClockState diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs index 4e9ab07e4c..c7af87a91d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Timing; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs index 29afaf00d8..a0558f97a9 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 14bd8fa6dc..36a6487289 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index d9c19cdfdd..8270bb3b6f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; @@ -131,7 +133,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(users) { Expanded = { Value = true }, - }, l => + }, _ => { foreach (var instance in instances) leaderboard.AddClock(instance.UserId, instance.GameplayClock); diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs index 4979bd906b..302d04b531 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using JetBrains.Annotations; @@ -51,9 +53,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate [CanBeNull] public Score Score { get; private set; } - [Resolved] - private BeatmapManager beatmapManager { get; set; } - private readonly BindableDouble volumeAdjustment = new BindableDouble(); private readonly Container gameplayContent; private readonly LoadingLayer loadingLayer; @@ -82,6 +81,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate GameplayClock.Source = masterClock; } + [Resolved] + private IBindable beatmap { get; set; } + public void LoadScore([NotNull] Score score) { if (Score != null) @@ -89,7 +91,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate Score = score; - gameplayContent.Child = new PlayerIsolationContainer(beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.BeatmapInfo), Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods) + gameplayContent.Child = new PlayerIsolationContainer(beatmap.Value, Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods) { RelativeSizeAxes = Axes.Both, Child = stack = new OsuScreenStack diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs index 6638d47dca..82d4cf5caf 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs index 2df05cb5ed..ee213f7be1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Cell.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs index 6b363c6040..f7b8d48d0a 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate diff --git a/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs b/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs index aabeafe460..c87cf32c73 100644 --- a/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs +++ b/osu.Game/Screens/OnlinePlay/OngoingOperationTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 88354c8646..0bf5f2604c 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -92,7 +94,7 @@ namespace osu.Game.Screens.OnlinePlay base.LoadComplete(); subScreenSelectedItem?.BindValueChanged(_ => UpdateSelectedItem()); - Playlist.BindCollectionChanged((_, __) => UpdateSelectedItem(), true); + Playlist.BindCollectionChanged((_, _) => UpdateSelectedItem(), true); } protected void UpdateSelectedItem() diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index ff4225e155..61ea7d68ee 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index fb18a33d66..f26480909e 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -116,8 +118,6 @@ namespace osu.Game.Screens.OnlinePlay protected sealed override bool OnStart() { - itemSelected = true; - var item = new PlaylistItem(Beatmap.Value.BeatmapInfo) { RulesetID = Ruleset.Value.OnlineID, @@ -125,15 +125,21 @@ namespace osu.Game.Screens.OnlinePlay AllowedMods = FreeMods.Value.Select(m => new APIMod(m)).ToArray() }; - SelectItem(item); - return true; + if (SelectItem(item)) + { + itemSelected = true; + return true; + } + + return false; } /// /// Invoked when the user has requested a selection of a beatmap. /// /// The resultant . This item has not yet been added to the 's. - protected abstract void SelectItem(PlaylistItem item); + /// true if a selection occurred. + protected abstract bool SelectItem(PlaylistItem item); public override bool OnBackButton() { diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs index 07e0f60011..5c0a158c97 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs index 7f2a0980c1..ae6988f0d6 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Screens; namespace osu.Game.Screens.OnlinePlay diff --git a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs index a9826a72eb..8cdae954ce 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Screens.OnlinePlay.Match.Components; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index 1edeef77df..b84079b955 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Screens.OnlinePlay.Lounge; namespace osu.Game.Screens.OnlinePlay.Playlists diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs index b36e162e3d..0827e2031d 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsLoungeSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.ComponentModel; using System.Linq; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index 5cba8676c5..282c1db585 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs index 24f112ef0c..b8ab514721 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsReadyButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index 1e6722d51e..53b38962ac 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs index 3eb1cde0a4..b1b400713f 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomFooter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs index 6674a37c3c..9c6a2a5e0b 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Specialized; using System.Linq; @@ -138,9 +140,14 @@ namespace osu.Game.Screens.OnlinePlay.Playlists }, new Section("Duration") { - Child = DurationField = new DurationDropdown + Child = new Container { RelativeSizeAxes = Axes.X, + Height = 40, + Child = DurationField = new DurationDropdown + { + RelativeSizeAxes = Axes.X + } } }, new Section("Allowed attempts (across all playlist items)") diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs index 2fe215eef2..80f38d0cd8 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 338a9c856f..228ecd4bf3 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using System.Linq; using JetBrains.Annotations; @@ -10,6 +12,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Graphics.Cursor; using osu.Game.Input; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; @@ -66,158 +69,162 @@ namespace osu.Game.Screens.OnlinePlay.Playlists } }, true); - Room.MaxAttempts.BindValueChanged(attempts => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true); + Room.MaxAttempts.BindValueChanged(_ => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true); } protected override Drawable CreateMainContent() => new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = 5, Vertical = 10 }, - Child = new GridContainer + Child = new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Child = new GridContainer { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 10), - new Dimension(), - new Dimension(GridSizeMode.Absolute, 10), - new Dimension(), - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] { - // Playlist items column - new Container + new Dimension(), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension(), + new Dimension(GridSizeMode.Absolute, 10), + new Dimension(), + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - Child = new GridContainer + // Playlist items column + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Right = 5 }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new OverlinedPlaylistHeader(), }, + new Drawable[] + { + new DrawableRoomPlaylist + { + RelativeSizeAxes = Axes.Both, + Items = { BindTarget = Room.Playlist }, + SelectedItem = { BindTarget = SelectedItem }, + AllowSelection = true, + AllowShowingResults = true, + RequestResults = item => + { + Debug.Assert(RoomId.Value != null); + ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); + } + } + }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } + } + }, + // Spacer + null, + // Middle column (mods and leaderboard) + new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] { - new Drawable[] { new OverlinedPlaylistHeader(), }, + new[] + { + UserModsSection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + Margin = new MarginPadding { Bottom = 10 }, + Children = new Drawable[] + { + new OverlinedHeader("Extra mods"), + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new UserModSelectButton + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Width = 90, + Text = "Select", + Action = ShowUserModSelect, + }, + new ModDisplay + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Current = UserMods, + Scale = new Vector2(0.8f), + }, + } + } + } + }, + }, new Drawable[] { - new DrawableRoomPlaylist + progressSection = new FillFlowContainer { - RelativeSizeAxes = Axes.Both, - Items = { BindTarget = Room.Playlist }, - SelectedItem = { BindTarget = SelectedItem }, - AllowSelection = true, - AllowShowingResults = true, - RequestResults = item => + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + Margin = new MarginPadding { Bottom = 10 }, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - Debug.Assert(RoomId.Value != null); - ParentScreen?.Push(new PlaylistsResultsScreen(null, RoomId.Value.Value, item, false)); + new OverlinedHeader("Progress"), + new RoomLocalUserInfo(), } - } + }, }, + new Drawable[] + { + new OverlinedHeader("Leaderboard") + }, + new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + } + }, + // Spacer + null, + // Main right column + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { new OverlinedHeader("Chat") }, + new Drawable[] { new MatchChatDisplay(Room) { RelativeSizeAxes = Axes.Both } } }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), new Dimension(), } - } - }, - // Spacer - null, - // Middle column (mods and leaderboard) - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new[] - { - UserModsSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Alpha = 0, - Margin = new MarginPadding { Bottom = 10 }, - Children = new Drawable[] - { - new OverlinedHeader("Extra mods"), - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - new UserModSelectButton - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = 90, - Text = "Select", - Action = ShowUserModSelect, - }, - new ModDisplay - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Current = UserMods, - Scale = new Vector2(0.8f), - }, - } - } - } - }, - }, - new Drawable[] - { - progressSection = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Alpha = 0, - Margin = new MarginPadding { Bottom = 10 }, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new OverlinedHeader("Progress"), - new RoomLocalUserInfo(), - } - }, - }, - new Drawable[] - { - new OverlinedHeader("Leaderboard") - }, - new Drawable[] { leaderboard = new MatchLeaderboard { RelativeSizeAxes = Axes.Both }, }, }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } - }, - // Spacer - null, - // Main right column - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] { new OverlinedHeader("Chat") }, - new Drawable[] { new MatchChatDisplay(Room) { RelativeSizeAxes = Axes.Both } } - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - } }, }, - }, + } } }; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs index 86591c1d6d..73765fc661 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Screens; using osu.Game.Online.API; @@ -22,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists CreateNewItem = createNewItem }; - protected override void SelectItem(PlaylistItem item) + protected override bool SelectItem(PlaylistItem item) { switch (Playlist.Count) { @@ -37,6 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists } this.Exit(); + return true; } private void createNewItem() diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 77db1285bd..0678a90f71 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using JetBrains.Annotations; @@ -77,7 +79,7 @@ namespace osu.Game.Screens private Sample sampleExit; - protected virtual bool PlayResumeSound => true; + protected virtual bool PlayExitSound => true; public virtual float BackgroundParallaxAmount => 1; @@ -173,9 +175,6 @@ namespace osu.Game.Screens public override void OnResuming(ScreenTransitionEvent e) { - if (PlayResumeSound) - sampleExit?.Play(); - applyArrivingDefaults(true); // it's feasible to resume to a screen if the target screen never loaded successfully. @@ -215,6 +214,9 @@ namespace osu.Game.Screens public override bool OnExiting(ScreenExitEvent e) { + if (ValidForResume && PlayExitSound) + sampleExit?.Play(); + if (ValidForResume && logo != null) onExitingLogo(); diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index 8d54829d49..66176685fd 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs index 18b16ba865..49f1255ec7 100644 --- a/osu.Game/Screens/OsuScreenStack.cs +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index e8021d4065..0e56cafaaa 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Allocation; @@ -195,21 +197,19 @@ namespace osu.Game.Screens.Play starRatingDisplay.Show(); } else - { starRatingDisplay.Hide(); - starDifficulty.ValueChanged += d => - { - Debug.Assert(d.NewValue != null); + starDifficulty.ValueChanged += d => + { + Debug.Assert(d.NewValue != null); - starRatingDisplay.Current.Value = d.NewValue.Value; + starRatingDisplay.Current.Value = d.NewValue.Value; - versionFlow.AutoSizeDuration = 300; - versionFlow.AutoSizeEasing = Easing.OutQuint; + versionFlow.AutoSizeDuration = 300; + versionFlow.AutoSizeEasing = Easing.OutQuint; - starRatingDisplay.FadeIn(300, Easing.InQuint); - }; - } + starRatingDisplay.FadeIn(300, Easing.InQuint); + }; } private class MetadataLineLabel : OsuSpriteText diff --git a/osu.Game/Screens/Play/Break/BlurredIcon.cs b/osu.Game/Screens/Play/Break/BlurredIcon.cs index 1e974ec916..97eafa01fa 100644 --- a/osu.Game/Screens/Play/Break/BlurredIcon.cs +++ b/osu.Game/Screens/Play/Break/BlurredIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/Break/BreakArrows.cs b/osu.Game/Screens/Play/Break/BreakArrows.cs index 4b96fa666a..f2feda4d76 100644 --- a/osu.Game/Screens/Play/Break/BreakArrows.cs +++ b/osu.Game/Screens/Play/Break/BreakArrows.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index ead41a826a..5aed8b7df1 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 4cae90e50f..690d7c7e63 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/Break/GlowIcon.cs b/osu.Game/Screens/Play/Break/GlowIcon.cs index 2810389619..9222e8f890 100644 --- a/osu.Game/Screens/Play/Break/GlowIcon.cs +++ b/osu.Game/Screens/Play/Break/GlowIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs index 2d7163b5fe..3eb58da469 100644 --- a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs +++ b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs index 2f5e43aebf..4b84f7c69e 100644 --- a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs +++ b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index 1665ee83ae..492c9c27ff 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/BreakTracker.cs b/osu.Game/Screens/Play/BreakTracker.cs index 8441b7657e..8679db01a0 100644 --- a/osu.Game/Screens/Play/BreakTracker.cs +++ b/osu.Game/Screens/Play/BreakTracker.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/ComboEffects.cs b/osu.Game/Screens/Play/ComboEffects.cs index 5041d07e5d..77681401bb 100644 --- a/osu.Game/Screens/Play/ComboEffects.cs +++ b/osu.Game/Screens/Play/ComboEffects.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs index 5a3ef1e9d3..ae43d3d70d 100644 --- a/osu.Game/Screens/Play/DimmableStoryboard.cs +++ b/osu.Game/Screens/Play/DimmableStoryboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/EpilepsyWarning.cs b/osu.Game/Screens/Play/EpilepsyWarning.cs index ccb2870d78..4f87853158 100644 --- a/osu.Game/Screens/Play/EpilepsyWarning.cs +++ b/osu.Game/Screens/Play/EpilepsyWarning.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 17a3e5eb71..c1223d7262 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Game.Rulesets.UI; @@ -196,7 +198,7 @@ namespace osu.Game.Screens.Play dropOffScreen(obj, failTime, rotation, originalScale, originalPosition); // need to reapply the fail drop after judgement state changes - obj.ApplyCustomUpdateState += (o, _) => dropOffScreen(obj, failTime, rotation, originalScale, originalPosition); + obj.ApplyCustomUpdateState += (_, _) => dropOffScreen(obj, failTime, rotation, originalScale, originalPosition); appliedObjects.Add(obj); } diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index b67f45c4f2..2af5102369 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -1,14 +1,27 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + +using System; +using System.Threading.Tasks; +using osu.Game.Scoring; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; namespace osu.Game.Screens.Play { public class FailOverlay : GameplayMenuOverlay { + public Func> SaveReplay; + public override string Header => "failed"; public override string Description => "you're dead, try again?"; @@ -17,6 +30,39 @@ namespace osu.Game.Screens.Play { AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); + // from #10339 maybe this is a better visual effect + Add(new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = TwoLayerButton.SIZE_EXTENDED.Y, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex("#333") + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Spacing = new Vector2(5), + Padding = new MarginPadding(10), + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new SaveFailedScoreButton(SaveReplay) + { + Width = 300 + }, + } + } + } + }); } } } diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index 54aa395f5f..e6248014c5 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 721abc66f8..9396b3311f 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -1,11 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; using osu.Framework.Timing; namespace osu.Game.Screens.Play @@ -99,6 +102,8 @@ namespace osu.Game.Screens.Play /// The destination time to seek to. public virtual void Seek(double time) { + Logger.Log($"{nameof(GameplayClockContainer)} seeking to {time}"); + AdjustableSource.Seek(time); // Manually process to make sure the gameplay clock is correctly updated after a seek. diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 9e3400b09d..c2652e9212 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -140,7 +142,7 @@ namespace osu.Game.Screens.Play }, }; - State.ValueChanged += s => InternalButtons.Deselect(); + State.ValueChanged += _ => InternalButtons.Deselect(); updateRetryCount(); } @@ -265,7 +267,7 @@ namespace osu.Game.Screens.Play { switch (e) { - case ScrollEvent _: + case ScrollEvent: if (ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) return globalAction.TriggerEvent(e); diff --git a/osu.Game/Screens/Play/GameplayState.cs b/osu.Game/Screens/Play/GameplayState.cs index 586cdcda51..9fb62106f3 100644 --- a/osu.Game/Screens/Play/GameplayState.cs +++ b/osu.Game/Screens/Play/GameplayState.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs index 06b53e8426..018720510c 100644 --- a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Skinning; diff --git a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs index 52f86d2bc3..1f14811169 100644 --- a/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultComboCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs index 4f93868a66..37e1d2fb84 100644 --- a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs index 6af89404e0..4450ad53d8 100644 --- a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Play/HUD/FailingLayer.cs b/osu.Game/Screens/Play/HUD/FailingLayer.cs index ceb81f6b8d..10c1d418ee 100644 --- a/osu.Game/Screens/Play/HUD/FailingLayer.cs +++ b/osu.Game/Screens/Play/HUD/FailingLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs index 7a63084812..afb6749436 100644 --- a/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayAccuracyCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs index 638b2c395f..f21ce5e36a 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 773ee4a036..0f007cd1cb 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs index e05eff5f3e..7a6292ccbf 100644 --- a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index 94f1b99b37..569b37aea5 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index dca50c07ad..747f4d4a8a 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 5012be7249..335d956e39 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -15,7 +17,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class ColourHitErrorMeter : HitErrorMeter { + internal const int MAX_DISPLAYED_JUDGEMENTS = 20; + private const int animation_duration = 200; + private const int drawable_judgement_size = 8; + private const int spacing = 2; private readonly JudgementFlow judgementsFlow; @@ -37,16 +43,12 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private class JudgementFlow : FillFlowContainer { - private const int max_available_judgements = 20; - private const int drawable_judgement_size = 8; - private const int spacing = 2; - public override IEnumerable FlowingChildren => base.FlowingChildren.Reverse(); public JudgementFlow() { AutoSizeAxes = Axes.X; - Height = max_available_judgements * (drawable_judgement_size + spacing) - spacing; + Height = MAX_DISPLAYED_JUDGEMENTS * (drawable_judgement_size + spacing) - spacing; Spacing = new Vector2(0, spacing); Direction = FillDirection.Vertical; LayoutDuration = animation_duration; @@ -57,7 +59,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { Add(new HitErrorCircle(colour, drawable_judgement_size)); - if (Children.Count > max_available_judgements) + if (Children.Count > MAX_DISPLAYED_JUDGEMENTS) Children.FirstOrDefault(c => !c.IsRemoved)?.Remove(); } } diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs index 1f08cb8aa7..26befd659c 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -31,6 +33,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private void load(DrawableRuleset drawableRuleset) { HitWindows = drawableRuleset?.FirstAvailableHitWindows ?? HitWindows.Empty; + + // This is to allow the visual state to be correct after HUD comes visible after being hidden. + AlwaysPresent = true; } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 2ba76d0896..39a8f1e783 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -216,7 +218,7 @@ namespace osu.Game.Screens.Play.HUD overlayCircle.ScaleTo(0, 100) .Then().FadeOut().ScaleTo(1).FadeIn(500) - .OnComplete(a => + .OnComplete(_ => { icon.ScaleTo(1, 100); circularProgress.FadeOut(100).OnComplete(_ => diff --git a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs index 83b6f6621b..20bf7045b8 100644 --- a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; namespace osu.Game.Screens.Play.HUD diff --git a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs index eaca623e39..6e36ffb54e 100644 --- a/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/LegacyComboCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs index 2129000268..00dc586448 100644 --- a/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs +++ b/osu.Game/Screens/Play/HUD/MatchScoreDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index b4a3eb209a..0badc063ce 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs b/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs index ff3ca6460f..86fece84fa 100644 --- a/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 5ee6000cf0..ac58325060 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index bdc98e53f9..97a120f9bd 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index 807b4989c7..5f6f040959 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs index 1f659fd5bf..ee29241321 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableInfo.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableInfo.cs @@ -1,10 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; -using Humanizer; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -69,7 +70,7 @@ namespace osu.Game.Screens.Play.HUD var bindable = (IBindable)property.GetValue(component); if (!bindable.IsDefault) - Settings.Add(property.Name.Underscore(), bindable.GetUnderlyingSettingValue()); + Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue()); } if (component is Container container) diff --git a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs index a71b661965..0ba88c549e 100644 --- a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs +++ b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index f6087e0958..8f80644d52 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -86,11 +88,15 @@ namespace osu.Game.Screens.Play Children = new Drawable[] { CreateFailingLayer(), - mainComponents = new MainComponentsContainer(), + mainComponents = new MainComponentsContainer + { + AlwaysPresent = true, + }, topRightElements = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, + AlwaysPresent = true, Margin = new MarginPadding(10), Spacing = new Vector2(10), AutoSizeAxes = Axes.Both, @@ -346,7 +352,7 @@ namespace osu.Game.Screens.Play // When the scoring mode changes, relative positions of elements may change (see DefaultSkin.GetDrawableComponent). // This is a best effort implementation for cases where users haven't customised layouts. scoringMode = config.GetBindable(OsuSetting.ScoreDisplayMode); - scoringMode.BindValueChanged(val => Reload()); + scoringMode.BindValueChanged(_ => Reload()); } } } diff --git a/osu.Game/Screens/Play/HotkeyExitOverlay.cs b/osu.Game/Screens/Play/HotkeyExitOverlay.cs index 9fe7d17cc7..07595a43c4 100644 --- a/osu.Game/Screens/Play/HotkeyExitOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyExitOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index 2812df8bbe..94c0f0a89d 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs index 9a2259b12f..e4328b2c78 100644 --- a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs +++ b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 98df73a5e6..1e5ada5295 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 00eddcc776..f636796436 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; namespace osu.Game.Screens.Play diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 66a44e5314..b6094726c0 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -155,10 +157,10 @@ namespace osu.Game.Screens.Play { switch (e) { - case KeyDownEvent _: - case KeyUpEvent _: - case MouseDownEvent _: - case MouseUpEvent _: + case KeyDownEvent: + case KeyUpEvent: + case MouseDownEvent: + case MouseUpEvent: return Target.Children.Any(c => c.TriggerEvent(e)); } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index 187dcc1264..1005de4ea4 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osuTK.Input; diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index e55525c5e8..0dc2830665 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osuTK.Input; using osuTK; diff --git a/osu.Game/Screens/Play/KeyCounterState.cs b/osu.Game/Screens/Play/KeyCounterState.cs index 0bceae9f85..45d027e5ec 100644 --- a/osu.Game/Screens/Play/KeyCounterState.cs +++ b/osu.Game/Screens/Play/KeyCounterState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Play { public class KeyCounterState diff --git a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs index d87d57ec49..cd37c541ec 100644 --- a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs +++ b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -253,7 +255,7 @@ namespace osu.Game.Screens.Play ControlPointInfo IBeatSyncProvider.ControlPoints => beatmap.Beatmap.ControlPointInfo; IClock IBeatSyncProvider.Clock => GameplayClock; - ChannelAmplitudes? IBeatSyncProvider.Amplitudes => beatmap.TrackLoaded ? beatmap.Track.CurrentAmplitudes : (ChannelAmplitudes?)null; + ChannelAmplitudes? IBeatSyncProvider.Amplitudes => beatmap.TrackLoaded ? beatmap.Track.CurrentAmplitudes : null; private class HardwareCorrectionOffsetClock : FramedOffsetClock { diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index e0b7e5c941..cb98fefcfe 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index dfc0fa1d1d..516364e13a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -19,6 +22,7 @@ using osu.Framework.Threading; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Graphics.Containers; using osu.Game.IO.Archives; using osu.Game.Online.API; @@ -52,6 +56,8 @@ namespace osu.Game.Screens.Play public override bool AllowBackButton => false; // handled by HoldForMenuButton + protected override bool PlayExitSound => !isRestarting; + protected override UserActivity InitialActivity => new UserActivity.InSoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); public override float BackgroundParallaxAmount => 0.1f; @@ -74,6 +80,8 @@ namespace osu.Game.Screens.Play public Action RestartRequested; + private bool isRestarting; + private Bindable mouseWheelDisabled; private readonly Bindable storyboardReplacesBackground = new Bindable(); @@ -166,7 +174,7 @@ namespace osu.Game.Screens.Play PrepareReplay(); - ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(Score.ScoreInfo); + ScoreProcessor.NewJudgement += _ => ScoreProcessor.PopulateScore(Score.ScoreInfo); ScoreProcessor.OnResetFromReplayFrame += () => ScoreProcessor.PopulateScore(Score.ScoreInfo); gameActive.BindValueChanged(_ => updatePauseOnFocusLostState(), true); @@ -181,7 +189,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(AudioManager audio, OsuConfigManager config, OsuGameBase game) + private void load(AudioManager audio, OsuConfigManager config, OsuGameBase game, CancellationToken cancellationToken) { var gameplayMods = Mods.Value.Select(m => m.DeepClone()).ToArray(); @@ -194,7 +202,7 @@ namespace osu.Game.Screens.Play if (Beatmap.Value is DummyWorkingBeatmap) return; - IBeatmap playableBeatmap = loadPlayableBeatmap(gameplayMods); + IBeatmap playableBeatmap = loadPlayableBeatmap(gameplayMods, cancellationToken); if (playableBeatmap == null) return; @@ -259,6 +267,12 @@ namespace osu.Game.Screens.Play }, FailOverlay = new FailOverlay { + SaveReplay = () => + { + Score.ScoreInfo.Passed = false; + Score.ScoreInfo.Rank = ScoreRank.F; + return prepareAndImportScore(); + }, OnRetry = Restart, OnQuit = () => PerformExit(true), }, @@ -308,7 +322,7 @@ namespace osu.Game.Screens.Play GameplayClockContainer.Start(); }); - DrawableRuleset.IsPaused.BindValueChanged(paused => + DrawableRuleset.IsPaused.BindValueChanged(_ => { updateGameplayState(); updateSampleDisabledState(); @@ -483,7 +497,7 @@ namespace osu.Game.Screens.Play } } - private IBeatmap loadPlayableBeatmap(Mod[] gameplayMods) + private IBeatmap loadPlayableBeatmap(Mod[] gameplayMods, CancellationToken cancellationToken) { IBeatmap playable; @@ -500,7 +514,7 @@ namespace osu.Game.Screens.Play try { - playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, gameplayMods); + playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, gameplayMods, cancellationToken); } catch (BeatmapInvalidForRulesetException) { @@ -508,7 +522,7 @@ namespace osu.Game.Screens.Play rulesetInfo = Beatmap.Value.BeatmapInfo.Ruleset; ruleset = rulesetInfo.CreateInstance(); - playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, gameplayMods); + playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, gameplayMods, cancellationToken); } if (playable.HitObjects.Count == 0) @@ -517,6 +531,11 @@ namespace osu.Game.Screens.Play return null; } } + catch (OperationCanceledException) + { + // Load has been cancelled. No logging is required. + return null; + } catch (Exception e) { Logger.Error(e, "Could not load beatmap successfully!"); @@ -637,6 +656,8 @@ namespace osu.Game.Screens.Play if (!Configuration.AllowRestart) return; + isRestarting = true; + // at the point of restarting the track should either already be paused or the volume should be zero. // stopping here is to ensure music doesn't become audible after exiting back to PlayerLoader. musicController.Stop(); @@ -705,7 +726,7 @@ namespace osu.Game.Screens.Play if (!Configuration.ShowResults) return; - prepareScoreForDisplayTask ??= Task.Run(prepareScoreForResults); + prepareScoreForDisplayTask ??= Task.Run(prepareAndImportScore); bool storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; @@ -724,7 +745,7 @@ namespace osu.Game.Screens.Play /// Asynchronously run score preparation operations (database import, online submission etc.). /// /// The final score. - private async Task prepareScoreForResults() + private async Task prepareAndImportScore() { var scoreCopy = Score.DeepClone(); @@ -1009,8 +1030,7 @@ namespace osu.Game.Screens.Play if (prepareScoreForDisplayTask == null) { Score.ScoreInfo.Passed = false; - // potentially should be ScoreRank.F instead? this is the best alternative for now. - Score.ScoreInfo.Rank = ScoreRank.D; + Score.ScoreInfo.Rank = ScoreRank.F; } // EndPlaying() is typically called from ReplayRecorder.Dispose(). Disposal is currently asynchronous. @@ -1050,12 +1070,15 @@ namespace osu.Game.Screens.Play if (DrawableRuleset.ReplayScore != null) return Task.CompletedTask; - LegacyByteArrayReader replayReader; + LegacyByteArrayReader replayReader = null; - using (var stream = new MemoryStream()) + if (score.ScoreInfo.Ruleset.IsLegacyRuleset()) { - new LegacyScoreEncoder(score, GameplayState.Beatmap).Encode(stream); - replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr"); + using (var stream = new MemoryStream()) + { + new LegacyScoreEncoder(score, GameplayState.Beatmap).Encode(stream); + replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr"); + } } // the import process will re-attach managed beatmap/rulesets to this score. we don't want this for now, so create a temporary copy to import. diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index 3aa424e5d5..d11825baee 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Play { public class PlayerConfiguration diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index d75466764d..5d7319c51f 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using System.Threading.Tasks; @@ -51,8 +49,6 @@ namespace osu.Game.Screens.Play // We show the previous screen status protected override UserActivity? InitialActivity => null; - protected override bool PlayResumeSound => false; - protected BeatmapMetadataDisplay MetadataInfo { get; private set; } = null!; /// diff --git a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs index 90caf6f0f3..606b5c198c 100644 --- a/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/AudioSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs index 1662ca399f..75da8e7b9d 100644 --- a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs +++ b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs index ac040774ee..afbd5caef3 100644 --- a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index b1063966da..04cf79873c 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 16e29ac3c8..12646d656a 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs index 26887327cd..dc09676254 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs index 0bbe6902f4..6c6f62a8ac 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Input.Events; using osu.Game.Overlays; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 3f1a5bc0ac..063056e83e 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index a999b32cb4..e55af0bba7 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 617374b4fd..e82238945b 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -20,12 +22,21 @@ namespace osu.Game.Screens.Play { private readonly Func, Score> createScore; + private readonly bool replayIsFailedScore; + // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) - protected override bool CheckModsAllowFailure() => false; + protected override bool CheckModsAllowFailure() + { + if (!replayIsFailedScore) + return false; + + return base.CheckModsAllowFailure(); + } public ReplayPlayer(Score score, PlayerConfiguration configuration = null) - : this((_, __) => score, configuration) + : this((_, _) => score, configuration) { + replayIsFailedScore = score.ScoreInfo.Rank == ScoreRank.F; } public ReplayPlayer(Func, Score> createScore, PlayerConfiguration configuration = null) diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index e78f700af2..a961f90d00 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Screens; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Play/ResumeOverlay.cs b/osu.Game/Screens/Play/ResumeOverlay.cs index 641d5358ba..2be1f93f80 100644 --- a/osu.Game/Screens/Play/ResumeOverlay.cs +++ b/osu.Game/Screens/Play/ResumeOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/RoomSubmittingPlayer.cs b/osu.Game/Screens/Play/RoomSubmittingPlayer.cs index fc96dfa965..3eb659664a 100644 --- a/osu.Game/Screens/Play/RoomSubmittingPlayer.cs +++ b/osu.Game/Screens/Play/RoomSubmittingPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Game.Online.API; using osu.Game.Online.Rooms; diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs new file mode 100644 index 0000000000..3f6e741dff --- /dev/null +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -0,0 +1,92 @@ +// Copyright (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; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Database; +using osu.Game.Scoring; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online; +using osuTK; + +namespace osu.Game.Screens.Play +{ + public class SaveFailedScoreButton : CompositeDrawable + { + private readonly Bindable state = new Bindable(); + + private readonly Func> importFailedScore; + + private ScoreInfo? importedScore; + + private DownloadButton button = null!; + + public SaveFailedScoreButton(Func> importFailedScore) + { + Size = new Vector2(50, 30); + + this.importFailedScore = importFailedScore; + } + + [BackgroundDependencyLoader] + private void load(OsuGame? game, Player? player, RealmAccess realm) + { + InternalChild = button = new DownloadButton + { + RelativeSizeAxes = Axes.Both, + State = { BindTarget = state }, + Action = () => + { + switch (state.Value) + { + case DownloadState.LocallyAvailable: + game?.PresentScore(importedScore, ScorePresentType.Gameplay); + break; + + case DownloadState.NotDownloaded: + state.Value = DownloadState.Importing; + Task.Run(importFailedScore).ContinueWith(t => + { + importedScore = realm.Run(r => r.Find(t.GetResultSafely().ID)?.Detach()); + Schedule(() => state.Value = importedScore != null ? DownloadState.LocallyAvailable : DownloadState.NotDownloaded); + }); + break; + } + } + }; + + if (player != null) + { + importedScore = realm.Run(r => r.Find(player.Score.ScoreInfo.ID)?.Detach()); + if (importedScore != null) + state.Value = DownloadState.LocallyAvailable; + } + + state.BindValueChanged(state => + { + switch (state.NewValue) + { + case DownloadState.LocallyAvailable: + button.TooltipText = @"watch replay"; + button.Enabled.Value = true; + break; + + case DownloadState.Importing: + button.TooltipText = @"importing score"; + button.Enabled.Value = false; + break; + + default: + button.TooltipText = @"save score"; + button.Enabled.Value = true; + break; + } + }, true); + } + } +} diff --git a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs index 30ca15c311..59b92a1b97 100644 --- a/osu.Game/Screens/Play/ScreenSuspensionHandler.cs +++ b/osu.Game/Screens/Play/ScreenSuspensionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 88dab88d42..7152fb7473 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Screens.Backgrounds; diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 84d5507dce..3e2cf9a756 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index a935ce49eb..565f256277 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using osu.Game.Beatmaps; @@ -35,7 +37,7 @@ namespace osu.Game.Screens.Play if (!Ruleset.Value.IsLegacyRuleset()) return null; - return new CreateSoloScoreRequest(beatmapId, rulesetId, Game.VersionHash); + return new CreateSoloScoreRequest(Beatmap.Value.BeatmapInfo, rulesetId, Game.VersionHash); } protected override bool HandleTokenRetrievalFailure(Exception exception) => false; diff --git a/osu.Game/Screens/Play/SoloSpectator.cs b/osu.Game/Screens/Play/SoloSpectator.cs index 202527f308..7eaba40640 100644 --- a/osu.Game/Screens/Play/SoloSpectator.cs +++ b/osu.Game/Screens/Play/SoloSpectator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs index 5b601083c2..5aa310750b 100644 --- a/osu.Game/Screens/Play/SoloSpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SoloSpectatorPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Online.Spectator; diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index b38dcb937d..d1510d10c2 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 5052b32335..67923f4b6a 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index f96de149ba..c742df67ce 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Screens/Play/SongProgressInfo.cs b/osu.Game/Screens/Play/SongProgressInfo.cs index 7a458cdde0..40759c3a3b 100644 --- a/osu.Game/Screens/Play/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/SongProgressInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 09bec9b89f..797787b194 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; @@ -43,6 +45,20 @@ namespace osu.Game.Screens.Play }); } + protected override void LoadComplete() + { + base.LoadComplete(); + + DrawableRuleset.FrameStableClock.WaitingOnFrames.BindValueChanged(waiting => + { + if (GameplayClockContainer is MasterGameplayClockContainer master) + { + if (master.UserPlaybackRate.Value > 1 && waiting.NewValue) + master.UserPlaybackRate.Value = 1; + } + }, true); + } + protected override void StartGameplay() { base.StartGameplay(); diff --git a/osu.Game/Screens/Play/SpectatorPlayerLoader.cs b/osu.Game/Screens/Play/SpectatorPlayerLoader.cs index 9ca5475ee4..6b664a4f96 100644 --- a/osu.Game/Screens/Play/SpectatorPlayerLoader.cs +++ b/osu.Game/Screens/Play/SpectatorPlayerLoader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Screens; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Play/SpectatorResultsScreen.cs b/osu.Game/Screens/Play/SpectatorResultsScreen.cs index fd7af3af85..3d320bd294 100644 --- a/osu.Game/Screens/Play/SpectatorResultsScreen.cs +++ b/osu.Game/Screens/Play/SpectatorResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Online.Spectator; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index a7d4454701..00d6ede3bf 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs index b62dc1e5a6..ad63925b93 100644 --- a/osu.Game/Screens/Play/SubmittingPlayer.cs +++ b/osu.Game/Screens/Play/SubmittingPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading.Tasks; @@ -9,6 +11,8 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Logging; using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Rulesets.Scoring; @@ -115,6 +119,23 @@ namespace osu.Game.Screens.Play await submitScore(score).ConfigureAwait(false); } + [Resolved] + private RealmAccess realm { get; set; } + + protected override void StartGameplay() + { + base.StartGameplay(); + + // User expectation is that last played should be updated when entering the gameplay loop + // from multiplayer / playlists / solo. + realm.WriteAsync(r => + { + var realmBeatmap = r.Find(Beatmap.Value.BeatmapInfo.ID); + if (realmBeatmap != null) + realmBeatmap.LastPlayed = DateTimeOffset.Now; + }); + } + public override bool OnExiting(ScreenExitEvent e) { bool exiting = base.OnExiting(e); @@ -166,7 +187,7 @@ namespace osu.Game.Screens.Play request.Failure += e => { - Logger.Error(e, "Failed to submit score"); + Logger.Error(e, $"Failed to submit score ({e.Message})"); scoreSubmissionSource.SetResult(false); }; diff --git a/osu.Game/Screens/Ranking/AspectContainer.cs b/osu.Game/Screens/Ranking/AspectContainer.cs index 84329d2a04..1c93d08474 100644 --- a/osu.Game/Screens/Ranking/AspectContainer.cs +++ b/osu.Game/Screens/Ranking/AspectContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs index bb286f41c0..3e67868f34 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs @@ -1,9 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -212,7 +215,7 @@ namespace osu.Game.Screens.Ranking.Contracted { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Text = key, + Text = key.ToTitle(), Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold) }, new OsuSpriteText diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs index beff509dc6..74b2f4ef93 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs index b9248bd67e..a1879c5c9b 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs index d0b79aa4c7..80415dbbc2 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs index 894790b5b6..573833932f 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs index 5aea0184ee..2d9c1f9d07 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs index 106af31cae..b4f41e0f39 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/SmoothCircularProgress.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index b924fbd5df..5b8777d2a4 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs index bf06bc2227..d2b2a842b8 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs index 25a644d8d9..824156598c 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/AccuracyStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs index cb25736f6e..3505786b64 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/ComboStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -51,7 +53,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics Spacing = new Vector2(10, 0), Children = new[] { - base.CreateContent().With(d => + base.CreateContent().With(_ => { Anchor = Anchor.CentreLeft; Origin = Anchor.CentreLeft; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs index b1c72173da..17a12a76a5 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/CounterStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs index ada8dfabf0..c23a5e668d 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs index c681946a2f..332215e15d 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/PerformanceStatistic.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs index bbcfc43dc8..36d6d6fa7c 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs index c034abc916..0d8dcda895 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs b/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs index c54bca9e3a..0b06dedc44 100644 --- a/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs +++ b/osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Ranking/PanelState.cs b/osu.Game/Screens/Ranking/PanelState.cs index 94e2c7cef4..3af74fe0f3 100644 --- a/osu.Game/Screens/Ranking/PanelState.cs +++ b/osu.Game/Screens/Ranking/PanelState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Ranking { public enum PanelState diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs index 0c9c909395..7081a0156e 100644 --- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -31,7 +33,7 @@ namespace osu.Game.Screens.Ranking if (State.Value == DownloadState.LocallyAvailable) return ReplayAvailability.Local; - if (!string.IsNullOrEmpty(Score.Value?.Hash)) + if (Score.Value?.HasReplay == true) return ReplayAvailability.Online; return ReplayAvailability.NotAvailable; diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 98514cd846..2f8868c06d 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Ranking/RetryButton.cs b/osu.Game/Screens/Ranking/RetryButton.cs index 59b69bc949..c56f364ae8 100644 --- a/osu.Game/Screens/Ranking/RetryButton.cs +++ b/osu.Game/Screens/Ranking/RetryButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -35,7 +37,7 @@ namespace osu.Game.Screens.Ranking Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(13), - Icon = FontAwesome.Solid.ArrowCircleLeft, + Icon = FontAwesome.Solid.Redo, }, }; diff --git a/osu.Game/Screens/Ranking/ScorePanel.cs b/osu.Game/Screens/Ranking/ScorePanel.cs index bc6eb9e366..babdd4b149 100644 --- a/osu.Game/Screens/Ranking/ScorePanel.cs +++ b/osu.Game/Screens/Ranking/ScorePanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Ranking/ScorePanelList.cs b/osu.Game/Screens/Ranking/ScorePanelList.cs index a5341242e2..4f9e61a4a1 100644 --- a/osu.Game/Screens/Ranking/ScorePanelList.cs +++ b/osu.Game/Screens/Ranking/ScorePanelList.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs b/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs index c8010d1c32..e55c4530b4 100644 --- a/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs +++ b/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 2ec6c38287..4312c9528f 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -31,7 +33,7 @@ namespace osu.Game.Screens.Ranking return null; getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset); - getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo))); + getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineID).Select(s => s.ToScoreInfo(rulesets, Beatmap.Value.BeatmapInfo))); return getScoreRequest; } diff --git a/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs b/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs index d0e70251e7..a0a9c1c1e2 100644 --- a/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs +++ b/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs b/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs index f7c9d36cc4..db69e270f6 100644 --- a/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs +++ b/osu.Game/Screens/Ranking/Statistics/HitEventTimingDistributionGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs index 5b42554716..3462a85e1c 100644 --- a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs +++ b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs index 6fe7e4eda8..ecff631c7e 100644 --- a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs index 8b503cc04e..f1eb16ca80 100644 --- a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs +++ b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs index 79f813ef64..078ca97737 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics.CodeAnalysis; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs index b43fbbdeee..0e5cce59f8 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs b/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs index e1ca9799a3..9f5f44918e 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; namespace osu.Game.Screens.Ranking.Statistics diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs index 898bd69b2c..ab68dec92d 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using System.Threading; @@ -85,7 +87,7 @@ namespace osu.Game.Screens.Ranking.Statistics Task.Run(() => { playableBeatmap = beatmapManager.GetWorkingBeatmap(newScore.BeatmapInfo).GetPlayableBeatmap(newScore.Ruleset, newScore.Mods); - }, loadCancellation.Token).ContinueWith(t => Schedule(() => + }, loadCancellation.Token).ContinueWith(_ => Schedule(() => { bool hitEventsAvailable = newScore.HitEvents.Count != 0; Container container; diff --git a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs index 0d23490f40..4ab085fa23 100644 --- a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs +++ b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/ScorePresentType.cs b/osu.Game/Screens/ScorePresentType.cs index 3216f92091..24105467f1 100644 --- a/osu.Game/Screens/ScorePresentType.cs +++ b/osu.Game/Screens/ScorePresentType.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens { public enum ScorePresentType diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index 3a9e7b8f18..550fda5480 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index e62b285966..75caa3c9a3 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -100,7 +102,7 @@ namespace osu.Game.Screens.Select private readonly NoResultsPlaceholder noResultsPlaceholder; - private IEnumerable beatmapSets => root.Children.OfType(); + private IEnumerable beatmapSets => root.Items.OfType(); // todo: only used for testing, maybe remove. private bool loadedTestBeatmaps; @@ -119,7 +121,7 @@ namespace osu.Game.Screens.Select { CarouselRoot newRoot = new CarouselRoot(this); - newRoot.AddChildren(beatmapSets.Select(s => createCarouselSet(s.Detach())).Where(g => g != null)); + newRoot.AddItems(beatmapSets.Select(s => createCarouselSet(s.Detach())).Where(g => g != null)); root = newRoot; @@ -298,7 +300,7 @@ namespace osu.Game.Screens.Select if (!root.BeatmapSetsByID.TryGetValue(beatmapSetID, out var existingSet)) return; - root.RemoveChild(existingSet); + root.RemoveItem(existingSet); itemsCache.Invalidate(); if (!Scroll.UserScrolling) @@ -314,12 +316,17 @@ namespace osu.Game.Screens.Select previouslySelectedID = selectedBeatmap?.BeatmapInfo.ID; var newSet = createCarouselSet(beatmapSet); + var removedSet = root.RemoveChild(beatmapSet.ID); - root.RemoveChild(beatmapSet.ID); + // If we don't remove this here, it may remain in a hidden state until scrolled off screen. + // Doesn't really affect anything during actual user interaction, but makes testing annoying. + var removedDrawable = Scroll.FirstOrDefault(c => c.Item == removedSet); + if (removedDrawable != null) + expirePanelImmediately(removedDrawable); if (newSet != null) { - root.AddChild(newSet); + root.AddItem(newSet); // check if we can/need to maintain our current selection. if (previouslySelectedID != null) @@ -413,7 +420,7 @@ namespace osu.Game.Screens.Select if (selectedBeatmap == null) return; - var unfilteredDifficulties = selectedBeatmapSet.Children.Where(s => !s.Filtered.Value).ToList(); + var unfilteredDifficulties = selectedBeatmapSet.Items.Where(s => !s.Filtered.Value).ToList(); int index = unfilteredDifficulties.IndexOf(selectedBeatmap); @@ -694,11 +701,7 @@ namespace osu.Game.Screens.Select // panel loaded as drawable but not required by visible range. // remove but only if too far off-screen if (panel.Y + panel.DrawHeight < visibleUpperBound - distance_offscreen_before_unload || panel.Y > visibleBottomBound + distance_offscreen_before_unload) - { - // may want a fade effect here (could be seen if a huge change happens, like a set with 20 difficulties becomes selected). - panel.ClearTransforms(); - panel.Expire(); - } + expirePanelImmediately(panel); } // Add those items within the previously found index range that should be displayed. @@ -728,6 +731,13 @@ namespace osu.Game.Screens.Select } } + private static void expirePanelImmediately(DrawableCarouselItem panel) + { + // may want a fade effect here (could be seen if a huge change happens, like a set with 20 difficulties becomes selected). + panel.ClearTransforms(); + panel.Expire(); + } + private readonly CarouselBoundsItem carouselBoundsItem = new CarouselBoundsItem(); private (int firstIndex, int lastIndex) getDisplayRange() @@ -796,7 +806,7 @@ namespace osu.Game.Screens.Select scrollTarget = null; - foreach (CarouselItem item in root.Children) + foreach (CarouselItem item in root.Items) { if (item.Filtered.Value) continue; @@ -957,31 +967,36 @@ namespace osu.Game.Screens.Select { // root should always remain selected. if not, PerformSelection will not be called. State.Value = CarouselItemState.Selected; - State.ValueChanged += state => State.Value = CarouselItemState.Selected; + State.ValueChanged += _ => State.Value = CarouselItemState.Selected; this.carousel = carousel; } - public override void AddChild(CarouselItem i) + public override void AddItem(CarouselItem i) { CarouselBeatmapSet set = (CarouselBeatmapSet)i; BeatmapSetsByID.Add(set.BeatmapSet.ID, set); - base.AddChild(i); + base.AddItem(i); } - public void RemoveChild(Guid beatmapSetID) + public CarouselBeatmapSet RemoveChild(Guid beatmapSetID) { if (BeatmapSetsByID.TryGetValue(beatmapSetID, out var carouselBeatmapSet)) - RemoveChild(carouselBeatmapSet); + { + RemoveItem(carouselBeatmapSet); + return carouselBeatmapSet; + } + + return null; } - public override void RemoveChild(CarouselItem i) + public override void RemoveItem(CarouselItem i) { CarouselBeatmapSet set = (CarouselBeatmapSet)i; BeatmapSetsByID.Remove(set.BeatmapSet.ID); - base.RemoveChild(i); + base.RemoveItem(i); } protected override void PerformSelection() diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index 4a16be4a3a..84426d230b 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Threading.Tasks; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index b156c2485b..e3b83d5780 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 72c2ba708b..bf6803f551 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -84,7 +86,7 @@ namespace osu.Game.Screens.Select { switch (tab) { - case BeatmapDetailAreaDetailTabItem _: + case BeatmapDetailAreaDetailTabItem: Details.Show(); break; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs index 7376cb4708..d6b076f30b 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Select { public class BeatmapDetailAreaDetailTabItem : BeatmapDetailAreaTabItem diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs index 066944e9d2..6efadc77b3 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Screens.Select diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 0fd39db97c..3c0d621abe 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs index f28e5a7c22..7b7a93d6ee 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Screens.Select diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 9ff1574fe4..90418efe15 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -36,15 +36,18 @@ namespace osu.Game.Screens.Select private readonly LoadingLayer loading; [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; - private IBeatmapInfo beatmapInfo; + [Resolved] + private SongSelect? songSelect { get; set; } - private APIFailTimes failTimes; + private IBeatmapInfo? beatmapInfo; - private int[] ratings; + private APIFailTimes? failTimes; - public IBeatmapInfo BeatmapInfo + private int[]? ratings; + + public IBeatmapInfo? BeatmapInfo { get => beatmapInfo; set @@ -54,7 +57,7 @@ namespace osu.Game.Screens.Select beatmapInfo = value; var onlineInfo = beatmapInfo as IBeatmapOnlineInfo; - var onlineSetInfo = beatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo; + var onlineSetInfo = beatmapInfo?.BeatmapSet as IBeatmapSetOnlineInfo; failTimes = onlineInfo?.FailTimes; ratings = onlineSetInfo?.Ratings; @@ -138,9 +141,9 @@ namespace osu.Game.Screens.Select LayoutEasing = Easing.OutQuad, Children = new[] { - description = new MetadataSection(MetadataType.Description), - source = new MetadataSection(MetadataType.Source), - tags = new MetadataSection(MetadataType.Tags), + description = new MetadataSection(MetadataType.Description, searchOnSongSelect), + source = new MetadataSection(MetadataType.Source, searchOnSongSelect), + tags = new MetadataSection(MetadataType.Tags, searchOnSongSelect), }, }, }, @@ -173,6 +176,12 @@ namespace osu.Game.Screens.Select }, loading = new LoadingLayer(true) }; + + void searchOnSongSelect(string text) + { + if (songSelect != null) + songSelect.FilterControl.CurrentTextSearch.Value = text; + } } private void updateStatistics() @@ -215,7 +224,7 @@ namespace osu.Game.Screens.Select }); }; - lookup.Failure += e => + lookup.Failure += _ => { Schedule(() => { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index d98238f518..3ee9a11b24 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs index d9b8a20846..68f0c92097 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index fd6a869938..81734745c4 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Game.Beatmaps; @@ -53,6 +55,8 @@ namespace osu.Game.Screens.Select.Carousel match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(BeatmapInfo.Metadata.Artist) || criteria.Artist.Matches(BeatmapInfo.Metadata.ArtistUnicode); + match &= criteria.Sort != SortMode.DateRanked || BeatmapInfo.BeatmapSet?.DateRanked != null; + match &= !criteria.UserStarDifficulty.HasFilter || criteria.UserStarDifficulty.IsInRange(BeatmapInfo.StarRating); if (match && criteria.SearchTerms.Length > 0) @@ -72,7 +76,7 @@ namespace osu.Game.Screens.Select.Carousel } if (match) - match &= criteria.Collection?.Beatmaps.Contains(BeatmapInfo) ?? true; + match &= criteria.Collection?.BeatmapHashes.Contains(BeatmapInfo.MD5Hash) ?? true; if (match && criteria.RulesetCriteria != null) match &= criteria.RulesetCriteria.Matches(BeatmapInfo); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index fc4b6c27f3..59d9318962 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -19,7 +21,7 @@ namespace osu.Game.Screens.Select.Carousel switch (State.Value) { case CarouselItemState.Selected: - return DrawableCarouselBeatmapSet.HEIGHT + Children.Count(c => c.Visible) * DrawableCarouselBeatmap.HEIGHT; + return DrawableCarouselBeatmapSet.HEIGHT + Items.Count(c => c.Visible) * DrawableCarouselBeatmap.HEIGHT; default: return DrawableCarouselBeatmapSet.HEIGHT; @@ -27,7 +29,7 @@ namespace osu.Game.Screens.Select.Carousel } } - public IEnumerable Beatmaps => InternalChildren.OfType(); + public IEnumerable Beatmaps => Items.OfType(); public BeatmapSetInfo BeatmapSet; @@ -42,15 +44,15 @@ namespace osu.Game.Screens.Select.Carousel .OrderBy(b => b.Ruleset) .ThenBy(b => b.StarRating) .Select(b => new CarouselBeatmap(b)) - .ForEach(AddChild); + .ForEach(AddItem); } protected override CarouselItem GetNextToSelect() { if (LastSelected == null || LastSelected.Filtered.Value) { - if (GetRecommendedBeatmap?.Invoke(Children.OfType().Where(b => !b.Filtered.Value).Select(b => b.BeatmapInfo)) is BeatmapInfo recommended) - return Children.OfType().First(b => b.BeatmapInfo.Equals(recommended)); + if (GetRecommendedBeatmap?.Invoke(Items.OfType().Where(b => !b.Filtered.Value).Select(b => b.BeatmapInfo)) is BeatmapInfo recommended) + return Items.OfType().First(b => b.BeatmapInfo.Equals(recommended)); } return base.GetNextToSelect(); @@ -79,6 +81,16 @@ namespace osu.Game.Screens.Select.Carousel case SortMode.DateAdded: return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded); + case SortMode.DateRanked: + // Beatmaps which have no ranked date should already be filtered away in this mode. + if (BeatmapSet.DateRanked == null || otherSet.BeatmapSet.DateRanked == null) + return 0; + + return otherSet.BeatmapSet.DateRanked.Value.CompareTo(BeatmapSet.DateRanked.Value); + + case SortMode.LastPlayed: + return -compareUsingAggregateMax(otherSet, b => (b.LastPlayed ?? DateTimeOffset.MinValue).ToUnixTimeSeconds()); + case SortMode.BPM: return compareUsingAggregateMax(otherSet, b => b.BPM); @@ -110,7 +122,7 @@ namespace osu.Game.Screens.Select.Carousel public override void Filter(FilterCriteria criteria) { base.Filter(criteria); - Filtered.Value = InternalChildren.All(i => i.Filtered.Value); + Filtered.Value = Items.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 6ebe314072..e430ff3d3a 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.Linq; -#nullable enable - namespace osu.Game.Screens.Select.Carousel { /// @@ -15,9 +13,9 @@ namespace osu.Game.Screens.Select.Carousel { public override DrawableCarouselItem? CreateDrawableRepresentation() => null; - public IReadOnlyList Children => InternalChildren; + public IReadOnlyList Items => items; - protected List InternalChildren = new List(); + private List items = new List(); /// /// Used to assign a monotonically increasing ID to children as they are added. This member is @@ -29,16 +27,18 @@ namespace osu.Game.Screens.Select.Carousel private FilterCriteria? lastCriteria; - public virtual void RemoveChild(CarouselItem i) + protected int GetIndexOfItem(CarouselItem lastSelected) => items.IndexOf(lastSelected); + + public virtual void RemoveItem(CarouselItem i) { - InternalChildren.Remove(i); + items.Remove(i); // it's important we do the deselection after removing, so any further actions based on // State.ValueChanged make decisions post-removal. i.State.Value = CarouselItemState.Collapsed; } - public virtual void AddChild(CarouselItem i) + public virtual void AddItem(CarouselItem i) { i.State.ValueChanged += state => ChildItemStateChanged(i, state.NewValue); i.ChildID = ++currentChildID; @@ -47,21 +47,21 @@ namespace osu.Game.Screens.Select.Carousel { i.Filter(lastCriteria); - int index = InternalChildren.BinarySearch(i, criteriaComparer); + int index = items.BinarySearch(i, criteriaComparer); if (index < 0) index = ~index; // BinarySearch hacks multiple return values with 2's complement. - InternalChildren.Insert(index, i); + items.Insert(index, i); } else { // criteria may be null for initial population. the filtering will be applied post-add. - InternalChildren.Add(i); + items.Add(i); } } public CarouselGroup(List? items = null) { - if (items != null) InternalChildren = items; + if (items != null) this.items = items; State.ValueChanged += state => { @@ -69,11 +69,11 @@ namespace osu.Game.Screens.Select.Carousel { case CarouselItemState.Collapsed: case CarouselItemState.NotSelected: - InternalChildren.ForEach(c => c.State.Value = CarouselItemState.Collapsed); + this.items.ForEach(c => c.State.Value = CarouselItemState.Collapsed); break; case CarouselItemState.Selected: - InternalChildren.ForEach(c => + this.items.ForEach(c => { if (c.State.Value == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected; }); @@ -86,11 +86,11 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); - InternalChildren.ForEach(c => c.Filter(criteria)); + items.ForEach(c => c.Filter(criteria)); // IEnumerable.OrderBy() is used instead of List.Sort() to ensure sorting stability criteriaComparer = Comparer.Create((x, y) => x.CompareTo(criteria, y)); - InternalChildren = InternalChildren.OrderBy(c => c, criteriaComparer).ToList(); + items = items.OrderBy(c => c, criteriaComparer).ToList(); lastCriteria = criteria; } @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select.Carousel // ensure we are the only item selected if (value == CarouselItemState.Selected) { - foreach (var b in InternalChildren) + foreach (var b in items) { if (item == b) continue; diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs index aac0e4ed82..613b3db5d5 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -47,32 +49,32 @@ namespace osu.Game.Screens.Select.Carousel attemptSelection(); } - public override void RemoveChild(CarouselItem i) + public override void RemoveItem(CarouselItem i) { - base.RemoveChild(i); + base.RemoveItem(i); if (i != LastSelected) updateSelectedIndex(); } - private bool addingChildren; + private bool addingItems; - public void AddChildren(IEnumerable items) + public void AddItems(IEnumerable items) { - addingChildren = true; + addingItems = true; foreach (var i in items) - AddChild(i); + AddItem(i); - addingChildren = false; + addingItems = false; attemptSelection(); } - public override void AddChild(CarouselItem i) + public override void AddItem(CarouselItem i) { - base.AddChild(i); - if (!addingChildren) + base.AddItem(i); + if (!addingItems) attemptSelection(); } @@ -101,15 +103,15 @@ namespace osu.Game.Screens.Select.Carousel 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.Value == CarouselItemState.Selected)) return; + if (Items.Any(i => i.State.Value == CarouselItemState.Selected)) return; PerformSelection(); } protected virtual CarouselItem GetNextToSelect() { - return Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value) ?? - Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value); + return Items.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value) ?? + Items.Reverse().Skip(Items.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value); } protected virtual void PerformSelection() @@ -129,6 +131,6 @@ namespace osu.Game.Screens.Select.Carousel updateSelectedIndex(); } - private void updateSelectedIndex() => lastSelectedIndex = LastSelected == null ? 0 : Math.Max(0, InternalChildren.IndexOf(LastSelected)); + private void updateSelectedIndex() => lastSelectedIndex = LastSelected == null ? 0 : Math.Max(0, GetIndexOfItem(LastSelected)); } } diff --git a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs index ed3aea3445..5cde5f7d5a 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index 4bd477412d..a901f72dad 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 98b885eb43..50e30c68d5 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -51,7 +53,9 @@ namespace osu.Game.Screens.Select.Carousel private Action hideRequested; private Triangles triangles; + private StarCounter starCounter; + private DifficultyIcon difficultyIcon; [Resolved(CanBeNull = true)] private BeatmapSetOverlay beatmapOverlay { get; set; } @@ -111,8 +115,9 @@ namespace osu.Game.Screens.Select.Carousel Origin = Anchor.CentreLeft, Children = new Drawable[] { - new DifficultyIcon(beatmapInfo, shouldShowTooltip: false) + difficultyIcon = new DifficultyIcon(beatmapInfo) { + ShowTooltip = false, Scale = new Vector2(1.8f), }, new FillFlowContainer @@ -148,17 +153,12 @@ namespace osu.Game.Screens.Select.Carousel { Direction = FillDirection.Horizontal, Spacing = new Vector2(4, 0), + Scale = new Vector2(0.8f), AutoSizeAxes = Axes.Both, Children = new Drawable[] { - new TopLocalRank(beatmapInfo) - { - Scale = new Vector2(0.8f), - }, - starCounter = new StarCounter - { - Scale = new Vector2(0.8f), - } + new TopLocalRank(beatmapInfo), + starCounter = new StarCounter() } } } @@ -214,6 +214,8 @@ namespace osu.Game.Screens.Select.Carousel starDifficultyBindable.BindValueChanged(d => { starCounter.Current = (float)(d.NewValue?.Stars ?? 0); + if (d.NewValue != null) + difficultyIcon.Current.Value = d.NewValue.Value; }, true); } @@ -237,7 +239,7 @@ namespace osu.Game.Screens.Select.Carousel if (collectionManager != null) { - var collectionItems = collectionManager.Collections.Select(createCollectionMenuItem).ToList(); + var collectionItems = collectionManager.Collections.Select(c => new CollectionToggleMenuItem(c, beatmapInfo)).Cast().ToList(); if (manageCollectionsDialog != null) collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show)); @@ -251,20 +253,6 @@ namespace osu.Game.Screens.Select.Carousel } } - private MenuItem createCollectionMenuItem(BeatmapCollection collection) - { - return new ToggleMenuItem(collection.Name.Value, MenuItemType.Standard, s => - { - if (s) - collection.Beatmaps.Add(beatmapInfo); - else - collection.Beatmaps.Remove(beatmapInfo); - }) - { - State = { Value = collection.Beatmaps.Contains(beatmapInfo) } - }; - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 2d70b1aecb..8c266c8dff 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -150,7 +152,7 @@ namespace osu.Game.Screens.Select.Carousel { var carouselBeatmapSet = (CarouselBeatmapSet)Item; - var visibleBeatmaps = carouselBeatmapSet.Children.Where(c => c.Visible).ToArray(); + var visibleBeatmaps = carouselBeatmapSet.Items.Where(c => c.Visible).ToArray(); // if we are already displaying all the correct beatmaps, only run animation updates. // note that the displayed beatmaps may change due to the applied filter. @@ -245,7 +247,7 @@ namespace osu.Game.Screens.Select.Carousel TernaryState state; - int countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b)); + int countExisting = beatmapSet.Beatmaps.Count(b => collection.BeatmapHashes.Contains(b.MD5Hash)); if (countExisting == beatmapSet.Beatmaps.Count) state = TernaryState.True; @@ -261,14 +263,14 @@ namespace osu.Game.Screens.Select.Carousel switch (s) { case TernaryState.True: - if (collection.Beatmaps.Contains(b)) + if (collection.BeatmapHashes.Contains(b.MD5Hash)) continue; - collection.Beatmaps.Add(b); + collection.BeatmapHashes.Add(b.MD5Hash); break; case TernaryState.False: - collection.Beatmaps.Remove(b); + collection.BeatmapHashes.Remove(b.MD5Hash); break; } } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 75bcdedec4..133bf5f9c3 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -51,7 +53,7 @@ namespace osu.Game.Screens.Select.Carousel if (item is CarouselGroup group) { - foreach (var c in group.Children) + foreach (var c in group.Items) c.Filtered.ValueChanged -= onStateChange; } } @@ -115,7 +117,7 @@ namespace osu.Game.Screens.Select.Carousel if (Item is CarouselGroup group) { - foreach (var c in group.Children) + foreach (var c in group.Items) c.Filtered.ValueChanged += onStateChange; } } diff --git a/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs b/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs index ce0cec837b..cc904fc1da 100644 --- a/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs +++ b/osu.Game/Screens/Select/Carousel/FilterableDifficultyIcon.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -17,7 +19,7 @@ namespace osu.Game.Screens.Select.Carousel public readonly CarouselBeatmap Item; public FilterableDifficultyIcon(CarouselBeatmap item) - : base(item.BeatmapInfo, performBackgroundDifficultyLookup: false) + : base(item.BeatmapInfo) { filtered.BindTo(item.Filtered); filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); diff --git a/osu.Game/Screens/Select/Carousel/FilterableGroupedDifficultyIcon.cs b/osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs similarity index 52% rename from osu.Game/Screens/Select/Carousel/FilterableGroupedDifficultyIcon.cs rename to osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs index acffdd9f64..8b4140df56 100644 --- a/osu.Game/Screens/Select/Carousel/FilterableGroupedDifficultyIcon.cs +++ b/osu.Game/Screens/Select/Carousel/GroupedDifficultyIcon.cs @@ -1,28 +1,49 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { - public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon + /// + /// A difficulty icon that contains a counter on the right-side of it. + /// + /// + /// Used in cases when there are too many difficulty icons to show. + /// + public class GroupedDifficultyIcon : DifficultyIcon { public readonly List Items; - public FilterableGroupedDifficultyIcon(List items, RulesetInfo ruleset) - : base(items.Select(i => i.BeatmapInfo).ToList(), ruleset, Color4.White) + public GroupedDifficultyIcon(List items, RulesetInfo ruleset) + : base(items.OrderBy(b => b.BeatmapInfo.StarRating).Last().BeatmapInfo, ruleset) { Items = items; foreach (var item in items) item.Filtered.BindValueChanged(_ => Scheduler.AddOnce(updateFilteredDisplay)); + AddInternal(new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Padding = new MarginPadding { Left = Size.X }, + Margin = new MarginPadding { Left = 2, Right = 5 }, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), + Text = items.Count.ToString(), + Colour = Color4.White, + }); + updateFilteredDisplay(); } diff --git a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs index 2a37969be1..2a435e084c 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Select/Carousel/SetPanelContent.cs b/osu.Game/Screens/Select/Carousel/SetPanelContent.cs index a000cfd5fc..a95d9078a2 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelContent.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelContent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -59,14 +61,25 @@ namespace osu.Game.Screens.Select.Carousel Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Top = 5 }, - Children = new Drawable[] + Spacing = new Vector2(5), + Children = new[] { + beatmapSet.AllBeatmapsUpToDate + ? Empty() + : new Container + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new UpdateBeatmapSetButton(beatmapSet), + } + }, new BeatmapSetOnlineStatusPill { AutoSizeAxes = Axes.Both, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, - Margin = new MarginPadding { Right = 5 }, TextSize = 11, TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 }, Status = beatmapSet.Status @@ -74,6 +87,8 @@ namespace osu.Game.Screens.Select.Carousel new FillFlowContainer { AutoSizeAxes = Axes.Both, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, Spacing = new Vector2(3), ChildrenEnumerable = getDifficultyIcons(), }, @@ -90,8 +105,8 @@ namespace osu.Game.Screens.Select.Carousel var beatmaps = carouselSet.Beatmaps.ToList(); return beatmaps.Count > maximum_difficulty_icons - ? (IEnumerable)beatmaps.GroupBy(b => b.BeatmapInfo.Ruleset) - .Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Last().BeatmapInfo.Ruleset)) + ? beatmaps.GroupBy(b => b.BeatmapInfo.Ruleset) + .Select(group => new GroupedDifficultyIcon(group.ToList(), group.Last().BeatmapInfo.Ruleset)) : beatmaps.Select(b => new FilterableDifficultyIcon(b)); } } diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index e1f9c1b508..cc01f61c57 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -55,7 +57,7 @@ namespace osu.Game.Screens.Select.Carousel + $" && {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $2" + $" && {nameof(ScoreInfo.DeletePending)} == false", api.LocalUser.Value.Id, beatmapInfo.ID, ruleset.Value.ShortName) .OrderByDescending(s => s.TotalScore), - (items, changes, ___) => + (items, _, _) => { Rank = items.FirstOrDefault()?.Rank; // Required since presence is changed via IsPresent override diff --git a/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs b/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs new file mode 100644 index 0000000000..b80eb40018 --- /dev/null +++ b/osu.Game/Screens/Select/Carousel/UpdateBeatmapSetButton.cs @@ -0,0 +1,138 @@ +// Copyright (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.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Select.Carousel +{ + public class UpdateBeatmapSetButton : OsuAnimatedButton + { + private readonly BeatmapSetInfo beatmapSetInfo; + private SpriteIcon icon = null!; + private Box progressFill = null!; + + public UpdateBeatmapSetButton(BeatmapSetInfo beatmapSetInfo) + { + this.beatmapSetInfo = beatmapSetInfo; + + AutoSizeAxes = Axes.Both; + + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + } + + [Resolved] + private BeatmapModelDownloader beatmapDownloader { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load() + { + const float icon_size = 14; + + Content.Anchor = Anchor.CentreLeft; + Content.Origin = Anchor.CentreLeft; + + Content.AddRange(new Drawable[] + { + progressFill = new Box + { + Colour = Color4.White, + Alpha = 0.2f, + Blending = BlendingParameters.Additive, + RelativeSizeAxes = Axes.Both, + Width = 0, + }, + new FillFlowContainer + { + Padding = new MarginPadding { Horizontal = 5, Vertical = 3 }, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(4), + Children = new Drawable[] + { + new Container + { + Size = new Vector2(icon_size), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Children = new Drawable[] + { + icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.Solid.SyncAlt, + Size = new Vector2(icon_size), + }, + } + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = OsuFont.Default.With(weight: FontWeight.Bold), + Text = "Update", + } + } + }, + }); + + Action = () => + { + beatmapDownloader.Download(beatmapSetInfo); + attachExistingDownload(); + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + icon.Spin(4000, RotationDirection.Clockwise); + } + + private void attachExistingDownload() + { + var download = beatmapDownloader.GetExistingDownload(beatmapSetInfo); + + if (download != null) + { + Enabled.Value = false; + TooltipText = string.Empty; + + download.DownloadProgressed += progress => progressFill.ResizeWidthTo(progress, 100, Easing.OutQuint); + download.Failure += _ => attachExistingDownload(); + } + else + { + Enabled.Value = true; + TooltipText = "Update beatmap with online changes"; + + progressFill.ResizeWidthTo(0, 100, Easing.OutQuint); + } + } + + protected override bool OnHover(HoverEvent e) + { + icon.Spin(400, RotationDirection.Clockwise); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + icon.Spin(4000, RotationDirection.Clockwise); + base.OnHoverLost(e); + } + } +} diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index a6f2520472..693f182065 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -94,7 +96,7 @@ namespace osu.Game.Screens.Select.Details modSettingChangeTracker?.Dispose(); modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue); - modSettingChangeTracker.SettingChanged += m => + modSettingChangeTracker.SettingChanged += _ => { debouncedStatisticsUpdate?.Cancel(); debouncedStatisticsUpdate = Scheduler.AddDelayed(updateStatistics, 100); diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 312c55b242..6fa6d50217 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index c2be3528fc..39cb9c3d15 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Screens/Select/DifficultyRangeFilterControl.cs b/osu.Game/Screens/Select/DifficultyRangeFilterControl.cs new file mode 100644 index 0000000000..a82c969805 --- /dev/null +++ b/osu.Game/Screens/Select/DifficultyRangeFilterControl.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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Select +{ + internal class DifficultyRangeFilterControl : CompositeDrawable + { + private Bindable lowerStars = null!; + private Bindable upperStars = null!; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + const float vertical_offset = 13; + + InternalChildren = new Drawable[] + { + new OsuSpriteText + { + Text = "Difficulty range", + Font = OsuFont.GetFont(size: 14), + }, + new MaximumStarsSlider + { + Current = config.GetBindable(OsuSetting.DisplayStarsMaximum), + KeyboardStep = 0.1f, + RelativeSizeAxes = Axes.X, + Y = vertical_offset, + }, + new MinimumStarsSlider + { + Current = config.GetBindable(OsuSetting.DisplayStarsMinimum), + KeyboardStep = 0.1f, + RelativeSizeAxes = Axes.X, + Y = vertical_offset, + } + }; + + lowerStars = config.GetBindable(OsuSetting.DisplayStarsMinimum); + upperStars = config.GetBindable(OsuSetting.DisplayStarsMaximum); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + lowerStars.ValueChanged += min => upperStars.Value = Math.Max(min.NewValue + 0.1, upperStars.Value); + upperStars.ValueChanged += max => lowerStars.Value = Math.Min(max.NewValue - 0.1, lowerStars.Value); + } + + private class MinimumStarsSlider : StarsSlider + { + protected override void LoadComplete() + { + base.LoadComplete(); + + LeftBox.Height = 6; // hide any colour bleeding from overlap + + AccentColour = BackgroundColour; + BackgroundColour = Color4.Transparent; + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + base.ReceivePositionalInputAt(screenSpacePos) + && screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X; + } + + private class MaximumStarsSlider : StarsSlider + { + protected override void LoadComplete() + { + base.LoadComplete(); + + RightBox.Height = 6; // just to match the left bar height really + } + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => + base.ReceivePositionalInputAt(screenSpacePos) + && screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X; + } + + private class StarsSlider : OsuSliderBar + { + public override LocalisableString TooltipText => Current.IsDefault + ? UserInterfaceStrings.NoLimit + : Current.Value.ToString(@"0.## stars"); + + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + return true; // Make sure only one nub shows hover effect at once. + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Nub.Width = Nub.HEIGHT; + RangePadding = Nub.Width / 2; + + OsuSpriteText currentDisplay; + + Nub.Add(currentDisplay = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = -0.5f, + Colour = Color4.White, + Font = OsuFont.Torus.With(size: 10), + }); + + Current.BindValueChanged(current => + { + currentDisplay.Text = current.NewValue != Current.Default ? current.NewValue.ToString("N1") : "∞"; + }, true); + } + } + } +} diff --git a/osu.Game/Screens/Select/Filter/GroupMode.cs b/osu.Game/Screens/Select/Filter/GroupMode.cs index d794c215a3..8e2b9271b0 100644 --- a/osu.Game/Screens/Select/Filter/GroupMode.cs +++ b/osu.Game/Screens/Select/Filter/GroupMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; namespace osu.Game.Screens.Select.Filter diff --git a/osu.Game/Screens/Select/Filter/Operator.cs b/osu.Game/Screens/Select/Filter/Operator.cs index 706daf631f..a6a53f0c3e 100644 --- a/osu.Game/Screens/Select/Filter/Operator.cs +++ b/osu.Game/Screens/Select/Filter/Operator.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Screens.Select.Filter { /// diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index 3dd3381059..1e60ea3bac 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; @@ -21,6 +23,12 @@ namespace osu.Game.Screens.Select.Filter [Description("Date Added")] DateAdded, + [Description("Date Ranked")] + DateRanked, + + [Description("Last Played")] + LastPlayed, + [LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingDifficulty))] Difficulty, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 65dde146bb..e43261f374 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -29,6 +31,8 @@ namespace osu.Game.Screens.Select public Action FilterChanged; + public Bindable CurrentTextSearch => searchTextBox.Current; + private OsuTabControl sortTabs; private Bindable sortMode; @@ -61,6 +65,7 @@ namespace osu.Game.Screens.Select } private SeekLimitedSearchTextBox searchTextBox; + private CollectionFilterDropdown collectionDropdown; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => @@ -153,15 +158,23 @@ namespace osu.Game.Screens.Select new Container { RelativeSizeAxes = Axes.X, - Height = 20, + Height = 40, Children = new Drawable[] { + new DifficultyRangeFilterControl + { + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + RelativeSizeAxes = Axes.Both, + Width = 0.48f, + }, collectionDropdown = new CollectionFilterDropdown { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, RelativeSizeAxes = Axes.X, - Width = 0.4f, + Y = 4, + Width = 0.5f, } } }, diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 1f6e99f0c6..c7e6e8496a 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index 94df8addb3..03b72bf5e9 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Globalization; using System.Linq; @@ -22,7 +24,7 @@ namespace osu.Game.Screens.Select { foreach (Match match in query_syntax_regex.Matches(query)) { - string key = match.Groups["key"].Value.ToLower(); + string key = match.Groups["key"].Value.ToLowerInvariant(); var op = parseOperator(match.Groups["op"].Value); string value = match.Groups["value"].Value; diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index ee13ebda44..86fe76c0c6 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osuTK; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 1587f43258..3f8cf2e13a 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -1,20 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; -using osuTK; -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; -using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; -using osu.Framework.Input.Bindings; -using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Select { @@ -66,7 +67,6 @@ namespace osu.Game.Screens.Select private readonly Box light; public FooterButton() - : base(HoverSampleSet.Toolbar) { AutoSizeAxes = Axes.Both; Shear = SHEAR; diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index 5bbca5ca1a..21f81995be 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -1,15 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Screens.Play.HUD; using osu.Game.Rulesets.Mods; using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.UserInterface; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; @@ -59,14 +63,28 @@ namespace osu.Game.Screens.Select Hotkey = GlobalAction.ToggleModSelection; } + [CanBeNull] + private ModSettingChangeTracker modSettingChangeTracker; + protected override void LoadComplete() { base.LoadComplete(); - Current.BindValueChanged(_ => updateMultiplierText(), true); + Current.BindValueChanged(mods => + { + modSettingChangeTracker?.Dispose(); + + updateMultiplierText(); + + if (mods.NewValue != null) + { + modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue); + modSettingChangeTracker.SettingChanged += _ => updateMultiplierText(); + } + }, true); } - private void updateMultiplierText() + private void updateMultiplierText() => Schedule(() => { double multiplier = Current.Value?.Aggregate(1.0, (current, mod) => current * mod.ScoreMultiplier) ?? 1; @@ -83,6 +101,6 @@ namespace osu.Game.Screens.Select modDisplay.FadeIn(); else modDisplay.FadeOut(); - } + }); } } diff --git a/osu.Game/Screens/Select/FooterButtonOptions.cs b/osu.Game/Screens/Select/FooterButtonOptions.cs index e549656785..764f56e79c 100644 --- a/osu.Game/Screens/Select/FooterButtonOptions.cs +++ b/osu.Game/Screens/Select/FooterButtonOptions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index f855b80f75..1f56915f62 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 8d1654eb1d..b497943dfa 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -109,7 +112,7 @@ namespace osu.Game.Screens.Select.Leaderboards if (Scope == BeatmapLeaderboardScope.Local) { - subscribeToLocalScores(cancellationToken); + subscribeToLocalScores(fetchBeatmapInfo, cancellationToken); return null; } @@ -149,7 +152,7 @@ namespace osu.Game.Screens.Select.Leaderboards req.Success += r => { - scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets, fetchBeatmapInfo)).ToArray(), cancellationToken) + scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo)).ToArray(), cancellationToken) .ContinueWith(task => Schedule(() => { if (cancellationToken.IsCancellationRequested) @@ -172,14 +175,13 @@ namespace osu.Game.Screens.Select.Leaderboards Action = () => ScoreSelected?.Invoke(model) }; - private void subscribeToLocalScores(CancellationToken cancellationToken) + private void subscribeToLocalScores(BeatmapInfo beatmapInfo, CancellationToken cancellationToken) { + Debug.Assert(beatmapInfo != null); + scoreSubscription?.Dispose(); scoreSubscription = null; - if (beatmapInfo == null) - return; - scoreSubscription = realm.RegisterForNotifications(r => r.All().Filter($"{nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $0" + $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1" diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index 5bcb4c27a7..b8840b124a 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index cb96e3f23e..3c05a1fa5a 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Game.Overlays.Dialog; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Select/NoResultsPlaceholder.cs b/osu.Game/Screens/Select/NoResultsPlaceholder.cs index 28a0541a22..f3c3fb4d87 100644 --- a/osu.Game/Screens/Select/NoResultsPlaceholder.cs +++ b/osu.Game/Screens/Select/NoResultsPlaceholder.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -52,7 +50,7 @@ namespace osu.Game.Screens.Select Masking = true; CornerRadius = 10; - Width = 300; + Width = 400; AutoSizeAxes = Axes.Y; Anchor = Anchor.Centre; @@ -111,7 +109,7 @@ namespace osu.Game.Screens.Select textFlow.AddParagraph("No beatmaps found!"); textFlow.AddParagraph(string.Empty); - textFlow.AddParagraph("Consider using the \""); + textFlow.AddParagraph("- Consider running the \""); textFlow.AddLink(FirstRunSetupOverlayStrings.FirstRunSetupTitle, () => firstRunSetupOverlay?.Show()); textFlow.AddText("\" to download or import some beatmaps!"); } @@ -120,25 +118,37 @@ namespace osu.Game.Screens.Select textFlow.AddParagraph("No beatmaps match your filter criteria!"); textFlow.AddParagraph(string.Empty); - if (string.IsNullOrEmpty(filter?.SearchText)) + if (filter?.UserStarDifficulty.HasFilter == true) { - // TODO: Add realm queries to hint at which ruleset results are available in (and allow clicking to switch). - // TODO: Make this message more certain by ensuring the osu! beatmaps exist before suggesting. - if (filter?.Ruleset.OnlineID > 0 && !filter.AllowConvertedBeatmaps) + textFlow.AddParagraph("- Try "); + textFlow.AddLink("removing", () => { - textFlow.AddParagraph("Beatmaps may be available by "); - textFlow.AddLink("enabling automatic conversion", () => config.SetValue(OsuSetting.ShowConvertedBeatmaps, true)); - textFlow.AddText("!"); - } + config.SetValue(OsuSetting.DisplayStarsMinimum, 0.0); + config.SetValue(OsuSetting.DisplayStarsMaximum, 10.1); + }); + + string lowerStar = filter.UserStarDifficulty.Min == null ? "∞" : $"{filter.UserStarDifficulty.Min:N1}"; + string upperStar = filter.UserStarDifficulty.Max == null ? "∞" : $"{filter.UserStarDifficulty.Max:N1}"; + + textFlow.AddText($" the {lowerStar}-{upperStar} star difficulty filter."); } - else + + // TODO: Add realm queries to hint at which ruleset results are available in (and allow clicking to switch). + // TODO: Make this message more certain by ensuring the osu! beatmaps exist before suggesting. + if (filter?.Ruleset?.OnlineID != 0 && filter?.AllowConvertedBeatmaps == false) { - textFlow.AddParagraph("You can try "); - textFlow.AddLink("searching online", LinkAction.SearchBeatmapSet, filter.SearchText); - textFlow.AddText(" for this query."); + textFlow.AddParagraph("- Try"); + textFlow.AddLink(" enabling ", () => config.SetValue(OsuSetting.ShowConvertedBeatmaps, true)); + textFlow.AddText("automatic conversion!"); } } + if (!string.IsNullOrEmpty(filter?.SearchText)) + { + textFlow.AddParagraph("- Try "); + textFlow.AddLink("searching online", LinkAction.SearchBeatmapSet, filter.SearchText); + textFlow.AddText($" for \"{filter.SearchText}\"."); + } // TODO: add clickable link to reset criteria. } } diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index df7dd47ef3..69800c4e86 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 1a8b69d859..8785dac0aa 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs b/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs index 09f75b7658..a19acddb48 100644 --- a/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/PlayBeatmapDetailArea.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; @@ -111,7 +113,7 @@ namespace osu.Game.Screens.Select { switch (item) { - case BeatmapDetailAreaDetailTabItem _: + case BeatmapDetailAreaDetailTabItem: return TabType.Details; case BeatmapDetailAreaLeaderboardTabItem leaderboardTab: diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index ec8b2e029a..c24ca9a7cf 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Select/SkinDeleteDialog.cs b/osu.Game/Screens/Select/SkinDeleteDialog.cs index 4262118658..8defd6347a 100644 --- a/osu.Game/Screens/Select/SkinDeleteDialog.cs +++ b/osu.Game/Screens/Select/SkinDeleteDialog.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Game.Skinning; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3bfdc845ab..7abcbfca42 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -358,7 +360,10 @@ namespace osu.Game.Screens.Select { // This is very important as we have not yet bound to screen-level bindables before the carousel load is completed. if (!Carousel.BeatmapSetsLoaded) + { + Logger.Log($"{nameof(FinaliseSelection)} aborted as carousel beatmaps are not yet loaded"); return; + } if (ruleset != null) Ruleset.Value = ruleset; @@ -492,7 +497,7 @@ namespace osu.Game.Screens.Select // clear pending task immediately to track any potential nested debounce operation. selectionChangedDebounce = null; - Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ShortName ?? "null"}"); + Logger.Log($"Song select updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ShortName ?? "null"}"); if (transferRulesetValue()) { @@ -517,7 +522,7 @@ namespace osu.Game.Screens.Select // In these cases, the other component has already loaded the beatmap, so we don't need to do so again. if (!EqualityComparer.Default.Equals(beatmap, Beatmap.Value.BeatmapInfo)) { - Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); + Logger.Log($"Song select changing beatmap from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap?.ToString() ?? "null"}\""); Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap); } @@ -735,7 +740,10 @@ namespace osu.Game.Screens.Select bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; if (!track.IsRunning && (music.UserPauseRequested != true || isNewTrack)) + { + Logger.Log($"Song select decided to {nameof(ensurePlayingSelected)}"); music.Play(true); + } lastTrack.SetTarget(track); } @@ -784,7 +792,17 @@ namespace osu.Game.Screens.Select Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); - decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; + decoupledRuleset.ValueChanged += r => + { + bool wasDisabled = Ruleset.Disabled; + + // a sub-screen may have taken a lease on this decoupled ruleset bindable, + // which would indirectly propagate to the game-global bindable via the `DisabledChanged` callback below. + // to make sure changes sync without crashes, lift the disable for a short while to sync, and then restore the old value. + Ruleset.Disabled = false; + Ruleset.Value = r.NewValue; + Ruleset.Disabled = wasDisabled; + }; decoupledRuleset.DisabledChanged += r => Ruleset.Disabled = r; Beatmap.BindValueChanged(workingBeatmapChanged); diff --git a/osu.Game/Screens/Select/WedgeBackground.cs b/osu.Game/Screens/Select/WedgeBackground.cs index f1337a8119..4a5b9d8911 100644 --- a/osu.Game/Screens/Select/WedgeBackground.cs +++ b/osu.Game/Screens/Select/WedgeBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Spectate/SpectatorGameplayState.cs b/osu.Game/Screens/Spectate/SpectatorGameplayState.cs index 6ca1ac9a0a..498363adef 100644 --- a/osu.Game/Screens/Spectate/SpectatorGameplayState.cs +++ b/osu.Game/Screens/Spectate/SpectatorGameplayState.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index 9eb374f0f7..0c1fe56eb6 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index be217d6b1f..89761d80de 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Overlays; namespace osu.Game.Screens diff --git a/osu.Game/Screens/Utility/ButtonWithKeyBind.cs b/osu.Game/Screens/Utility/ButtonWithKeyBind.cs new file mode 100644 index 0000000000..7df9a22ce4 --- /dev/null +++ b/osu.Game/Screens/Utility/ButtonWithKeyBind.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 osu.Framework.Allocation; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Overlays; +using osu.Game.Overlays.Settings; +using osuTK.Input; + +namespace osu.Game.Screens.Utility +{ + public class ButtonWithKeyBind : SettingsButton + { + private readonly Key key; + + public ButtonWithKeyBind(Key key) + { + this.key = key; + } + + public new LocalisableString Text + { + get => base.Text; + set => base.Text = $"{value} (Press {key.ToString().Replace("Number", string.Empty)})"; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (!e.Repeat && e.Key == key) + { + TriggerClick(); + return true; + } + + return base.OnKeyDown(e); + } + + [Resolved] + private OverlayColourProvider overlayColourProvider { get; set; } = null!; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Height = 100; + SpriteText.Colour = overlayColourProvider.Background6; + SpriteText.Font = OsuFont.TorusAlternate.With(size: 34); + } + } +} diff --git a/osu.Game/Screens/Utility/CircleGameplay.cs b/osu.Game/Screens/Utility/CircleGameplay.cs new file mode 100644 index 0000000000..1ee5567c43 --- /dev/null +++ b/osu.Game/Screens/Utility/CircleGameplay.cs @@ -0,0 +1,238 @@ +// Copyright (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.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Input.States; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Utility.SampleComponents; +using osuTK; + +namespace osu.Game.Screens.Utility +{ + public class CircleGameplay : LatencySampleComponent + { + private int nextLocation; + + private readonly List hitEvents = new List(); + + private double? lastGeneratedBeatTime; + + private Container circles = null!; + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new Drawable[] + { + circles = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }; + + SampleBPM.BindValueChanged(_ => + { + circles.Clear(); + lastGeneratedBeatTime = null; + }); + } + + protected override void UpdateAtLimitedRate(InputState inputState) + { + double beatLength = 60000 / SampleBPM.Value; + + int nextBeat = (int)(Clock.CurrentTime / beatLength) + 1; + + // We want to generate a few hit objects ahead of the current time (to allow them to animate). + double generateUpTo = (nextBeat + 2) * beatLength; + + while (lastGeneratedBeatTime == null || lastGeneratedBeatTime < generateUpTo) + { + double time = ++nextBeat * beatLength; + + if (time <= lastGeneratedBeatTime) + continue; + + newBeat(time); + lastGeneratedBeatTime = time; + } + } + + private void newBeat(double time) + { + nextLocation++; + + Vector2 location; + + float adjust = SampleVisualSpacing.Value * 0.25f; + + float spacingLow = 0.5f - adjust; + float spacingHigh = 0.5f + adjust; + + switch (nextLocation % 4) + { + default: + location = new Vector2(spacingLow, spacingLow); + break; + + case 1: + location = new Vector2(spacingHigh, spacingHigh); + break; + + case 2: + location = new Vector2(spacingHigh, spacingLow); + break; + + case 3: + location = new Vector2(spacingLow, spacingHigh); + break; + } + + circles.Add(new SampleHitCircle(time) + { + RelativePositionAxes = Axes.Both, + Position = location, + Hit = hit, + }); + } + + private void hit(HitEvent h) + { + hitEvents.Add(h); + } + + public class SampleHitCircle : LatencySampleComponent + { + public HitEvent? HitEvent; + + public Action? Hit { get; set; } + + public readonly double HitTime; + + private CircularContainer approach = null!; + private Circle circle = null!; + + private const float size = 100; + private const float duration = 200; + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + => circle.ReceivePositionalInputAt(screenSpacePos); + + public SampleHitCircle(double hitTime) + { + HitTime = hitTime; + + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + AlwaysPresent = true; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChildren = new Drawable[] + { + circle = new Circle + { + Colour = OverlayColourProvider.Content1, + Size = new Vector2(size), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + approach = new CircularContainer + { + BorderColour = colours.Blue, + Size = new Vector2(size), + Masking = true, + BorderThickness = 4, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + Alpha = 0, + AlwaysPresent = true, + RelativeSizeAxes = Axes.Both, + }, + } + }, + }; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + if (HitEvent != null) + return false; + + if (Math.Abs(Clock.CurrentTime - HitTime) > duration) + return false; + + attemptHit(); + return true; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (!IsActive.Value) + return false; + + if (Math.Abs(Clock.CurrentTime - HitTime) > duration) + return false; + + if (IsHovered) + attemptHit(); + return base.OnKeyDown(e); + } + + protected override void UpdateAtLimitedRate(InputState inputState) + { + if (HitEvent == null) + { + double preempt = (float)IBeatmapDifficultyInfo.DifficultyRange(SampleApproachRate.Value, 1800, 1200, 450); + + approach.Scale = new Vector2(1 + 4 * (float)MathHelper.Clamp((HitTime - Clock.CurrentTime) / preempt, 0, 100)); + Alpha = (float)MathHelper.Clamp((Clock.CurrentTime - HitTime + 600) / 400, 0, 1); + + if (Clock.CurrentTime > HitTime + duration) + Expire(); + } + } + + private void attemptHit() => Schedule(() => + { + if (HitEvent != null) + return; + + // in case it was hit outside of display range, show immediately + // so the user isn't confused. + this.FadeIn(); + + approach.Expire(); + + circle + .FadeOut(duration) + .ScaleTo(1.5f, duration); + + HitEvent = new HitEvent(Clock.CurrentTime - HitTime, HitResult.Good, new HitObject + { + HitWindows = new HitWindows(), + }, null, null); + + Hit?.Invoke(HitEvent.Value); + + this.Delay(duration).Expire(); + }); + } + } +} diff --git a/osu.Game/Screens/Utility/LatencyArea.cs b/osu.Game/Screens/Utility/LatencyArea.cs new file mode 100644 index 0000000000..b7d45ba642 --- /dev/null +++ b/osu.Game/Screens/Utility/LatencyArea.cs @@ -0,0 +1,154 @@ +// Copyright (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.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Cursor; +using osu.Game.Overlays; +using osu.Game.Screens.Utility.SampleComponents; +using osuTK.Input; + +namespace osu.Game.Screens.Utility +{ + [Cached] + public class LatencyArea : CompositeDrawable, IProvideCursor + { + [Resolved] + private OverlayColourProvider overlayColourProvider { get; set; } = null!; + + public Action? ReportUserBest { get; set; } + + private Drawable? background; + + private readonly Key key; + + private Container visualContent = null!; + + public readonly int? TargetFrameRate; + + public readonly BindableBool IsActiveArea = new BindableBool(); + + public readonly Bindable VisualMode = new Bindable(); + + public CursorContainer? Cursor { get; private set; } + + public bool ProvidingUserCursor => IsActiveArea.Value; + + public LatencyArea(Key key, int? targetFrameRate) + { + this.key = key; + TargetFrameRate = targetFrameRate; + + RelativeSizeAxes = Axes.Both; + Masking = true; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new[] + { + background = new Box + { + Colour = overlayColourProvider.Background6, + RelativeSizeAxes = Axes.Both, + }, + new ButtonWithKeyBind(key) + { + Text = "Feels better", + Y = 20, + Width = 0.8f, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Action = () => ReportUserBest?.Invoke(), + }, + visualContent = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }; + + IsActiveArea.BindValueChanged(active => + { + background.FadeColour(active.NewValue ? overlayColourProvider.Background4 : overlayColourProvider.Background6, 200, Easing.OutQuint); + }, true); + + VisualMode.BindValueChanged(mode => + { + switch (mode.NewValue) + { + case LatencyVisualMode.Simple: + visualContent.Children = new Drawable[] + { + new LatencyMovableBox + { + RelativeSizeAxes = Axes.Both, + }, + Cursor = new LatencyCursorContainer + { + RelativeSizeAxes = Axes.Both, + }, + }; + break; + + case LatencyVisualMode.CircleGameplay: + visualContent.Children = new Drawable[] + { + new CircleGameplay + { + RelativeSizeAxes = Axes.Both, + }, + Cursor = new LatencyCursorContainer + { + RelativeSizeAxes = Axes.Both, + }, + }; + break; + + case LatencyVisualMode.ScrollingGameplay: + visualContent.Children = new Drawable[] + { + new ScrollingGameplay + { + RelativeSizeAxes = Axes.Both, + }, + Cursor = new LatencyCursorContainer + { + RelativeSizeAxes = Axes.Both, + }, + }; + break; + + default: + throw new ArgumentOutOfRangeException(); + } + }, true); + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + IsActiveArea.Value = true; + return base.OnMouseMove(e); + } + + private double lastFrameTime; + + public override bool UpdateSubTree() + { + double elapsed = Clock.CurrentTime - lastFrameTime; + if (TargetFrameRate.HasValue && elapsed < 1000.0 / TargetFrameRate) + return false; + + lastFrameTime = Clock.CurrentTime; + + return base.UpdateSubTree(); + } + } +} diff --git a/osu.Game/Screens/Utility/LatencyCertifierScreen.cs b/osu.Game/Screens/Utility/LatencyCertifierScreen.cs new file mode 100644 index 0000000000..c9d4dc7811 --- /dev/null +++ b/osu.Game/Screens/Utility/LatencyCertifierScreen.cs @@ -0,0 +1,528 @@ +// Copyright (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 System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Configuration; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Platform; +using osu.Framework.Platform.Windows; +using osu.Framework.Screens; +using osu.Framework.Utils; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; +using osu.Game.Overlays.Settings; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Screens.Utility +{ + [Cached] + public class LatencyCertifierScreen : OsuScreen + { + private FrameSync previousFrameSyncMode; + private double previousActiveHz; + + private readonly OsuTextFlowContainer statusText; + + public override bool HideOverlaysOnEnter => true; + + public override float BackgroundParallaxAmount => 0; + + private readonly LinkFlowContainer explanatoryText; + + private readonly Container mainArea; + + private readonly Container resultsArea; + + public readonly BindableDouble SampleBPM = new BindableDouble(120) { MinValue = 60, MaxValue = 300, Precision = 1 }; + public readonly BindableDouble SampleApproachRate = new BindableDouble(9) { MinValue = 5, MaxValue = 12, Precision = 0.1 }; + public readonly BindableFloat SampleVisualSpacing = new BindableFloat(0.5f) { MinValue = 0f, MaxValue = 1, Precision = 0.1f }; + + /// + /// The rate at which the game host should attempt to run. + /// + private const int target_host_update_frames = 4000; + + [Cached] + private readonly OverlayColourProvider overlayColourProvider = new OverlayColourProvider(OverlayColourScheme.Orange); + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private FrameworkConfigManager config { get; set; } = null!; + + public readonly Bindable VisualMode = new Bindable(); + + private const int rounds_to_complete = 5; + + private const int rounds_to_complete_certified = 20; + + /// + /// Whether we are now in certification mode and decreasing difficulty. + /// + private bool isCertifying; + + private int totalRoundForNextResultsScreen => isCertifying ? rounds_to_complete_certified : rounds_to_complete; + + private int attemptsAtCurrentDifficulty; + private int correctAtCurrentDifficulty; + + public int DifficultyLevel { get; private set; } = 1; + + private double lastPoll; + private int pollingMax; + + private readonly FillFlowContainer settings; + + [Resolved] + private GameHost host { get; set; } = null!; + + [Resolved] + private MusicController musicController { get; set; } = null!; + + public LatencyCertifierScreen() + { + InternalChildren = new Drawable[] + { + new Box + { + Colour = overlayColourProvider.Background6, + RelativeSizeAxes = Axes.Both, + }, + mainArea = new Container + { + RelativeSizeAxes = Axes.Both, + }, + // Make sure the edge between the two comparisons can't be used to ascertain latency. + new Box + { + Name = "separator", + Colour = ColourInfo.GradientHorizontal(overlayColourProvider.Background6, overlayColourProvider.Background6.Opacity(0)), + Width = 100, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopLeft, + }, + new Box + { + Name = "separator", + Colour = ColourInfo.GradientHorizontal(overlayColourProvider.Background6.Opacity(0), overlayColourProvider.Background6), + Width = 100, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopRight, + }, + settings = new FillFlowContainer + { + Name = "Settings", + AutoSizeAxes = Axes.Y, + Width = 800, + Padding = new MarginPadding(10), + Spacing = new Vector2(2), + Direction = FillDirection.Vertical, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Children = new Drawable[] + { + explanatoryText = new LinkFlowContainer(cp => cp.Font = OsuFont.Default.With(size: 20)) + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, + }, + new SettingsSlider + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.None, + Width = 400, + LabelText = "bpm", + Current = SampleBPM + }, + new SettingsSlider + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.None, + Width = 400, + LabelText = "visual spacing", + Current = SampleVisualSpacing + }, + new SettingsSlider + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.None, + Width = 400, + LabelText = "approach rate", + Current = SampleApproachRate + }, + }, + }, + resultsArea = new Container + { + RelativeSizeAxes = Axes.Both, + }, + statusText = new OsuTextFlowContainer(cp => cp.Font = OsuFont.Default.With(size: 40)) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, + Y = 150, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }, + }; + + explanatoryText.AddParagraph(@"Welcome to the latency certifier!"); + explanatoryText.AddParagraph(@"Do whatever you need to try and perceive the difference in latency, then choose your best side. Read more about the methodology "); + explanatoryText.AddLink("here", "https://github.com/ppy/osu/wiki/Latency-and-unlimited-frame-rates#methodology"); + explanatoryText.AddParagraph(@"Use the arrow keys or Z/X/F/J to control the display."); + explanatoryText.AddParagraph(@"Tab key to change focus. Space to change display mode"); + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + if (lastPoll > 0 && Clock.CurrentTime != lastPoll) + pollingMax = (int)Math.Max(pollingMax, 1000 / (Clock.CurrentTime - lastPoll)); + lastPoll = Clock.CurrentTime; + return base.OnMouseMove(e); + } + + public override void OnEntering(ScreenTransitionEvent e) + { + base.OnEntering(e); + + previousFrameSyncMode = config.Get(FrameworkSetting.FrameSync); + previousActiveHz = host.UpdateThread.ActiveHz; + config.SetValue(FrameworkSetting.FrameSync, FrameSync.Unlimited); + host.UpdateThread.ActiveHz = target_host_update_frames; + host.AllowBenchmarkUnlimitedFrames = true; + + musicController.Stop(); + } + + public override bool OnExiting(ScreenExitEvent e) + { + host.AllowBenchmarkUnlimitedFrames = false; + config.SetValue(FrameworkSetting.FrameSync, previousFrameSyncMode); + host.UpdateThread.ActiveHz = previousActiveHz; + return base.OnExiting(e); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + loadNextRound(); + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Space: + int availableModes = Enum.GetValues(typeof(LatencyVisualMode)).Length; + VisualMode.Value = (LatencyVisualMode)(((int)VisualMode.Value + 1) % availableModes); + return true; + + case Key.Tab: + var firstArea = mainArea.FirstOrDefault(a => !a.IsActiveArea.Value); + if (firstArea != null) + firstArea.IsActiveArea.Value = true; + return true; + } + + return base.OnKeyDown(e); + } + + private void showResults() + { + mainArea.Clear(); + resultsArea.Clear(); + settings.Hide(); + + var displayMode = host.Window?.CurrentDisplayMode.Value; + + string exclusive = "unknown"; + + if (host.Window is WindowsWindow windowsWindow) + exclusive = windowsWindow.FullscreenCapability.ToString(); + + statusText.Clear(); + + float successRate = (float)correctAtCurrentDifficulty / attemptsAtCurrentDifficulty; + bool isPass = successRate == 1; + + statusText.AddParagraph($"You scored {correctAtCurrentDifficulty} out of {attemptsAtCurrentDifficulty} ({successRate:0%})!", cp => cp.Colour = isPass ? colours.Green : colours.Red); + statusText.AddParagraph($"Level {DifficultyLevel} ({mapDifficultyToTargetFrameRate(DifficultyLevel):N0} Hz)", + cp => cp.Font = OsuFont.Default.With(size: 24)); + + statusText.AddParagraph(string.Empty); + statusText.AddParagraph(string.Empty); + statusText.AddIcon(isPass ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.TimesCircle, cp => cp.Colour = isPass ? colours.Green : colours.Red); + statusText.AddParagraph(string.Empty); + + if (!isPass && DifficultyLevel > 1) + { + statusText.AddParagraph("To complete certification, the difficulty level will now decrease until you can get 20 rounds correct in a row!", + cp => cp.Font = OsuFont.Default.With(size: 24, weight: FontWeight.SemiBold)); + statusText.AddParagraph(string.Empty); + } + + statusText.AddParagraph($"Polling: {pollingMax} Hz Monitor: {displayMode?.RefreshRate ?? 0:N0} Hz Exclusive: {exclusive}", + cp => cp.Font = OsuFont.Default.With(size: 15, weight: FontWeight.SemiBold)); + + statusText.AddParagraph($"Input: {host.InputThread.Clock.FramesPerSecond} Hz " + + $"Update: {host.UpdateThread.Clock.FramesPerSecond} Hz " + + $"Draw: {host.DrawThread.Clock.FramesPerSecond} Hz" + , cp => cp.Font = OsuFont.Default.With(size: 15, weight: FontWeight.SemiBold)); + + if (isCertifying && isPass) + { + showCertifiedScreen(); + return; + } + + string cannotIncreaseReason = string.Empty; + + if (mapDifficultyToTargetFrameRate(DifficultyLevel + 1) > target_host_update_frames) + cannotIncreaseReason = "You've reached the maximum level."; + else if (mapDifficultyToTargetFrameRate(DifficultyLevel + 1) > Clock.FramesPerSecond) + cannotIncreaseReason = "Game is not running fast enough to test this level"; + + FillFlowContainer buttonFlow; + + resultsArea.Add(buttonFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Spacing = new Vector2(20), + Padding = new MarginPadding(20), + }); + + if (isPass) + { + buttonFlow.Add(new ButtonWithKeyBind(Key.Enter) + { + Text = "Continue to next level", + BackgroundColour = colours.Green, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = () => changeDifficulty(DifficultyLevel + 1), + Enabled = { Value = string.IsNullOrEmpty(cannotIncreaseReason) }, + TooltipText = cannotIncreaseReason + }); + } + else + { + if (DifficultyLevel == 1) + { + buttonFlow.Add(new ButtonWithKeyBind(Key.Enter) + { + Text = "Retry", + TooltipText = "Are you even trying..?", + BackgroundColour = colours.Pink2, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = () => + { + isCertifying = false; + changeDifficulty(1); + }, + }); + } + else + { + buttonFlow.Add(new ButtonWithKeyBind(Key.Enter) + { + Text = "Begin certification at last level", + BackgroundColour = colours.Yellow, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Action = () => + { + isCertifying = true; + changeDifficulty(DifficultyLevel - 1); + }, + TooltipText = isPass + ? $"Chain {rounds_to_complete_certified} rounds to confirm your perception!" + : "You've reached your limits. Go to the previous level to complete certification!", + }); + } + } + } + + private void showCertifiedScreen() + { + Drawable background; + Drawable certifiedText; + + resultsArea.AddRange(new[] + { + background = new Box + { + Colour = overlayColourProvider.Background4, + RelativeSizeAxes = Axes.Both, + }, + (certifiedText = new OsuSpriteText + { + Alpha = 0, + Font = OsuFont.TorusAlternate.With(size: 80, weight: FontWeight.Bold), + Text = "Certified!", + Blending = BlendingParameters.Additive, + }).WithEffect(new GlowEffect + { + Colour = overlayColourProvider.Colour1, + PadExtent = true + }).With(e => + { + e.Anchor = Anchor.Centre; + e.Origin = Anchor.Centre; + }), + new OsuSpriteText + { + Text = $"You should use a frame limiter with update rate of {mapDifficultyToTargetFrameRate(DifficultyLevel + 1)} Hz (or fps) for best results!", + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Torus.With(size: 24, weight: FontWeight.SemiBold), + Y = 80, + } + }); + + background.FadeInFromZero(1000, Easing.OutQuint); + + certifiedText.FadeInFromZero(500, Easing.InQuint); + + certifiedText + .ScaleTo(10) + .ScaleTo(1, 600, Easing.InQuad) + .Then() + .ScaleTo(1.05f, 10000, Easing.OutQuint); + } + + private void changeDifficulty(int difficulty) + { + Debug.Assert(difficulty > 0); + + resultsArea.Clear(); + + correctAtCurrentDifficulty = 0; + attemptsAtCurrentDifficulty = 0; + + pollingMax = 0; + lastPoll = 0; + + DifficultyLevel = difficulty; + + loadNextRound(); + } + + private void loadNextRound() + { + settings.Show(); + + attemptsAtCurrentDifficulty++; + statusText.Text = $"Level {DifficultyLevel}\nRound {attemptsAtCurrentDifficulty} of {totalRoundForNextResultsScreen}"; + + mainArea.Clear(); + + int betterSide = RNG.Next(0, 2); + + mainArea.AddRange(new[] + { + new LatencyArea(Key.Number1, betterSide == 1 ? mapDifficultyToTargetFrameRate(DifficultyLevel) : null) + { + Width = 0.5f, + VisualMode = { BindTarget = VisualMode }, + IsActiveArea = { Value = true }, + ReportUserBest = () => recordResult(betterSide == 0), + }, + new LatencyArea(Key.Number2, betterSide == 0 ? mapDifficultyToTargetFrameRate(DifficultyLevel) : null) + { + Width = 0.5f, + VisualMode = { BindTarget = VisualMode }, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + ReportUserBest = () => recordResult(betterSide == 1) + } + }); + + foreach (var area in mainArea) + { + area.IsActiveArea.BindValueChanged(active => + { + if (active.NewValue) + mainArea.Children.First(a => a != area).IsActiveArea.Value = false; + }); + } + } + + private void recordResult(bool correct) + { + // Fading this out will improve the frame rate after the first round due to less text on screen. + explanatoryText.FadeOut(500, Easing.OutQuint); + + if (correct) + correctAtCurrentDifficulty++; + + if (attemptsAtCurrentDifficulty < totalRoundForNextResultsScreen) + loadNextRound(); + else + showResults(); + } + + private static int mapDifficultyToTargetFrameRate(int difficulty) + { + switch (difficulty) + { + case 1: + return 15; + + case 2: + return 30; + + case 3: + return 45; + + case 4: + return 60; + + case 5: + return 120; + + case 6: + return 240; + + case 7: + return 480; + + case 8: + return 720; + + case 9: + return 960; + + default: + return 1000 + ((difficulty - 10) * 500); + } + } + } +} diff --git a/osu.Game/Screens/Utility/LatencyVisualMode.cs b/osu.Game/Screens/Utility/LatencyVisualMode.cs new file mode 100644 index 0000000000..c4022d09b2 --- /dev/null +++ b/osu.Game/Screens/Utility/LatencyVisualMode.cs @@ -0,0 +1,12 @@ +// 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.Utility +{ + public enum LatencyVisualMode + { + CircleGameplay, + ScrollingGameplay, + Simple, + } +} diff --git a/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.cs b/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.cs new file mode 100644 index 0000000000..aaf837eb60 --- /dev/null +++ b/osu.Game/Screens/Utility/SampleComponents/LatencyCursorContainer.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 osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Input.States; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Screens.Utility.SampleComponents +{ + public class LatencyCursorContainer : CursorContainer + { + protected override Drawable CreateCursor() => new LatencyCursor(); + + public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; + + public LatencyCursorContainer() + { + State.Value = Visibility.Hidden; + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + // Scheduling is required to ensure updating of cursor position happens in limited rate. + // We can alternatively solve this by a PassThroughInputManager layer inside LatencyArea, + // but that would mean including input lag to this test, which may not be desired. + Schedule(() => base.OnMouseMove(e)); + return false; + } + + private class LatencyCursor : LatencySampleComponent + { + public LatencyCursor() + { + AutoSizeAxes = Axes.Both; + Origin = Anchor.Centre; + + InternalChild = new Circle { Size = new Vector2(40) }; + } + + protected override void UpdateAtLimitedRate(InputState inputState) + { + Colour = inputState.Mouse.IsPressed(MouseButton.Left) ? OverlayColourProvider.Content1 : OverlayColourProvider.Colour2; + } + } + } +} diff --git a/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.cs b/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.cs new file mode 100644 index 0000000000..8b6841caf0 --- /dev/null +++ b/osu.Game/Screens/Utility/SampleComponents/LatencyMovableBox.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 osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Input.States; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Screens.Utility.SampleComponents +{ + public class LatencyMovableBox : LatencySampleComponent + { + private Box box = null!; + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChild = box = new Box + { + Size = new Vector2(40), + RelativePositionAxes = Axes.Both, + Position = new Vector2(0.5f), + Origin = Anchor.Centre, + Colour = OverlayColourProvider.Colour1, + }; + } + + protected override bool OnHover(HoverEvent e) => false; + + private double? lastFrameTime; + + protected override void UpdateAtLimitedRate(InputState inputState) + { + if (!IsActive.Value) + { + lastFrameTime = null; + box.Colour = OverlayColourProvider.Colour1; + return; + } + + if (lastFrameTime != null) + { + float movementAmount = (float)(Clock.CurrentTime - lastFrameTime) / 400; + + var buttons = inputState.Keyboard.Keys; + + box.Colour = buttons.HasAnyButtonPressed ? OverlayColourProvider.Content1 : OverlayColourProvider.Colour1; + + foreach (var key in buttons) + { + switch (key) + { + case Key.F: + case Key.Up: + box.Y = MathHelper.Clamp(box.Y - movementAmount, 0.1f, 0.9f); + break; + + case Key.J: + case Key.Down: + box.Y = MathHelper.Clamp(box.Y + movementAmount, 0.1f, 0.9f); + break; + + case Key.Z: + case Key.Left: + box.X = MathHelper.Clamp(box.X - movementAmount, 0.1f, 0.9f); + break; + + case Key.X: + case Key.Right: + box.X = MathHelper.Clamp(box.X + movementAmount, 0.1f, 0.9f); + break; + } + } + } + + lastFrameTime = Clock.CurrentTime; + } + } +} diff --git a/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs b/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs new file mode 100644 index 0000000000..834865d237 --- /dev/null +++ b/osu.Game/Screens/Utility/SampleComponents/LatencySampleComponent.cs @@ -0,0 +1,53 @@ +// Copyright (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.Containers; +using osu.Framework.Input; +using osu.Framework.Input.States; +using osu.Game.Overlays; + +namespace osu.Game.Screens.Utility.SampleComponents +{ + public abstract class LatencySampleComponent : CompositeDrawable + { + protected readonly BindableDouble SampleBPM = new BindableDouble(); + protected readonly BindableDouble SampleApproachRate = new BindableDouble(); + protected readonly BindableFloat SampleVisualSpacing = new BindableFloat(); + + protected readonly BindableBool IsActive = new BindableBool(); + + private InputManager inputManager = null!; + + [Resolved] + private LatencyArea latencyArea { get; set; } = null!; + + [Resolved] + protected OverlayColourProvider OverlayColourProvider { get; private set; } = null!; + + [BackgroundDependencyLoader] + private void load(LatencyCertifierScreen latencyCertifierScreen) + { + SampleBPM.BindTo(latencyCertifierScreen.SampleBPM); + SampleApproachRate.BindTo(latencyCertifierScreen.SampleApproachRate); + SampleVisualSpacing.BindTo(latencyCertifierScreen.SampleVisualSpacing); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + IsActive.BindTo(latencyArea.IsActiveArea); + } + + protected sealed override void Update() + { + base.Update(); + UpdateAtLimitedRate(inputManager.CurrentState); + } + + protected abstract void UpdateAtLimitedRate(InputState inputState); + } +} diff --git a/osu.Game/Screens/Utility/ScrollingGameplay.cs b/osu.Game/Screens/Utility/ScrollingGameplay.cs new file mode 100644 index 0000000000..1f40514cd5 --- /dev/null +++ b/osu.Game/Screens/Utility/ScrollingGameplay.cs @@ -0,0 +1,200 @@ +// Copyright (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.Framework.Graphics.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Input.States; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Utility.SampleComponents; +using osuTK; +using osuTK.Input; + +namespace osu.Game.Screens.Utility +{ + public class ScrollingGameplay : LatencySampleComponent + { + private const float judgement_position = 0.8f; + private const float bar_height = 20; + + private int nextLocation; + + private readonly List hitEvents = new List(); + + private double? lastGeneratedBeatTime; + + private Container circles = null!; + + protected override void LoadComplete() + { + base.LoadComplete(); + + InternalChildren = new Drawable[] + { + new Box + { + Name = "judgement bar", + Colour = OverlayColourProvider.Content2, + RelativeSizeAxes = Axes.X, + RelativePositionAxes = Axes.Y, + Y = judgement_position, + Height = bar_height, + }, + circles = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }; + + SampleBPM.BindValueChanged(_ => + { + circles.Clear(); + lastGeneratedBeatTime = null; + }); + } + + protected override void UpdateAtLimitedRate(InputState inputState) + { + double beatLength = 60000 / SampleBPM.Value; + + int nextBeat = (int)(Clock.CurrentTime / beatLength) + 1; + + // We want to generate a few hit objects ahead of the current time (to allow them to animate). + double generateUpTo = (nextBeat + 2) * beatLength; + + while (lastGeneratedBeatTime == null || lastGeneratedBeatTime < generateUpTo) + { + double time = ++nextBeat * beatLength; + + if (time <= lastGeneratedBeatTime) + continue; + + newBeat(time); + lastGeneratedBeatTime = time; + } + } + + private void newBeat(double time) + { + const float columns = 4; + + float adjustedXPos = ((1f + nextLocation++ % columns) - columns / 2) / columns; + + circles.Add(new SampleNote(time) + { + RelativePositionAxes = Axes.Both, + X = 0.5f + SampleVisualSpacing.Value * (adjustedXPos * 0.5f), + Scale = new Vector2(0.4f + (0.8f * SampleVisualSpacing.Value), 1), + Hit = hit, + }); + } + + private void hit(HitEvent h) + { + hitEvents.Add(h); + } + + public class SampleNote : LatencySampleComponent + { + public HitEvent? HitEvent; + + public Action? Hit { get; set; } + + public readonly double HitTime; + + private Box box = null!; + + private const float size = 100; + private const float duration = 200; + + public SampleNote(double hitTime) + { + HitTime = hitTime; + + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + AlwaysPresent = true; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + box = new Box + { + Colour = OverlayColourProvider.Content1, + Size = new Vector2(size, bar_height), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + }; + } + + protected override bool OnKeyDown(KeyDownEvent e) + { + if (!IsActive.Value) + return false; + + if (Math.Abs(Clock.CurrentTime - HitTime) > duration) + return false; + + // Allow using any key that isn't used by the latency certifier itself. + switch (e.Key) + { + case Key.Space: + case Key.Number1: + case Key.Number2: + case Key.Tab: + return false; + } + + attemptHit(); + return true; + } + + protected override void UpdateAtLimitedRate(InputState inputState) + { + if (HitEvent == null) + { + double preempt = (float)IBeatmapDifficultyInfo.DifficultyRange(SampleApproachRate.Value, 1800, 1200, 450); + + Alpha = (float)MathHelper.Clamp((Clock.CurrentTime - HitTime + 600) / 400, 0, 1); + Y = judgement_position - (float)((HitTime - Clock.CurrentTime) / preempt); + + if (Clock.CurrentTime > HitTime + duration) + Expire(); + } + } + + private void attemptHit() => Schedule(() => + { + if (HitEvent != null) + return; + + // in case it was hit outside of display range, show immediately + // so the user isn't confused. + this.FadeIn(); + + box + .FadeOut(duration / 2) + .ScaleTo(1.5f, duration / 2); + + HitEvent = new HitEvent(Clock.CurrentTime - HitTime, HitResult.Good, new HitObject + { + HitWindows = new HitWindows(), + }, null, null); + + Hit?.Invoke(HitEvent.Value); + + this.Delay(duration).Expire(); + }); + } + } +} diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index 2ba301deed..abc7b61036 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Skinning/Components/BigBlackBox.cs b/osu.Game/Skinning/Components/BigBlackBox.cs index 373e6467e8..5bdee827ca 100644 --- a/osu.Game/Skinning/Components/BigBlackBox.cs +++ b/osu.Game/Skinning/Components/BigBlackBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index f7b415e886..2ebcc98c53 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using JetBrains.Annotations; using osu.Framework.IO.Stores; diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index fb24084659..5267861e3e 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; @@ -72,7 +74,7 @@ namespace osu.Game.Skinning switch (target.Target) { case SkinnableTarget.SongSelect: - var songSelectComponents = new SkinnableTargetComponentsContainer(container => + var songSelectComponents = new SkinnableTargetComponentsContainer(_ => { // do stuff when we need to. }); @@ -111,12 +113,12 @@ namespace osu.Game.Skinning accuracy.Position = new Vector2(-accuracy.ScreenSpaceDeltaToParentSpace(score.ScreenSpaceDrawQuad.Size).X / 2 - horizontal_padding, vertical_offset + 5); accuracy.Origin = Anchor.TopRight; accuracy.Anchor = Anchor.TopCentre; - } - if (combo != null) - { - combo.Position = new Vector2(accuracy.ScreenSpaceDeltaToParentSpace(score.ScreenSpaceDrawQuad.Size).X / 2 + horizontal_padding, vertical_offset + 5); - combo.Anchor = Anchor.TopCentre; + if (combo != null) + { + combo.Position = new Vector2(accuracy.ScreenSpaceDeltaToParentSpace(score.ScreenSpaceDrawQuad.Size).X / 2 + horizontal_padding, vertical_offset + 5); + combo.Anchor = Anchor.TopCentre; + } } var hitError = container.OfType().FirstOrDefault(); diff --git a/osu.Game/Skinning/EFSkinInfo.cs b/osu.Game/Skinning/EFSkinInfo.cs index 50588563be..4204364c50 100644 --- a/osu.Game/Skinning/EFSkinInfo.cs +++ b/osu.Game/Skinning/EFSkinInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; diff --git a/osu.Game/Skinning/Editor/SkinBlueprint.cs b/osu.Game/Skinning/Editor/SkinBlueprint.cs index 1860c6006c..ecf1de89da 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprint.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprint.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs index ebf3c9c319..46f5c1e67f 100644 --- a/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs +++ b/osu.Game/Skinning/Editor/SkinBlueprintContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; diff --git a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs index 756f229927..344a659627 100644 --- a/osu.Game/Skinning/Editor/SkinComponentToolbox.cs +++ b/osu.Game/Skinning/Editor/SkinComponentToolbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.Linq; @@ -86,7 +88,7 @@ namespace osu.Game.Skinning.Editor } } - private class ToolboxComponentButton : OsuButton + public class ToolboxComponentButton : OsuButton { protected override bool ShouldBeConsideredForInput(Drawable child) => false; diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index 095763de18..c1ff161f25 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -11,21 +13,26 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Overlays; +using osu.Game.Overlays.OSD; using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; namespace osu.Game.Skinning.Editor { [Cached(typeof(SkinEditor))] - public class SkinEditor : VisibilityContainer, ICanAcceptFiles + public class SkinEditor : VisibilityContainer, ICanAcceptFiles, IKeyBindingHandler { public const double TRANSITION_DURATION = 500; @@ -66,6 +73,9 @@ namespace osu.Game.Skinning.Editor private EditorSidebar componentsSidebar; private EditorSidebar settingsSidebar; + [Resolved(canBeNull: true)] + private OnScreenDisplay onScreenDisplay { get; set; } + public SkinEditor() { } @@ -188,13 +198,32 @@ namespace osu.Game.Skinning.Editor // schedule ensures this only happens when the skin editor is visible. // also avoid some weird endless recursion / bindable feedback loop (something to do with tracking skins across three different bindable types). // probably something which will be factored out in a future database refactor so not too concerning for now. - currentSkin.BindValueChanged(skin => + currentSkin.BindValueChanged(_ => { hasBegunMutating = false; Scheduler.AddOnce(skinChanged); }, true); - SelectedComponents.BindCollectionChanged((_, __) => Scheduler.AddOnce(populateSettings), true); + SelectedComponents.BindCollectionChanged((_, _) => Scheduler.AddOnce(populateSettings), true); + } + + public bool OnPressed(KeyBindingPressEvent e) + { + switch (e.Action) + { + case PlatformAction.Save: + if (e.Repeat) + return false; + + Save(); + return true; + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { } public void UpdateTargetScreen(Drawable targetScreen) @@ -314,12 +343,19 @@ namespace osu.Game.Skinning.Editor currentSkin.Value.UpdateDrawableTarget(t); skins.Save(skins.CurrentSkin.Value); + onScreenDisplay?.Display(new SkinEditorToast(ToastStrings.SkinSaved, currentSkin.Value.SkinInfo.ToString())); } protected override bool OnHover(HoverEvent e) => true; protected override bool OnMouseDown(MouseDownEvent e) => true; + public override void Hide() + { + base.Hide(); + SelectedComponents.Clear(); + } + protected override void PopIn() { this @@ -387,5 +423,13 @@ namespace osu.Game.Skinning.Editor game?.UnregisterImportHandler(this); } + + private class SkinEditorToast : Toast + { + public SkinEditorToast(LocalisableString value, string skinDisplayName) + : base(SkinSettingsStrings.SkinLayoutEditor, value, skinDisplayName) + { + } + } } } diff --git a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs index a3110ced24..000917f728 100644 --- a/osu.Game/Skinning/Editor/SkinEditorOverlay.cs +++ b/osu.Game/Skinning/Editor/SkinEditorOverlay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -68,7 +70,7 @@ namespace osu.Game.Skinning.Editor var editor = new SkinEditor(); - editor.State.BindValueChanged(visibility => updateComponentVisibility()); + editor.State.BindValueChanged(_ => updateComponentVisibility()); skinEditor = editor; diff --git a/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs b/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs index dc5a8aefc0..4efbf58881 100644 --- a/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs +++ b/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs index 943425e099..2e2122f7c2 100644 --- a/osu.Game/Skinning/Editor/SkinSelectionHandler.cs +++ b/osu.Game/Skinning/Editor/SkinSelectionHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs b/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs index d2823ed0e4..3e19fc3afe 100644 --- a/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs +++ b/osu.Game/Skinning/Editor/SkinSettingsToolbox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Skinning/GameplaySkinComponent.cs b/osu.Game/Skinning/GameplaySkinComponent.cs index 80f6efc07a..cdd3638375 100644 --- a/osu.Game/Skinning/GameplaySkinComponent.cs +++ b/osu.Game/Skinning/GameplaySkinComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; namespace osu.Game.Skinning diff --git a/osu.Game/Skinning/GlobalSkinColours.cs b/osu.Game/Skinning/GlobalSkinColours.cs index f889371b98..e2b5799048 100644 --- a/osu.Game/Skinning/GlobalSkinColours.cs +++ b/osu.Game/Skinning/GlobalSkinColours.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public enum GlobalSkinColours diff --git a/osu.Game/Skinning/HUDSkinComponents.cs b/osu.Game/Skinning/HUDSkinComponents.cs index ea39c98635..586882d790 100644 --- a/osu.Game/Skinning/HUDSkinComponents.cs +++ b/osu.Game/Skinning/HUDSkinComponents.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public enum HUDSkinComponents diff --git a/osu.Game/Skinning/IAnimationTimeReference.cs b/osu.Game/Skinning/IAnimationTimeReference.cs index f627379a57..dcb9e9bbb9 100644 --- a/osu.Game/Skinning/IAnimationTimeReference.cs +++ b/osu.Game/Skinning/IAnimationTimeReference.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.OpenGL.Textures; diff --git a/osu.Game/Skinning/IPooledSampleProvider.cs b/osu.Game/Skinning/IPooledSampleProvider.cs index 40193d1a1a..46cd824e95 100644 --- a/osu.Game/Skinning/IPooledSampleProvider.cs +++ b/osu.Game/Skinning/IPooledSampleProvider.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Game.Audio; diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs index 414a316dec..431fc1c0b8 100644 --- a/osu.Game/Skinning/ISkin.cs +++ b/osu.Game/Skinning/ISkin.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Skinning/ISkinComponent.cs b/osu.Game/Skinning/ISkinComponent.cs index 4bd9f21b6b..34922b98b6 100644 --- a/osu.Game/Skinning/ISkinComponent.cs +++ b/osu.Game/Skinning/ISkinComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public interface ISkinComponent diff --git a/osu.Game/Skinning/ISkinSource.cs b/osu.Game/Skinning/ISkinSource.cs index a5ed0fc990..94940fd549 100644 --- a/osu.Game/Skinning/ISkinSource.cs +++ b/osu.Game/Skinning/ISkinSource.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using JetBrains.Annotations; diff --git a/osu.Game/Skinning/ISkinnableDrawable.cs b/osu.Game/Skinning/ISkinnableDrawable.cs index 3fc6a2fdd8..ca643af17a 100644 --- a/osu.Game/Skinning/ISkinnableDrawable.cs +++ b/osu.Game/Skinning/ISkinnableDrawable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; diff --git a/osu.Game/Skinning/ISkinnableTarget.cs b/osu.Game/Skinning/ISkinnableTarget.cs index 8d4f4dd0c3..17279ef178 100644 --- a/osu.Game/Skinning/ISkinnableTarget.cs +++ b/osu.Game/Skinning/ISkinnableTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Skinning/LegacyAccuracyCounter.cs b/osu.Game/Skinning/LegacyAccuracyCounter.cs index bdcb85456a..ffb463faae 100644 --- a/osu.Game/Skinning/LegacyAccuracyCounter.cs +++ b/osu.Game/Skinning/LegacyAccuracyCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Play.HUD; diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 70f5b35d00..e8414b4c11 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; @@ -98,7 +96,7 @@ namespace osu.Game.Skinning new SkinInfo { Name = beatmapInfo.ToString(), - Creator = beatmapInfo.Metadata.Author.Username ?? string.Empty + Creator = beatmapInfo.Metadata.Author.Username }; } } diff --git a/osu.Game/Skinning/LegacyColourCompatibility.cs b/osu.Game/Skinning/LegacyColourCompatibility.cs index 38e43432ce..0673d0a8d3 100644 --- a/osu.Game/Skinning/LegacyColourCompatibility.cs +++ b/osu.Game/Skinning/LegacyColourCompatibility.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Skinning/LegacyFont.cs b/osu.Game/Skinning/LegacyFont.cs index d1971cb84c..f738caf3f3 100644 --- a/osu.Game/Skinning/LegacyFont.cs +++ b/osu.Game/Skinning/LegacyFont.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { /// diff --git a/osu.Game/Skinning/LegacyHealthDisplay.cs b/osu.Game/Skinning/LegacyHealthDisplay.cs index b1cd1f86c0..236e9c355e 100644 --- a/osu.Game/Skinning/LegacyHealthDisplay.cs +++ b/osu.Game/Skinning/LegacyHealthDisplay.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs index e76f251ce5..b87fc9acb5 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceNew.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index 5d74ab9ae3..c47f46ed2b 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index 77d390875b..5ed2ddc73c 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs index 9db6c8bf66..45454be4a5 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public class LegacyManiaSkinConfigurationLookup diff --git a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs index 7214c847a7..49914c53aa 100644 --- a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs +++ b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -118,16 +120,16 @@ namespace osu.Game.Skinning currentConfig.MinimumColumnWidth = minWidth; break; - case string _ when pair.Key.StartsWith("Colour", StringComparison.Ordinal): + case string when pair.Key.StartsWith("Colour", StringComparison.Ordinal): HandleColours(currentConfig, line); break; // Custom sprite paths - case string _ when pair.Key.StartsWith("NoteImage", StringComparison.Ordinal): - case string _ when pair.Key.StartsWith("KeyImage", StringComparison.Ordinal): - case string _ when pair.Key.StartsWith("Hit", StringComparison.Ordinal): - case string _ when pair.Key.StartsWith("Stage", StringComparison.Ordinal): - case string _ when pair.Key.StartsWith("Lighting", StringComparison.Ordinal): + case string when pair.Key.StartsWith("NoteImage", StringComparison.Ordinal): + case string when pair.Key.StartsWith("KeyImage", StringComparison.Ordinal): + case string when pair.Key.StartsWith("Hit", StringComparison.Ordinal): + case string when pair.Key.StartsWith("Stage", StringComparison.Ordinal): + case string when pair.Key.StartsWith("Lighting", StringComparison.Ordinal): currentConfig.ImageLookups[pair.Key] = pair.Value; break; } diff --git a/osu.Game/Skinning/LegacyRollingCounter.cs b/osu.Game/Skinning/LegacyRollingCounter.cs index b531ae1e6f..fd17b06a21 100644 --- a/osu.Game/Skinning/LegacyRollingCounter.cs +++ b/osu.Game/Skinning/LegacyRollingCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Skinning/LegacyScoreCounter.cs b/osu.Game/Skinning/LegacyScoreCounter.cs index 0c9a82074f..aee594454f 100644 --- a/osu.Game/Skinning/LegacyScoreCounter.cs +++ b/osu.Game/Skinning/LegacyScoreCounter.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Play.HUD; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9524d3f615..34219722a1 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index aac343d710..e5f87b3230 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Globalization; using osu.Game.Beatmaps.Formats; diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index 514a06a4ee..5a537dd57d 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Skinning/LegacySkinTransformer.cs b/osu.Game/Skinning/LegacySkinTransformer.cs index 34714b9dc5..da7da759fc 100644 --- a/osu.Game/Skinning/LegacySkinTransformer.cs +++ b/osu.Game/Skinning/LegacySkinTransformer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using JetBrains.Annotations; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs index 94383834fc..c5d65cb0c7 100644 --- a/osu.Game/Skinning/LegacySpriteText.cs +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs index b34351d4e7..ebcaeaa3ff 100644 --- a/osu.Game/Skinning/PausableSkinnableSound.cs +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index 5db4f00b46..49bc71064c 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/Skinning/RealmBackedResourceStore.cs b/osu.Game/Skinning/RealmBackedResourceStore.cs index 7fa24284ee..0cc90f1dcb 100644 --- a/osu.Game/Skinning/RealmBackedResourceStore.cs +++ b/osu.Game/Skinning/RealmBackedResourceStore.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Skinning/ResourceStoreBackedSkin.cs b/osu.Game/Skinning/ResourceStoreBackedSkin.cs index 48286bff59..597eef99d4 100644 --- a/osu.Game/Skinning/ResourceStoreBackedSkin.cs +++ b/osu.Game/Skinning/ResourceStoreBackedSkin.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using osu.Framework.Audio; using osu.Framework.Audio.Sample; diff --git a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs index b884794739..937cf20bc6 100644 --- a/osu.Game/Skinning/RulesetSkinProvidingContainer.cs +++ b/osu.Game/Skinning/RulesetSkinProvidingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index b9f9d3bd10..d6aa9cdaad 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Skinning/SkinComboColourLookup.cs b/osu.Game/Skinning/SkinComboColourLookup.cs index 33e35a96fb..2eb4af6289 100644 --- a/osu.Game/Skinning/SkinComboColourLookup.cs +++ b/osu.Game/Skinning/SkinComboColourLookup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Skinning diff --git a/osu.Game/Skinning/SkinConfigManager.cs b/osu.Game/Skinning/SkinConfigManager.cs index 682138a2e9..8a34ab3db4 100644 --- a/osu.Game/Skinning/SkinConfigManager.cs +++ b/osu.Game/Skinning/SkinConfigManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Configuration; diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index f71f6811e8..0b1159f8fd 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Game.Beatmaps.Formats; using osuTK.Graphics; diff --git a/osu.Game/Skinning/SkinCustomColourLookup.cs b/osu.Game/Skinning/SkinCustomColourLookup.cs index b8e5ac9b53..319b071bf5 100644 --- a/osu.Game/Skinning/SkinCustomColourLookup.cs +++ b/osu.Game/Skinning/SkinCustomColourLookup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public class SkinCustomColourLookup diff --git a/osu.Game/Skinning/SkinFileInfo.cs b/osu.Game/Skinning/SkinFileInfo.cs index 4f1bf68e51..f3243d3f24 100644 --- a/osu.Game/Skinning/SkinFileInfo.cs +++ b/osu.Game/Skinning/SkinFileInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.ComponentModel.DataAnnotations; using osu.Game.Database; using osu.Game.IO; diff --git a/osu.Game/Skinning/SkinModelManager.cs b/osu.Game/Skinning/SkinImporter.cs similarity index 92% rename from osu.Game/Skinning/SkinModelManager.cs rename to osu.Game/Skinning/SkinImporter.cs index 23813e8eb2..ed31a8c3f5 100644 --- a/osu.Game/Skinning/SkinModelManager.cs +++ b/osu.Game/Skinning/SkinImporter.cs @@ -14,24 +14,25 @@ using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.IO.Archives; -using osu.Game.Stores; using Realms; -#nullable enable - namespace osu.Game.Skinning { - public class SkinModelManager : RealmArchiveModelManager + public class SkinImporter : RealmArchiveModelImporter { private const string skin_info_file = "skininfo.json"; private readonly IStorageResourceProvider skinResources; - public SkinModelManager(Storage storage, RealmAccess realm, IStorageResourceProvider skinResources) + private readonly ModelManager modelManager; + + public SkinImporter(Storage storage, RealmAccess realm, IStorageResourceProvider skinResources) : base(storage, realm) { this.skinResources = skinResources; + modelManager = new ModelManager(storage, realm); + // can be removed 20220420. populateMissingHashes(); } @@ -46,8 +47,6 @@ namespace osu.Game.Skinning private const string unknown_creator_string = @"Unknown"; - protected override bool HasCustomHashFunction => true; - protected override void Populate(SkinInfo model, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default) { var skinInfoFile = model.Files.SingleOrDefault(f => f.Filename == skin_info_file); @@ -157,7 +156,7 @@ namespace osu.Game.Skinning sw.WriteLine(line); } - ReplaceFile(existingFile, stream, realm); + modelManager.ReplaceFile(existingFile, stream, realm); // can be removed 20220502. if (!ensureIniWasUpdated(item)) @@ -187,7 +186,7 @@ namespace osu.Game.Skinning sw.WriteLine(line); } - AddFile(item, stream, @"skin.ini", realm); + modelManager.AddFile(item, stream, @"skin.ini", realm); } item.Hash = ComputeHash(item); @@ -215,11 +214,11 @@ namespace osu.Game.Skinning { try { - realm.Write(r => skin.Hash = ComputeHash(skin)); + realm.Write(_ => skin.Hash = ComputeHash(skin)); } catch (Exception e) { - Delete(skin); + modelManager.Delete(skin); Logger.Error(e, $"Existing skin {skin} has been deleted during hash recomputation due to being invalid"); } } @@ -237,7 +236,7 @@ namespace osu.Game.Skinning using (var streamContent = new MemoryStream(Encoding.UTF8.GetBytes(skinInfoJson))) { - AddFile(s, streamContent, skin_info_file, s.Realm); + modelManager.AddFile(s, streamContent, skin_info_file, s.Realm); } // Then serialise each of the drawable component groups into respective files. @@ -252,16 +251,14 @@ namespace osu.Game.Skinning var oldFile = s.Files.FirstOrDefault(f => f.Filename == filename); if (oldFile != null) - ReplaceFile(oldFile, streamContent, s.Realm); + modelManager.ReplaceFile(oldFile, streamContent, s.Realm); else - AddFile(s, streamContent, filename, s.Realm); + modelManager.AddFile(s, streamContent, filename, s.Realm); } } s.Hash = ComputeHash(s); }); } - - public override bool IsAvailableLocally(SkinInfo model) => true; // skins do not have online download support yet. } } diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index a89725e466..bf3cf77257 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -12,8 +12,6 @@ using osu.Game.IO; using osu.Game.Models; using Realms; -#nullable enable - namespace osu.Game.Skinning { [ExcludeFromDynamicCompile] diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 5e1902f520..dc0197e613 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -1,9 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -23,8 +24,6 @@ using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Database; using osu.Game.IO; -using osu.Game.IO.Archives; -using osu.Game.Models; using osu.Game.Overlays.Notifications; using osu.Game.Utils; @@ -38,7 +37,7 @@ namespace osu.Game.Skinning /// For gameplay components, see which adds extra legacy and toggle logic that may affect the lookup process. /// [ExcludeFromDynamicCompile] - public class SkinManager : ISkinSource, IStorageResourceProvider, IModelImporter, IModelManager, IModelFileManager + public class SkinManager : ModelManager, ISkinSource, IStorageResourceProvider, IModelImporter { private readonly AudioManager audio; @@ -55,8 +54,7 @@ namespace osu.Game.Skinning Default = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged() }; - private readonly SkinModelManager skinModelManager; - private readonly RealmAccess realm; + private readonly SkinImporter skinImporter; private readonly IResourceStore userFiles; @@ -71,8 +69,8 @@ namespace osu.Game.Skinning public Skin DefaultLegacySkin { get; } public SkinManager(Storage storage, RealmAccess realm, GameHost host, IResourceStore resources, AudioManager audio, Scheduler scheduler) + : base(storage, realm) { - this.realm = realm; this.audio = audio; this.scheduler = scheduler; this.host = host; @@ -80,7 +78,10 @@ namespace osu.Game.Skinning userFiles = new StorageBackedResourceStore(storage.GetStorageForDirectory("files")); - skinModelManager = new SkinModelManager(storage, realm, this); + skinImporter = new SkinImporter(storage, realm, this) + { + PostNotification = obj => PostNotification?.Invoke(obj), + }; var defaultSkins = new[] { @@ -115,7 +116,7 @@ namespace osu.Game.Skinning public void SelectRandomSkin() { - realm.Run(r => + Realm.Run(r => { // choose from only user skins, removing the current selection to ensure a new one is chosen. var randomChoices = r.All().Where(s => !s.DeletePending && s.ID != CurrentSkinInfo.Value.ID).ToArray(); @@ -128,7 +129,7 @@ namespace osu.Game.Skinning var chosen = randomChoices.ElementAt(RNG.Next(0, randomChoices.Length)); - CurrentSkinInfo.Value = chosen.ToLive(realm); + CurrentSkinInfo.Value = chosen.ToLive(Realm); }); } @@ -153,7 +154,7 @@ namespace osu.Game.Skinning if (!s.Protected) return false; - string[] existingSkinNames = realm.Run(r => r.All() + string[] existingSkinNames = Realm.Run(r => r.All() .Where(skin => !skin.DeletePending) .AsEnumerable() .Select(skin => skin.Name).ToArray()); @@ -166,7 +167,7 @@ namespace osu.Game.Skinning Name = NamingUtils.GetNextBestName(existingSkinNames, $@"{s.Name} (modified)") }; - var result = skinModelManager.Import(skinInfo); + var result = skinImporter.ImportModel(skinInfo); if (result != null) { @@ -186,7 +187,7 @@ namespace osu.Game.Skinning if (!skin.SkinInfo.IsManaged) throw new InvalidOperationException($"Attempting to save a skin which is not yet tracked. Call {nameof(EnsureMutableSkin)} first."); - skinModelManager.Save(skin); + skinImporter.Save(skin); } /// @@ -196,7 +197,7 @@ namespace osu.Game.Skinning /// The first result for the provided query, or null if no results were found. public Live Query(Expression> query) { - return realm.Run(r => r.All().FirstOrDefault(query)?.ToLive(realm)); + return Realm.Run(r => r.All().FirstOrDefault(query)?.ToLive(Realm)); } public event Action SourceChanged; @@ -251,62 +252,33 @@ namespace osu.Game.Skinning AudioManager IStorageResourceProvider.AudioManager => audio; IResourceStore IStorageResourceProvider.Resources => resources; IResourceStore IStorageResourceProvider.Files => userFiles; - RealmAccess IStorageResourceProvider.RealmAccess => realm; + RealmAccess IStorageResourceProvider.RealmAccess => Realm; IResourceStore IStorageResourceProvider.CreateTextureLoaderStore(IResourceStore underlyingStore) => host.CreateTextureLoaderStore(underlyingStore); #endregion #region Implementation of IModelImporter - public Action PostNotification + public Action>> PresentImport { - set => skinModelManager.PostNotification = value; + set => skinImporter.PresentImport = value; } - public Action>> PostImport - { - set => skinModelManager.PostImport = value; - } + public Task Import(params string[] paths) => skinImporter.Import(paths); - public Task Import(params string[] paths) - { - return skinModelManager.Import(paths); - } + public Task Import(params ImportTask[] tasks) => skinImporter.Import(tasks); - public Task Import(params ImportTask[] tasks) - { - return skinModelManager.Import(tasks); - } + public IEnumerable HandledExtensions => skinImporter.HandledExtensions; - public IEnumerable HandledExtensions => skinModelManager.HandledExtensions; + public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => skinImporter.Import(notification, tasks); - public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) - { - return skinModelManager.Import(notification, tasks); - } - - public Task> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return skinModelManager.Import(task, lowPriority, cancellationToken); - } - - public Task> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return skinModelManager.Import(archive, lowPriority, cancellationToken); - } - - public Live Import(SkinInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) - { - return skinModelManager.Import(item, archive, lowPriority, cancellationToken); - } + public Task> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinImporter.Import(task, batchImport, cancellationToken); #endregion - #region Implementation of IModelManager - public void Delete([CanBeNull] Expression> filter = null, bool silent = false) { - realm.Run(r => + Realm.Run(r => { var items = r.All() .Where(s => !s.Protected && !s.DeletePending); @@ -319,50 +291,8 @@ namespace osu.Game.Skinning if (items.Any(s => s.ID == currentUserSkin)) scheduler.Add(() => CurrentSkinInfo.Value = Skinning.DefaultSkin.CreateInfo().ToLiveUnmanaged()); - skinModelManager.Delete(items.ToList(), silent); + Delete(items.ToList(), silent); }); } - - #endregion - - public bool Delete(SkinInfo item) - { - return skinModelManager.Delete(item); - } - - public void Delete(List items, bool silent = false) - { - skinModelManager.Delete(items, silent); - } - - public void Undelete(List items, bool silent = false) - { - skinModelManager.Undelete(items, silent); - } - - public void Undelete(SkinInfo item) - { - skinModelManager.Undelete(item); - } - - public bool IsAvailableLocally(SkinInfo model) - { - return skinModelManager.IsAvailableLocally(model); - } - - public void ReplaceFile(SkinInfo model, RealmNamedFileUsage file, Stream contents) - { - skinModelManager.ReplaceFile(model, file, contents); - } - - public void DeleteFile(SkinInfo model, RealmNamedFileUsage file) - { - skinModelManager.DeleteFile(model, file); - } - - public void AddFile(SkinInfo model, Stream contents, string filename) - { - skinModelManager.AddFile(model, contents, filename); - } } } diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index 24198254a3..e447570931 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -267,9 +269,9 @@ namespace osu.Game.Skinning { switch (lookup) { - case GlobalSkinColours _: - case SkinComboColourLookup _: - case SkinCustomColourLookup _: + case GlobalSkinColours: + case SkinComboColourLookup: + case SkinCustomColourLookup: if (provider.AllowColourLookup) return skin.GetConfig(lookup); diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index dec546b82d..c6332fc4d2 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Pooling; diff --git a/osu.Game/Skinning/SkinUtils.cs b/osu.Game/Skinning/SkinUtils.cs index e3bc5e28b8..8e01bd2853 100644 --- a/osu.Game/Skinning/SkinUtils.cs +++ b/osu.Game/Skinning/SkinUtils.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; namespace osu.Game.Skinning diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 45409694b5..480d66c557 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Caching; using osu.Framework.Graphics; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index c9e55c09aa..c2696c56f3 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 21b34fcd27..57beb6e803 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index 2bde3c4180..3e9462b83e 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Skinning/SkinnableTarget.cs b/osu.Game/Skinning/SkinnableTarget.cs index 09de8a5d71..bca0d499f7 100644 --- a/osu.Game/Skinning/SkinnableTarget.cs +++ b/osu.Game/Skinning/SkinnableTarget.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public enum SkinnableTarget diff --git a/osu.Game/Skinning/SkinnableTargetComponent.cs b/osu.Game/Skinning/SkinnableTargetComponent.cs index a17aafe6e7..51af1c23c9 100644 --- a/osu.Game/Skinning/SkinnableTargetComponent.cs +++ b/osu.Game/Skinning/SkinnableTargetComponent.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Skinning { public class SkinnableTargetComponent : ISkinComponent diff --git a/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs b/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs index 67114de948..dd7290a858 100644 --- a/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs +++ b/osu.Game/Skinning/SkinnableTargetComponentsContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; using osu.Framework.Graphics; diff --git a/osu.Game/Skinning/SkinnableTargetContainer.cs b/osu.Game/Skinning/SkinnableTargetContainer.cs index 20c2fcc075..341a881789 100644 --- a/osu.Game/Skinning/SkinnableTargetContainer.cs +++ b/osu.Game/Skinning/SkinnableTargetContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Threading; diff --git a/osu.Game/Skinning/UnsupportedSkinComponentException.cs b/osu.Game/Skinning/UnsupportedSkinComponentException.cs index 7f0dd51d5b..3713b7c200 100644 --- a/osu.Game/Skinning/UnsupportedSkinComponentException.cs +++ b/osu.Game/Skinning/UnsupportedSkinComponentException.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; namespace osu.Game.Skinning diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 0713cb8670..0f26ed2c66 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index 8ded3ee975..4d0da9597b 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using System; using System.Collections.Generic; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index e7de135ce8..6fc9f60177 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osuTK; using osuTK.Graphics; @@ -54,7 +56,7 @@ namespace osu.Game.Storyboards { var first = Alpha.Commands.FirstOrDefault(); - return first?.StartValue == 0 ? first.StartTime : (double?)null; + return first?.StartValue == 0 ? first.StartTime : null; } } diff --git a/osu.Game/Storyboards/CommandTrigger.cs b/osu.Game/Storyboards/CommandTrigger.cs index 011f345df2..50f3f0ef49 100644 --- a/osu.Game/Storyboards/CommandTrigger.cs +++ b/osu.Game/Storyboards/CommandTrigger.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Storyboards { public class CommandTrigger : CommandTimelineGroup diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index a0fb7b0b4a..be98ca9a46 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -15,7 +17,6 @@ using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; -using osu.Game.Stores; namespace osu.Game.Storyboards.Drawables { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 8a14b8b183..9822f36620 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using osu.Framework.Allocation; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 1085b52d65..13f116af24 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 4e3f72512c..2e7ca31fe9 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index a6f2b8fcbd..28ed2e65e3 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs index 0625ddaffd..23b1004e74 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs index bbc55a336d..779c8384c5 100644 --- a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + 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 165b3d97cc..aceb5c041c 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Storyboards/Drawables/IVectorScalable.cs b/osu.Game/Storyboards/Drawables/IVectorScalable.cs index fcc407d460..3b43a35a90 100644 --- a/osu.Game/Storyboards/Drawables/IVectorScalable.cs +++ b/osu.Game/Storyboards/Drawables/IVectorScalable.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osuTK; diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 9a059991e6..7e83f8b692 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; namespace osu.Game.Storyboards diff --git a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs index 55f163ee07..c8daeb3b3d 100644 --- a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Storyboards { /// diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 1d21b5dce2..f30c3f7f94 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Storyboards/StoryboardAnimation.cs b/osu.Game/Storyboards/StoryboardAnimation.cs index 1a4b6bb923..16deac8e9e 100644 --- a/osu.Game/Storyboards/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/StoryboardAnimation.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Storyboards/StoryboardExtensions.cs b/osu.Game/Storyboards/StoryboardExtensions.cs index 4e8251c9e7..e5cafc152b 100644 --- a/osu.Game/Storyboards/StoryboardExtensions.cs +++ b/osu.Game/Storyboards/StoryboardExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osuTK; diff --git a/osu.Game/Storyboards/StoryboardLayer.cs b/osu.Game/Storyboards/StoryboardLayer.cs index fa9d4ebfea..2ab8d9fc2a 100644 --- a/osu.Game/Storyboards/StoryboardLayer.cs +++ b/osu.Game/Storyboards/StoryboardLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Storyboards.Drawables; using System.Collections.Generic; diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 5d6ce215f5..752d086993 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Audio; diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index ebd1a941a8..a759482b5d 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; @@ -107,20 +109,20 @@ namespace osu.Game.Storyboards generateCommands(generated, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); generateCommands(generated, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); generateCommands(generated, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - generateCommands(generated, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), + generateCommands(generated, getCommands(g => g.BlendingParameters, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, _) => d.TransformBlendingMode(value, duration), false); if (drawable is IVectorScalable vectorScalable) { - generateCommands(generated, getCommands(g => g.VectorScale, triggeredGroups), (d, value) => vectorScalable.VectorScale = value, - (d, value, duration, easing) => vectorScalable.VectorScaleTo(value, duration, easing)); + generateCommands(generated, getCommands(g => g.VectorScale, triggeredGroups), (_, value) => vectorScalable.VectorScale = value, + (_, value, duration, easing) => vectorScalable.VectorScaleTo(value, duration, easing)); } if (drawable is IFlippable flippable) { - generateCommands(generated, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), + generateCommands(generated, getCommands(g => g.FlipH, triggeredGroups), (_, value) => flippable.FlipH = value, (_, value, duration, _) => flippable.TransformFlipH(value, duration), false); - generateCommands(generated, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), + generateCommands(generated, getCommands(g => g.FlipV, triggeredGroups), (_, value) => flippable.FlipV = value, (_, value, duration, _) => flippable.TransformFlipV(value, duration), false); } diff --git a/osu.Game/Storyboards/StoryboardVideo.cs b/osu.Game/Storyboards/StoryboardVideo.cs index 4652e45852..04ff941397 100644 --- a/osu.Game/Storyboards/StoryboardVideo.cs +++ b/osu.Game/Storyboards/StoryboardVideo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Storyboards/StoryboardVideoLayer.cs b/osu.Game/Storyboards/StoryboardVideoLayer.cs index 2a01c2274a..339e70d677 100644 --- a/osu.Game/Storyboards/StoryboardVideoLayer.cs +++ b/osu.Game/Storyboards/StoryboardVideoLayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; using osuTK; diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 8d622955b7..c5f6f58b86 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs index ed00c7959b..c7441f68bd 100644 --- a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs +++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.IO; using System.Reflection; diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs index 4667a385b3..3ed3bb65c9 100644 --- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs +++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index 597c5e9a2b..06600c4681 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs index b7803f3420..921a039065 100644 --- a/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index ff670e1232..1aa99ceed9 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Diagnostics; using System.IO; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 19974701db..2306fd1c3e 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.IO; using osu.Framework.Audio; using osu.Framework.Audio.Track; diff --git a/osu.Game/Tests/CleanRunHeadlessGameHost.cs b/osu.Game/Tests/CleanRunHeadlessGameHost.cs index bdb171c528..02d67de5a5 100644 --- a/osu.Game/Tests/CleanRunHeadlessGameHost.cs +++ b/osu.Game/Tests/CleanRunHeadlessGameHost.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Runtime.CompilerServices; using osu.Framework; @@ -13,30 +15,38 @@ namespace osu.Game.Tests /// public class CleanRunHeadlessGameHost : TestRunHeadlessGameHost { + private readonly bool bypassCleanupOnSetup; + /// /// Create a new instance. /// /// Whether to bind IPC channels. /// Whether the host should be forced to run in realtime, rather than accelerated test time. - /// Whether to bypass directory cleanup on host disposal. Should be used only if a subsequent test relies on the files still existing. + /// Whether to bypass directory cleanup on . + /// Whether to bypass directory cleanup on host disposal. Should be used only if a subsequent test relies on the files still existing. /// The name of the calling method, used for test file isolation and clean-up. - public CleanRunHeadlessGameHost(bool bindIPC = false, bool realtime = true, bool bypassCleanup = false, [CallerMemberName] string callingMethodName = @"") + public CleanRunHeadlessGameHost(bool bindIPC = false, bool realtime = true, bool bypassCleanupOnSetup = false, bool bypassCleanupOnDispose = false, + [CallerMemberName] string callingMethodName = @"") : base($"{callingMethodName}-{Guid.NewGuid()}", new HostOptions { BindIPC = bindIPC, - }, bypassCleanup: bypassCleanup, realtime: realtime) + }, bypassCleanup: bypassCleanupOnDispose, realtime: realtime) { + this.bypassCleanupOnSetup = bypassCleanupOnSetup; } protected override void SetupForRun() { - try + if (!bypassCleanupOnSetup) { - Storage.DeleteDirectory(string.Empty); - } - catch - { - // May fail if a logging target has already been set via OsuStorage.ChangeTargetStorage. + try + { + Storage.DeleteDirectory(string.Empty); + } + catch + { + // May fail if a logging target has already been set via OsuStorage.ChangeTargetStorage. + } } // base call needs to be run *after* storage is emptied, as it updates the (static) logger's storage and may start writing diff --git a/osu.Game/Tests/FlakyTestAttribute.cs b/osu.Game/Tests/FlakyTestAttribute.cs new file mode 100644 index 0000000000..c61ce80bf5 --- /dev/null +++ b/osu.Game/Tests/FlakyTestAttribute.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 System; +using NUnit.Framework; + +namespace osu.Game.Tests +{ + /// + /// An attribute to mark any flaky tests. + /// Will add a retry count unless environment variable `FAIL_FLAKY_TESTS` is set to `1`. + /// + public class FlakyTestAttribute : RetryAttribute + { + public FlakyTestAttribute() + : this(10) + { + } + + public FlakyTestAttribute(int tryCount) + : base(Environment.GetEnvironmentVariable("OSU_TESTS_FAIL_FLAKY") == "1" ? 1 : tryCount) + { + } + } +} diff --git a/osu.Game/Tests/Gameplay/TestGameplayState.cs b/osu.Game/Tests/Gameplay/TestGameplayState.cs index f14f8c44ec..bb82335543 100644 --- a/osu.Game/Tests/Gameplay/TestGameplayState.cs +++ b/osu.Game/Tests/Gameplay/TestGameplayState.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System.Collections.Generic; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Tests/OsuTestBrowser.cs b/osu.Game/Tests/OsuTestBrowser.cs index 71b0b02fa6..064fdeee94 100644 --- a/osu.Game/Tests/OsuTestBrowser.cs +++ b/osu.Game/Tests/OsuTestBrowser.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Framework.Screens; diff --git a/osu.Game/Tests/Rulesets/TestRulesetConfigCache.cs b/osu.Game/Tests/Rulesets/TestRulesetConfigCache.cs index 537bee6824..a80154c38e 100644 --- a/osu.Game/Tests/Rulesets/TestRulesetConfigCache.cs +++ b/osu.Game/Tests/Rulesets/TestRulesetConfigCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Concurrent; using osu.Game.Rulesets; using osu.Game.Rulesets.Configuration; diff --git a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs index d1290fc5ac..8d9108f376 100644 --- a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs +++ b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs index 15e4fc4d8f..91284ae499 100644 --- a/osu.Game/Tests/Visual/EditorClockTestScene.cs +++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; diff --git a/osu.Game/Tests/Visual/EditorSavingTestScene.cs b/osu.Game/Tests/Visual/EditorSavingTestScene.cs index cc39ead1de..3b7b6780b1 100644 --- a/osu.Game/Tests/Visual/EditorSavingTestScene.cs +++ b/osu.Game/Tests/Visual/EditorSavingTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Input; using osu.Framework.Testing; diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 46f31ae53b..31036247ab 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -15,9 +17,7 @@ using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Dialog; using osu.Game.Rulesets; -using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit; -using osu.Game.Screens.Edit.Compose.Components.Timeline; using osu.Game.Screens.Menu; using osu.Game.Skinning; @@ -56,15 +56,13 @@ namespace osu.Game.Tests.Visual Dependencies.CacheAs(testBeatmapManager = new TestBeatmapManager(LocalStorage, Realm, rulesets, null, audio, Resources, host, Beatmap.Default)); } - protected virtual bool EditorComponentsReady => Editor.ChildrenOfType().FirstOrDefault()?.IsLoaded == true - && Editor.ChildrenOfType().FirstOrDefault()?.IsLoaded == true; - public override void SetUpSteps() { base.SetUpSteps(); AddStep("load editor", LoadEditor); - AddUntilStep("wait for editor to load", () => EditorComponentsReady); + AddUntilStep("wait for editor to load", () => Editor?.ReadyForUse == true); + AddUntilStep("wait for beatmap updated", () => !Beatmap.IsDefault); } protected virtual void LoadEditor() @@ -145,11 +143,6 @@ namespace osu.Game.Tests.Visual { } - protected override BeatmapModelManager CreateBeatmapModelManager(Storage storage, RealmAccess realm, RulesetStore rulesets, BeatmapOnlineLookupQueue onlineLookupQueue) - { - return new TestBeatmapModelManager(storage, realm, onlineLookupQueue); - } - protected override WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap defaultBeatmap, GameHost host) { return new TestWorkingBeatmapCache(this, audioManager, resources, storage, defaultBeatmap, host); @@ -181,17 +174,6 @@ namespace osu.Game.Tests.Visual => testBeatmapManager.TestBeatmap; } - internal class TestBeatmapModelManager : BeatmapModelManager - { - public TestBeatmapModelManager(Storage storage, RealmAccess databaseAccess, BeatmapOnlineLookupQueue beatmapOnlineLookupQueue) - : base(databaseAccess, storage, beatmapOnlineLookupQueue) - { - } - - protected override string ComputeHash(BeatmapSetInfo item) - => string.Empty; - } - public override void Save(BeatmapInfo info, IBeatmap beatmapContent, ISkin beatmapSkin = null) { // don't actually care about saving for this context. diff --git a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs index d74be70df8..f6b5d861be 100644 --- a/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs +++ b/osu.Game/Tests/Visual/LegacySkinPlayerTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game/Tests/Visual/ModPerfectTestScene.cs b/osu.Game/Tests/Visual/ModPerfectTestScene.cs index 93b38a149c..f1ad2656cd 100644 --- a/osu.Game/Tests/Visual/ModPerfectTestScene.cs +++ b/osu.Game/Tests/Visual/ModPerfectTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Tests/Visual/ModTestScene.cs b/osu.Game/Tests/Visual/ModTestScene.cs index 2505864d59..28778f1ac3 100644 --- a/osu.Game/Tests/Visual/ModTestScene.cs +++ b/osu.Game/Tests/Visual/ModTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using JetBrains.Annotations; diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs index 62d1c9ceca..0570c4e2f2 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index a26c6f9be9..5ea98bdbb1 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using NUnit.Framework; using osu.Game.Online.Rooms; using osu.Game.Tests.Beatmaps; diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index 6b4e01b673..0f286475bd 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Online.Multiplayer; using osu.Game.Online.Spectator; using osu.Game.Screens.OnlinePlay; diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 725499d0e5..19b887eea5 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -1,16 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using MessagePack; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; +using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; @@ -31,7 +31,32 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// The local client's . This is not always equivalent to the server-side room. /// - public new Room? APIRoom => base.APIRoom; + public Room? ClientAPIRoom => base.APIRoom; + + /// + /// The local client's . This is not always equivalent to the server-side room. + /// + public MultiplayerRoom? ClientRoom => base.Room; + + /// + /// The server's . This is always up-to-date. + /// + public Room? ServerAPIRoom { get; private set; } + + /// + /// The server's . This is always up-to-date. + /// + public MultiplayerRoom? ServerRoom { get; private set; } + + [Obsolete] + protected new Room APIRoom => throw new InvalidOperationException($"Accessing the client-side API room via {nameof(TestMultiplayerClient)} is unsafe. " + + $"Use {nameof(ClientAPIRoom)} if this was intended."); + + [Obsolete] + public new MultiplayerRoom Room => throw new InvalidOperationException($"Accessing the client-side room via {nameof(TestMultiplayerClient)} is unsafe. " + + $"Use {nameof(ClientRoom)} if this was intended."); + + public new MultiplayerRoomUser? LocalUser => ServerRoom?.Users.SingleOrDefault(u => u.User?.Id == API.LocalUser.Value.Id); public Action? RoomSetupAction; @@ -42,17 +67,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private readonly TestMultiplayerRoomManager roomManager; - /// - /// Guaranteed up-to-date playlist. - /// - private readonly List serverSidePlaylist = new List(); - - /// - /// Guaranteed up-to-date API room. - /// - private Room? serverSideAPIRoom; - - private MultiplayerPlaylistItem? currentItem => Room?.Playlist[currentIndex]; + private MultiplayerPlaylistItem? currentItem => ServerRoom?.Playlist[currentIndex]; private int currentIndex; private long lastPlaylistItemId; @@ -81,158 +96,163 @@ namespace osu.Game.Tests.Visual.Multiplayer private void addUser(MultiplayerRoomUser user) { - ((IMultiplayerClient)this).UserJoined(user).WaitSafely(); + Debug.Assert(ServerRoom != null); - // We want the user to be immediately available for testing, so force a scheduler update to run the update-bound continuation. - Scheduler.Update(); + ServerRoom.Users.Add(user); + ((IMultiplayerClient)this).UserJoined(clone(user)).WaitSafely(); - switch (Room?.MatchState) + switch (ServerRoom?.MatchState) { case TeamVersusRoomState teamVersus: - Debug.Assert(Room != null); - // simulate the server's automatic assignment of users to teams on join. // the "best" team is the one with the least users on it. int bestTeam = teamVersus.Teams - .Select(team => (teamID: team.ID, userCount: Room.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))) + .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))) .OrderBy(pair => pair.userCount) .First().teamID; - ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, new TeamVersusUserState { TeamID = bestTeam }).WaitSafely(); + + user.MatchState = new TeamVersusUserState { TeamID = bestTeam }; + ((IMultiplayerClient)this).MatchUserStateChanged(clone(user.UserID), clone(user.MatchState)).WaitSafely(); break; } } public void RemoveUser(APIUser user) { - Debug.Assert(Room != null); - ((IMultiplayerClient)this).UserLeft(new MultiplayerRoomUser(user.Id)); + Debug.Assert(ServerRoom != null); - Schedule(() => - { - if (Room.Users.Any()) - TransferHost(Room.Users.First().UserID); - }); + ServerRoom.Users.Remove(ServerRoom.Users.Single(u => u.UserID == user.Id)); + ((IMultiplayerClient)this).UserLeft(clone(new MultiplayerRoomUser(user.Id))); + + if (ServerRoom.Users.Any()) + TransferHost(ServerRoom.Users.First().UserID); } public void ChangeRoomState(MultiplayerRoomState newState) { - Debug.Assert(Room != null); - ((IMultiplayerClient)this).RoomStateChanged(newState); + Debug.Assert(ServerRoom != null); + + ServerRoom.State = clone(newState); + + ((IMultiplayerClient)this).RoomStateChanged(clone(ServerRoom.State)); } public void ChangeUserState(int userId, MultiplayerUserState newState) { - Debug.Assert(Room != null); + Debug.Assert(ServerRoom != null); + + var user = ServerRoom.Users.Single(u => u.UserID == userId); + user.State = clone(newState); + + ((IMultiplayerClient)this).UserStateChanged(clone(userId), clone(user.State)); - ((IMultiplayerClient)this).UserStateChanged(userId, newState); updateRoomStateIfRequired(); } private void updateRoomStateIfRequired() { - Debug.Assert(Room != null); - Debug.Assert(APIRoom != null); + Debug.Assert(ServerRoom != null); - Schedule(() => + switch (ServerRoom.State) { - switch (Room.State) - { - case MultiplayerRoomState.Open: - break; + case MultiplayerRoomState.Open: + break; - case MultiplayerRoomState.WaitingForLoad: - if (Room.Users.All(u => u.State != MultiplayerUserState.WaitingForLoad)) + case MultiplayerRoomState.WaitingForLoad: + if (ServerRoom.Users.All(u => u.State != MultiplayerUserState.WaitingForLoad)) + { + var loadedUsers = ServerRoom.Users.Where(u => u.State == MultiplayerUserState.Loaded).ToArray(); + + if (loadedUsers.Length == 0) { - var loadedUsers = Room.Users.Where(u => u.State == MultiplayerUserState.Loaded).ToArray(); - - if (loadedUsers.Length == 0) - { - // all users have bailed from the load sequence. cancel the game start. - ChangeRoomState(MultiplayerRoomState.Open); - return; - } - - foreach (var u in Room.Users.Where(u => u.State == MultiplayerUserState.Loaded)) - ChangeUserState(u.UserID, MultiplayerUserState.Playing); - - ((IMultiplayerClient)this).GameplayStarted(); - - ChangeRoomState(MultiplayerRoomState.Playing); - } - - break; - - case MultiplayerRoomState.Playing: - if (Room.Users.All(u => u.State != MultiplayerUserState.Playing)) - { - foreach (var u in Room.Users.Where(u => u.State == MultiplayerUserState.FinishedPlay)) - ChangeUserState(u.UserID, MultiplayerUserState.Results); - + // all users have bailed from the load sequence. cancel the game start. ChangeRoomState(MultiplayerRoomState.Open); - ((IMultiplayerClient)this).ResultsReady(); - - FinishCurrentItem().WaitSafely(); + return; } - break; - } - }); + foreach (var u in ServerRoom.Users.Where(u => u.State == MultiplayerUserState.Loaded)) + ChangeUserState(u.UserID, MultiplayerUserState.Playing); + + ((IMultiplayerClient)this).GameplayStarted(); + + ChangeRoomState(MultiplayerRoomState.Playing); + } + + break; + + case MultiplayerRoomState.Playing: + if (ServerRoom.Users.All(u => u.State != MultiplayerUserState.Playing)) + { + foreach (var u in ServerRoom.Users.Where(u => u.State == MultiplayerUserState.FinishedPlay)) + ChangeUserState(u.UserID, MultiplayerUserState.Results); + + ChangeRoomState(MultiplayerRoomState.Open); + ((IMultiplayerClient)this).ResultsReady(); + + FinishCurrentItem().WaitSafely(); + } + + break; + } } public void ChangeUserBeatmapAvailability(int userId, BeatmapAvailability newBeatmapAvailability) { - Debug.Assert(Room != null); + Debug.Assert(ServerRoom != null); - ((IMultiplayerClient)this).UserBeatmapAvailabilityChanged(userId, newBeatmapAvailability); + var user = ServerRoom.Users.Single(u => u.UserID == userId); + user.BeatmapAvailability = newBeatmapAvailability; + + ((IMultiplayerClient)this).UserBeatmapAvailabilityChanged(clone(userId), clone(user.BeatmapAvailability)); } protected override async Task JoinRoom(long roomId, string? password = null) { - serverSideAPIRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == roomId); + roomId = clone(roomId); + password = clone(password); - if (password != serverSideAPIRoom.Password.Value) + ServerAPIRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == roomId); + + if (password != ServerAPIRoom.Password.Value) throw new InvalidOperationException("Invalid password."); - serverSidePlaylist.Clear(); - serverSidePlaylist.AddRange(serverSideAPIRoom.Playlist.Select(item => new MultiplayerPlaylistItem(item))); - lastPlaylistItemId = serverSidePlaylist.Max(item => item.ID); + lastPlaylistItemId = ServerAPIRoom.Playlist.Max(item => item.ID); var localUser = new MultiplayerRoomUser(api.LocalUser.Value.Id) { User = api.LocalUser.Value }; - var room = new MultiplayerRoom(roomId) + ServerRoom = new MultiplayerRoom(roomId) { Settings = { - Name = serverSideAPIRoom.Name.Value, - MatchType = serverSideAPIRoom.Type.Value, + Name = ServerAPIRoom.Name.Value, + MatchType = ServerAPIRoom.Type.Value, Password = password, - QueueMode = serverSideAPIRoom.QueueMode.Value, - AutoStartDuration = serverSideAPIRoom.AutoStartDuration.Value + QueueMode = ServerAPIRoom.QueueMode.Value, + AutoStartDuration = ServerAPIRoom.AutoStartDuration.Value }, - Playlist = serverSidePlaylist.ToList(), + Playlist = ServerAPIRoom.Playlist.Select(item => new MultiplayerPlaylistItem(item)).ToList(), Users = { localUser }, Host = localUser }; - await updatePlaylistOrder(room).ConfigureAwait(false); - await updateCurrentItem(room, false).ConfigureAwait(false); + await updatePlaylistOrder(ServerRoom).ConfigureAwait(false); + await updateCurrentItem(ServerRoom, false).ConfigureAwait(false); - RoomSetupAction?.Invoke(room); + RoomSetupAction?.Invoke(ServerRoom); RoomSetupAction = null; - return room; + return clone(ServerRoom); } protected override void OnRoomJoined() { - Debug.Assert(APIRoom != null); - Debug.Assert(Room != null); + Debug.Assert(ServerRoom != null); // emulate the server sending this after the join room. scheduler required to make sure the join room event is fired first (in Join). - changeMatchType(Room.Settings.MatchType).WaitSafely(); + changeMatchType(ServerRoom.Settings.MatchType).WaitSafely(); RoomJoined = true; } @@ -243,29 +263,45 @@ namespace osu.Game.Tests.Visual.Multiplayer return Task.CompletedTask; } - public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId); + public override Task TransferHost(int userId) + { + userId = clone(userId); + + Debug.Assert(ServerRoom != null); + + ServerRoom.Host = ServerRoom.Users.Single(u => u.UserID == userId); + + return ((IMultiplayerClient)this).HostChanged(clone(userId)); + } public override Task KickUser(int userId) { - Debug.Assert(Room != null); + userId = clone(userId); - return ((IMultiplayerClient)this).UserKicked(Room.Users.Single(u => u.UserID == userId)); + Debug.Assert(ServerRoom != null); + + var user = ServerRoom.Users.Single(u => u.UserID == userId); + ServerRoom.Users.Remove(user); + + return ((IMultiplayerClient)this).UserKicked(clone(user)); } public override async Task ChangeSettings(MultiplayerRoomSettings settings) { - Debug.Assert(Room != null); - Debug.Assert(APIRoom != null); + settings = clone(settings); + + Debug.Assert(ServerRoom != null); Debug.Assert(currentItem != null); // Server is authoritative for the time being. - settings.PlaylistItemId = Room.Settings.PlaylistItemId; + settings.PlaylistItemId = ServerRoom.Settings.PlaylistItemId; + ServerRoom.Settings = settings; await changeQueueMode(settings.QueueMode).ConfigureAwait(false); - await ((IMultiplayerClient)this).SettingsChanged(settings).ConfigureAwait(false); + await ((IMultiplayerClient)this).SettingsChanged(clone(settings)).ConfigureAwait(false); - foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready)) + foreach (var user in ServerRoom.Users.Where(u => u.State == MultiplayerUserState.Ready)) ChangeUserState(user.UserID, MultiplayerUserState.Idle); await changeMatchType(settings.MatchType).ConfigureAwait(false); @@ -274,46 +310,52 @@ namespace osu.Game.Tests.Visual.Multiplayer public override Task ChangeState(MultiplayerUserState newState) { - Debug.Assert(Room != null); + newState = clone(newState); if (newState == MultiplayerUserState.Idle && LocalUser?.State == MultiplayerUserState.WaitingForLoad) return Task.CompletedTask; - ChangeUserState(api.LocalUser.Value.Id, newState); + ChangeUserState(api.LocalUser.Value.Id, clone(newState)); return Task.CompletedTask; } public override Task ChangeBeatmapAvailability(BeatmapAvailability newBeatmapAvailability) { - ChangeUserBeatmapAvailability(api.LocalUser.Value.Id, newBeatmapAvailability); + ChangeUserBeatmapAvailability(api.LocalUser.Value.Id, clone(newBeatmapAvailability)); return Task.CompletedTask; } public void ChangeUserMods(int userId, IEnumerable newMods) - => ChangeUserMods(userId, newMods.Select(m => new APIMod(m)).ToList()); + => ChangeUserMods(userId, newMods.Select(m => new APIMod(m))); public void ChangeUserMods(int userId, IEnumerable newMods) { - Debug.Assert(Room != null); - ((IMultiplayerClient)this).UserModsChanged(userId, newMods.ToList()); + Debug.Assert(ServerRoom != null); + + var user = ServerRoom.Users.Single(u => u.UserID == userId); + user.Mods = newMods.ToArray(); + + ((IMultiplayerClient)this).UserModsChanged(clone(userId), clone(user.Mods)); } public override Task ChangeUserMods(IEnumerable newMods) { - ChangeUserMods(api.LocalUser.Value.Id, newMods); + ChangeUserMods(api.LocalUser.Value.Id, clone(newMods)); return Task.CompletedTask; } public override async Task SendMatchRequest(MatchUserRequest request) { - Debug.Assert(Room != null); + request = clone(request); + + Debug.Assert(ServerRoom != null); Debug.Assert(LocalUser != null); switch (request) { case ChangeTeamRequest changeTeam: - TeamVersusRoomState roomState = (TeamVersusRoomState)Room.MatchState!; + TeamVersusRoomState roomState = (TeamVersusRoomState)ServerRoom.MatchState!; TeamVersusUserState userState = (TeamVersusUserState)LocalUser.MatchState!; var targetTeam = roomState.Teams.FirstOrDefault(t => t.ID == changeTeam.TeamID); @@ -322,7 +364,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { userState.TeamID = targetTeam.ID; - await ((IMultiplayerClient)this).MatchUserStateChanged(LocalUser.UserID, userState).ConfigureAwait(false); + await ((IMultiplayerClient)this).MatchUserStateChanged(clone(LocalUser.UserID), clone(userState)).ConfigureAwait(false); } break; @@ -331,10 +373,10 @@ namespace osu.Game.Tests.Visual.Multiplayer public override Task StartMatch() { - Debug.Assert(Room != null); + Debug.Assert(ServerRoom != null); ChangeRoomState(MultiplayerRoomState.WaitingForLoad); - foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready)) + foreach (var user in ServerRoom.Users.Where(u => u.State == MultiplayerUserState.Ready)) ChangeUserState(user.UserID, MultiplayerUserState.WaitingForLoad); return ((IMultiplayerClient)this).LoadRequested(); @@ -342,7 +384,6 @@ namespace osu.Game.Tests.Visual.Multiplayer public override Task AbortGameplay() { - Debug.Assert(Room != null); Debug.Assert(LocalUser != null); ChangeUserState(LocalUser.UserID, MultiplayerUserState.Idle); @@ -352,36 +393,35 @@ namespace osu.Game.Tests.Visual.Multiplayer public async Task AddUserPlaylistItem(int userId, MultiplayerPlaylistItem item) { - Debug.Assert(Room != null); - Debug.Assert(APIRoom != null); + Debug.Assert(ServerRoom != null); Debug.Assert(currentItem != null); - if (Room.Settings.QueueMode == QueueMode.HostOnly && Room.Host?.UserID != LocalUser?.UserID) + if (ServerRoom.Settings.QueueMode == QueueMode.HostOnly && ServerRoom.Host?.UserID != LocalUser?.UserID) throw new InvalidOperationException("Local user is not the room host."); item.OwnerID = userId; await addItem(item).ConfigureAwait(false); - await updateCurrentItem(Room).ConfigureAwait(false); + await updateCurrentItem(ServerRoom).ConfigureAwait(false); updateRoomStateIfRequired(); } - public override Task AddPlaylistItem(MultiplayerPlaylistItem item) => AddUserPlaylistItem(api.LocalUser.Value.OnlineID, item); + public override Task AddPlaylistItem(MultiplayerPlaylistItem item) => AddUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(item)); public async Task EditUserPlaylistItem(int userId, MultiplayerPlaylistItem item) { - Debug.Assert(Room != null); + Debug.Assert(ServerRoom != null); Debug.Assert(currentItem != null); - Debug.Assert(serverSideAPIRoom != null); + Debug.Assert(ServerAPIRoom != null); item.OwnerID = userId; - var existingItem = serverSidePlaylist.SingleOrDefault(i => i.ID == item.ID); + var existingItem = ServerRoom.Playlist.SingleOrDefault(i => i.ID == item.ID); if (existingItem == null) throw new InvalidOperationException("Attempted to change an item that doesn't exist."); - if (existingItem.OwnerID != userId && Room.Host?.UserID != LocalUser?.UserID) + if (existingItem.OwnerID != userId && ServerRoom.Host?.UserID != LocalUser?.UserID) throw new InvalidOperationException("Attempted to change an item which is not owned by the user."); if (existingItem.Expired) @@ -390,21 +430,20 @@ namespace osu.Game.Tests.Visual.Multiplayer // Ensure the playlist order doesn't change. item.PlaylistOrder = existingItem.PlaylistOrder; - serverSidePlaylist[serverSidePlaylist.IndexOf(existingItem)] = item; - serverSideAPIRoom.Playlist[serverSideAPIRoom.Playlist.IndexOf(serverSideAPIRoom.Playlist.Single(i => i.ID == item.ID))] = new PlaylistItem(item); + ServerRoom.Playlist[ServerRoom.Playlist.IndexOf(existingItem)] = item; + ServerAPIRoom.Playlist[ServerAPIRoom.Playlist.IndexOf(ServerAPIRoom.Playlist.Single(i => i.ID == item.ID))] = new PlaylistItem(item); - await ((IMultiplayerClient)this).PlaylistItemChanged(item).ConfigureAwait(false); + await ((IMultiplayerClient)this).PlaylistItemChanged(clone(item)).ConfigureAwait(false); } - public override Task EditPlaylistItem(MultiplayerPlaylistItem item) => EditUserPlaylistItem(api.LocalUser.Value.OnlineID, item); + public override Task EditPlaylistItem(MultiplayerPlaylistItem item) => EditUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(item)); public async Task RemoveUserPlaylistItem(int userId, long playlistItemId) { - Debug.Assert(Room != null); - Debug.Assert(APIRoom != null); - Debug.Assert(serverSideAPIRoom != null); + Debug.Assert(ServerRoom != null); + Debug.Assert(ServerAPIRoom != null); - var item = serverSidePlaylist.Find(i => i.ID == playlistItemId); + var item = ServerRoom.Playlist.FirstOrDefault(i => i.ID == playlistItemId); if (item == null) throw new InvalidOperationException("Item does not exist in the room."); @@ -418,70 +457,78 @@ namespace osu.Game.Tests.Visual.Multiplayer if (item.Expired) throw new InvalidOperationException("Attempted to remove an item which has already been played."); - serverSidePlaylist.Remove(item); - serverSideAPIRoom.Playlist.RemoveAll(i => i.ID == item.ID); - await ((IMultiplayerClient)this).PlaylistItemRemoved(playlistItemId).ConfigureAwait(false); + ServerRoom.Playlist.Remove(item); + ServerAPIRoom.Playlist.RemoveAll(i => i.ID == item.ID); + await ((IMultiplayerClient)this).PlaylistItemRemoved(clone(playlistItemId)).ConfigureAwait(false); - await updateCurrentItem(Room).ConfigureAwait(false); + await updateCurrentItem(ServerRoom).ConfigureAwait(false); updateRoomStateIfRequired(); } - public override Task RemovePlaylistItem(long playlistItemId) => RemoveUserPlaylistItem(api.LocalUser.Value.OnlineID, playlistItemId); + public override Task RemovePlaylistItem(long playlistItemId) => RemoveUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(playlistItemId)); private async Task changeMatchType(MatchType type) { - Debug.Assert(Room != null); + Debug.Assert(ServerRoom != null); switch (type) { case MatchType.HeadToHead: - await ((IMultiplayerClient)this).MatchRoomStateChanged(null).ConfigureAwait(false); + ServerRoom.MatchState = null; + await ((IMultiplayerClient)this).MatchRoomStateChanged(clone(ServerRoom.MatchState)).ConfigureAwait(false); + + foreach (var user in ServerRoom.Users) + { + user.MatchState = null; + await ((IMultiplayerClient)this).MatchUserStateChanged(clone(user.UserID), clone(user.MatchState)).ConfigureAwait(false); + } - foreach (var user in Room.Users) - await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, null).ConfigureAwait(false); break; case MatchType.TeamVersus: - await ((IMultiplayerClient)this).MatchRoomStateChanged(TeamVersusRoomState.CreateDefault()).ConfigureAwait(false); + ServerRoom.MatchState = TeamVersusRoomState.CreateDefault(); + await ((IMultiplayerClient)this).MatchRoomStateChanged(clone(ServerRoom.MatchState)).ConfigureAwait(false); + + foreach (var user in ServerRoom.Users) + { + user.MatchState = new TeamVersusUserState(); + await ((IMultiplayerClient)this).MatchUserStateChanged(clone(user.UserID), clone(user.MatchState)).ConfigureAwait(false); + } - foreach (var user in Room.Users) - await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, new TeamVersusUserState()).ConfigureAwait(false); break; } } private async Task changeQueueMode(QueueMode newMode) { - Debug.Assert(Room != null); - Debug.Assert(APIRoom != null); + Debug.Assert(ServerRoom != null); Debug.Assert(currentItem != null); // When changing to host-only mode, ensure that at least one non-expired playlist item exists by duplicating the current item. - if (newMode == QueueMode.HostOnly && serverSidePlaylist.All(item => item.Expired)) + if (newMode == QueueMode.HostOnly && ServerRoom.Playlist.All(item => item.Expired)) await duplicateCurrentItem().ConfigureAwait(false); - await updatePlaylistOrder(Room).ConfigureAwait(false); - await updateCurrentItem(Room).ConfigureAwait(false); + await updatePlaylistOrder(ServerRoom).ConfigureAwait(false); + await updateCurrentItem(ServerRoom).ConfigureAwait(false); } public async Task FinishCurrentItem() { - Debug.Assert(Room != null); - Debug.Assert(APIRoom != null); + Debug.Assert(ServerRoom != null); Debug.Assert(currentItem != null); // Expire the current playlist item. currentItem.Expired = true; currentItem.PlayedAt = DateTimeOffset.Now; - await ((IMultiplayerClient)this).PlaylistItemChanged(currentItem).ConfigureAwait(false); - await updatePlaylistOrder(Room).ConfigureAwait(false); + await ((IMultiplayerClient)this).PlaylistItemChanged(clone(currentItem)).ConfigureAwait(false); + await updatePlaylistOrder(ServerRoom).ConfigureAwait(false); // In host-only mode, a duplicate playlist item will be used for the next round. - if (Room.Settings.QueueMode == QueueMode.HostOnly && serverSidePlaylist.All(item => item.Expired)) + if (ServerRoom.Settings.QueueMode == QueueMode.HostOnly && ServerRoom.Playlist.All(item => item.Expired)) await duplicateCurrentItem().ConfigureAwait(false); - await updateCurrentItem(Room).ConfigureAwait(false); + await updateCurrentItem(ServerRoom).ConfigureAwait(false); } private async Task duplicateCurrentItem() @@ -500,51 +547,54 @@ namespace osu.Game.Tests.Visual.Multiplayer private async Task addItem(MultiplayerPlaylistItem item) { - Debug.Assert(Room != null); - Debug.Assert(serverSideAPIRoom != null); + Debug.Assert(ServerRoom != null); + Debug.Assert(ServerAPIRoom != null); item.ID = ++lastPlaylistItemId; - serverSidePlaylist.Add(item); - serverSideAPIRoom.Playlist.Add(new PlaylistItem(item)); - await ((IMultiplayerClient)this).PlaylistItemAdded(item).ConfigureAwait(false); + ServerRoom.Playlist.Add(item); + ServerAPIRoom.Playlist.Add(new PlaylistItem(item)); + await ((IMultiplayerClient)this).PlaylistItemAdded(clone(item)).ConfigureAwait(false); - await updatePlaylistOrder(Room).ConfigureAwait(false); + await updatePlaylistOrder(ServerRoom).ConfigureAwait(false); } - private IEnumerable upcomingItems => serverSidePlaylist.Where(i => !i.Expired).OrderBy(i => i.PlaylistOrder); + private IEnumerable upcomingItems => ServerRoom?.Playlist.Where(i => !i.Expired).OrderBy(i => i.PlaylistOrder) ?? Enumerable.Empty(); private async Task updateCurrentItem(MultiplayerRoom room, bool notify = true) { - // Pick the next non-expired playlist item by playlist order, or default to the most-recently-expired item. - MultiplayerPlaylistItem nextItem = upcomingItems.FirstOrDefault() ?? serverSidePlaylist.OrderByDescending(i => i.PlayedAt).First(); + Debug.Assert(ServerRoom != null); - currentIndex = serverSidePlaylist.IndexOf(nextItem); + // Pick the next non-expired playlist item by playlist order, or default to the most-recently-expired item. + MultiplayerPlaylistItem nextItem = upcomingItems.FirstOrDefault() ?? ServerRoom.Playlist.OrderByDescending(i => i.PlayedAt).First(); + + currentIndex = ServerRoom.Playlist.IndexOf(nextItem); long lastItem = room.Settings.PlaylistItemId; room.Settings.PlaylistItemId = nextItem.ID; if (notify && nextItem.ID != lastItem) - await ((IMultiplayerClient)this).SettingsChanged(room.Settings).ConfigureAwait(false); + await ((IMultiplayerClient)this).SettingsChanged(clone(room.Settings)).ConfigureAwait(false); } private async Task updatePlaylistOrder(MultiplayerRoom room) { - Debug.Assert(serverSideAPIRoom != null); + Debug.Assert(ServerRoom != null); + Debug.Assert(ServerAPIRoom != null); List orderedActiveItems; switch (room.Settings.QueueMode) { default: - orderedActiveItems = serverSidePlaylist.Where(item => !item.Expired).OrderBy(item => item.ID).ToList(); + orderedActiveItems = ServerRoom.Playlist.Where(item => !item.Expired).OrderBy(item => item.ID).ToList(); break; case QueueMode.AllPlayersRoundRobin: var itemsByPriority = new List<(MultiplayerPlaylistItem item, int priority)>(); // Assign a priority for items from each user, starting from 0 and increasing in order which the user added the items. - foreach (var group in serverSidePlaylist.Where(item => !item.Expired).OrderBy(item => item.ID).GroupBy(item => item.OwnerID)) + foreach (var group in ServerRoom.Playlist.Where(item => !item.Expired).OrderBy(item => item.ID).GroupBy(item => item.OwnerID)) { int priority = 0; itemsByPriority.AddRange(group.Select(item => (item, priority++))); @@ -575,12 +625,18 @@ namespace osu.Game.Tests.Visual.Multiplayer item.PlaylistOrder = (ushort)i; - await ((IMultiplayerClient)this).PlaylistItemChanged(item).ConfigureAwait(false); + await ((IMultiplayerClient)this).PlaylistItemChanged(clone(item)).ConfigureAwait(false); } // Also ensure that the API room's playlist is correct. - foreach (var item in serverSideAPIRoom.Playlist) - item.PlaylistOrder = serverSidePlaylist.Single(i => i.ID == item.ID).PlaylistOrder; + foreach (var item in ServerAPIRoom.Playlist) + item.PlaylistOrder = ServerRoom.Playlist.Single(i => i.ID == item.ID).PlaylistOrder; + } + + private T clone(T incoming) + { + byte[]? serialized = MessagePackSerializer.Serialize(typeof(T), incoming, SignalRUnionWorkaroundResolver.OPTIONS); + return MessagePackSerializer.Deserialize(serialized, SignalRUnionWorkaroundResolver.OPTIONS); } } } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs index 296db3152d..b2283af9e7 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index c94e288e11..12d1846ece 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Bindables; using osu.Game.Database; using osu.Game.Online.Rooms; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs index df3974664e..6577057c17 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs @@ -1,15 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; -using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; +using osu.Framework.Logging; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay; @@ -70,22 +72,18 @@ namespace osu.Game.Tests.Visual.OnlinePlay ((DummyAPIAccess)API).HandleRequest = request => { - TaskCompletionSource tcs = new TaskCompletionSource(); - - // Because some of the handlers use realm, we need to ensure the game is still alive when firing. - // If we don't, a stray `PerformAsync` could hit an `ObjectDisposedException` if running too late. - Scheduler.Add(() => + try { - bool result = handler.HandleRequest(request, API.LocalUser.Value, beatmapManager); - tcs.SetResult(result); - }, false); - -#pragma warning disable RS0030 - // We can't GetResultSafely() here (will fail with "Can't use GetResultSafely from inside an async operation."), but Wait is safe enough due to - // the task being a TaskCompletionSource. - // Importantly, this doesn't deadlock because of the scheduler call above running inline where feasible (see the `false` argument). - return tcs.Task.Result; -#pragma warning restore RS0030 + return handler.HandleRequest(request, API.LocalUser.Value, beatmapManager); + } + catch (ObjectDisposedException) + { + // These requests can be fired asynchronously, but potentially arrive after game components + // have been disposed (ie. realm in BeatmapManager). + // This only happens in tests and it's easiest to ignore them for now. + Logger.Log($"Handled {nameof(ObjectDisposedException)} in test request handling"); + return true; + } }; }); diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index 7c8bc2d535..35bdba0038 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs index 3de4e7afd9..f905eb26d3 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs index 8fea77833e..fa7ade2c07 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -134,6 +136,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay return true; case GetBeatmapsRequest getBeatmapsRequest: + { var result = new List(); foreach (int id in getBeatmapsRequest.BeatmapIds) @@ -152,6 +155,24 @@ namespace osu.Game.Tests.Visual.OnlinePlay getBeatmapsRequest.TriggerSuccess(new GetBeatmapsResponse { Beatmaps = result }); return true; + } + + case GetBeatmapSetRequest getBeatmapSetRequest: + { + var baseBeatmap = getBeatmapSetRequest.Type == BeatmapSetLookupType.BeatmapId + ? beatmapManager.QueryBeatmap(b => b.OnlineID == getBeatmapSetRequest.ID) + : beatmapManager.QueryBeatmap(b => b.BeatmapSet.OnlineID == getBeatmapSetRequest.ID); + + if (baseBeatmap == null) + { + baseBeatmap = new TestBeatmap(new RulesetInfo { OnlineID = 0 }).BeatmapInfo; + baseBeatmap.OnlineID = getBeatmapSetRequest.ID; + baseBeatmap.BeatmapSet!.OnlineID = getBeatmapSetRequest.ID; + } + + getBeatmapSetRequest.TriggerSuccess(OsuTestScene.CreateAPIBeatmapSet(baseBeatmap)); + return true; + } } return false; diff --git a/osu.Game/Tests/Visual/OsuGameTestScene.cs b/osu.Game/Tests/Visual/OsuGameTestScene.cs index 6e4adb4d4c..b9f6183869 100644 --- a/osu.Game/Tests/Visual/OsuGameTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGameTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using osu.Framework.Allocation; @@ -73,7 +75,7 @@ namespace osu.Game.Tests.Visual } [TearDownSteps] - public void TearDownSteps() + public virtual void TearDownSteps() { if (DebugUtils.IsNUnitRunning && Game != null) { @@ -132,6 +134,8 @@ namespace osu.Game.Tests.Visual public new NotificationOverlay Notifications => base.Notifications; + public new FirstRunSetupOverlay FirstRunOverlay => base.FirstRunOverlay; + public new MusicController MusicController => base.MusicController; public new OsuConfigManager LocalConfig => base.LocalConfig; diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index 48f85be6ba..f9a609f663 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs b/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs index 2deb8686cc..eccd2efa96 100644 --- a/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs +++ b/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 1582bdfca4..012c512266 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -428,11 +430,19 @@ namespace osu.Game.Tests.Visual return accumulated == seek; } + public override Task SeekAsync(double seek) => Task.FromResult(Seek(seek)); + public override void Start() { running = true; } + public override Task StartAsync() + { + Start(); + return Task.CompletedTask; + } + public override void Reset() { Seek(0); @@ -448,6 +458,12 @@ namespace osu.Game.Tests.Visual } } + public override Task StopAsync() + { + Stop(); + return Task.CompletedTask; + } + public override bool IsRunning => running; private double? lastReferenceTime; diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index b981a31bd1..797e8363c3 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/PlayerTestScene.cs b/osu.Game/Tests/Visual/PlayerTestScene.cs index b34f7e2d5f..a9decbae57 100644 --- a/osu.Game/Tests/Visual/PlayerTestScene.cs +++ b/osu.Game/Tests/Visual/PlayerTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using JetBrains.Annotations; @@ -37,17 +39,17 @@ namespace osu.Game.Tests.Visual base.SetUpSteps(); if (!HasCustomSteps) - CreateTest(null); + CreateTest(); } - protected void CreateTest(Action action) + protected void CreateTest([CanBeNull] Action action = null) { if (action != null && !HasCustomSteps) throw new InvalidOperationException($"Cannot add custom test steps without {nameof(HasCustomSteps)} being set."); action?.Invoke(); - AddStep(CreatePlayerRuleset().Description, LoadPlayer); + AddStep($"Load player for {CreatePlayerRuleset().Description}", LoadPlayer); AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); } diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs index 1034f208a9..a4f768800c 100644 --- a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Tests.Visual { /// diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs index 0fa2f3e786..803db07fa0 100644 --- a/osu.Game/Tests/Visual/ScreenTestScene.cs +++ b/osu.Game/Tests/Visual/ScreenTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -47,8 +49,8 @@ namespace osu.Game.Tests.Visual } }); - Stack.ScreenPushed += (lastScreen, newScreen) => Logger.Log($"{nameof(ScreenTestScene)} screen changed → {newScreen}"); - Stack.ScreenExited += (lastScreen, newScreen) => Logger.Log($"{nameof(ScreenTestScene)} screen changed ← {newScreen}"); + Stack.ScreenPushed += (_, newScreen) => Logger.Log($"{nameof(ScreenTestScene)} screen changed → {newScreen}"); + Stack.ScreenExited += (_, newScreen) => Logger.Log($"{nameof(ScreenTestScene)} screen changed ← {newScreen}"); } protected void LoadScreen(OsuScreen screen) => Stack.Push(screen); diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index 994f23577d..cf7fe6e45d 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs index 5448783f6d..66d79cad1c 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Tests/Visual/SkinnableTestScene.cs b/osu.Game/Tests/Visual/SkinnableTestScene.cs index 296ed80e37..2e5d0534f6 100644 --- a/osu.Game/Tests/Visual/SkinnableTestScene.cs +++ b/osu.Game/Tests/Visual/SkinnableTestScene.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Text.RegularExpressions; diff --git a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs index ac7cb43e02..2531f3c485 100644 --- a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs +++ b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics; @@ -136,7 +134,7 @@ namespace osu.Game.Tests.Visual.Spectator FrameSendAttempts++; if (ShouldFailSendingFrames) - return Task.FromException(new InvalidOperationException()); + return Task.FromException(new InvalidOperationException($"Intentional fail via {nameof(ShouldFailSendingFrames)}")); return ((ISpectatorClient)this).UserSentFrames(api.LocalUser.Value.Id, bundle); } diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index 66a956ca3d..e2ddd1734d 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Tests/Visual/TestReplayPlayer.cs b/osu.Game/Tests/Visual/TestReplayPlayer.cs index bacb2427b0..a33a6763af 100644 --- a/osu.Game/Tests/Visual/TestReplayPlayer.cs +++ b/osu.Game/Tests/Visual/TestReplayPlayer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Tests/Visual/TestUserLookupCache.cs b/osu.Game/Tests/Visual/TestUserLookupCache.cs index ce1bbd5f15..414166fdd8 100644 --- a/osu.Game/Tests/Visual/TestUserLookupCache.cs +++ b/osu.Game/Tests/Visual/TestUserLookupCache.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading; using System.Threading.Tasks; using osu.Game.Database; diff --git a/osu.Game/Tests/VisualTestRunner.cs b/osu.Game/Tests/VisualTestRunner.cs index 6aa75ec147..bd98482768 100644 --- a/osu.Game/Tests/VisualTestRunner.cs +++ b/osu.Game/Tests/VisualTestRunner.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework; using osu.Framework.Platform; diff --git a/osu.Game/Updater/GitHubAsset.cs b/osu.Game/Updater/GitHubAsset.cs index 4783161859..a5dfd9e1ac 100644 --- a/osu.Game/Updater/GitHubAsset.cs +++ b/osu.Game/Updater/GitHubAsset.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Updater diff --git a/osu.Game/Updater/GitHubRelease.cs b/osu.Game/Updater/GitHubRelease.cs index 363b2b628f..effabdbc04 100644 --- a/osu.Game/Updater/GitHubRelease.cs +++ b/osu.Game/Updater/GitHubRelease.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Updater/NoActionUpdateManager.cs b/osu.Game/Updater/NoActionUpdateManager.cs index 8f9c4c6f16..8a96cdb968 100644 --- a/osu.Game/Updater/NoActionUpdateManager.cs +++ b/osu.Game/Updater/NoActionUpdateManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs index c57a7c768e..fb5794d92e 100644 --- a/osu.Game/Updater/SimpleUpdateManager.cs +++ b/osu.Game/Updater/SimpleUpdateManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Linq; using System.Runtime.InteropServices; diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs index c17d8304b9..d60f2e4a4b 100644 --- a/osu.Game/Updater/UpdateManager.cs +++ b/osu.Game/Updater/UpdateManager.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Users/Badge.cs b/osu.Game/Users/Badge.cs index 9d46a1992b..c191c25895 100644 --- a/osu.Game/Users/Badge.cs +++ b/osu.Game/Users/Badge.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs deleted file mode 100644 index a9fcd69286..0000000000 --- a/osu.Game/Users/Country.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (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; - -namespace osu.Game.Users -{ - public class Country : IEquatable - { - /// - /// The name of this country. - /// - [JsonProperty(@"name")] - public string FullName; - - /// - /// Two-letter flag acronym (ISO 3166 standard) - /// - [JsonProperty(@"code")] - public string FlagName; - - public bool Equals(Country other) => FlagName == other?.FlagName; - } -} diff --git a/osu.Game/Users/CountryCode.cs b/osu.Game/Users/CountryCode.cs new file mode 100644 index 0000000000..775de2bcf5 --- /dev/null +++ b/osu.Game/Users/CountryCode.cs @@ -0,0 +1,768 @@ +// 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 JetBrains.Annotations; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace osu.Game.Users +{ + [JsonConverter(typeof(StringEnumConverter))] + [UsedImplicitly(ImplicitUseTargetFlags.WithMembers)] + public enum CountryCode + { + [Description("Unknown")] + Unknown = 0, + + [Description("Bangladesh")] + BD, + + [Description("Belgium")] + BE, + + [Description("Burkina Faso")] + BF, + + [Description("Bulgaria")] + BG, + + [Description("Bosnia and Herzegovina")] + BA, + + [Description("Barbados")] + BB, + + [Description("Wallis and Futuna")] + WF, + + [Description("Saint Barthelemy")] + BL, + + [Description("Bermuda")] + BM, + + [Description("Brunei")] + BN, + + [Description("Bolivia")] + BO, + + [Description("Bahrain")] + BH, + + [Description("Burundi")] + BI, + + [Description("Benin")] + BJ, + + [Description("Bhutan")] + BT, + + [Description("Jamaica")] + JM, + + [Description("Bouvet Island")] + BV, + + [Description("Botswana")] + BW, + + [Description("Samoa")] + WS, + + [Description("Bonaire, Saint Eustatius and Saba")] + BQ, + + [Description("Brazil")] + BR, + + [Description("Bahamas")] + BS, + + [Description("Jersey")] + JE, + + [Description("Belarus")] + BY, + + [Description("Belize")] + BZ, + + [Description("Russia")] + RU, + + [Description("Rwanda")] + RW, + + [Description("Serbia")] + RS, + + [Description("East Timor")] + TL, + + [Description("Reunion")] + RE, + + [Description("Turkmenistan")] + TM, + + [Description("Tajikistan")] + TJ, + + [Description("Romania")] + RO, + + [Description("Tokelau")] + TK, + + [Description("Guinea-Bissau")] + GW, + + [Description("Guam")] + GU, + + [Description("Guatemala")] + GT, + + [Description("South Georgia and the South Sandwich Islands")] + GS, + + [Description("Greece")] + GR, + + [Description("Equatorial Guinea")] + GQ, + + [Description("Guadeloupe")] + GP, + + [Description("Japan")] + JP, + + [Description("Guyana")] + GY, + + [Description("Guernsey")] + GG, + + [Description("French Guiana")] + GF, + + [Description("Georgia")] + GE, + + [Description("Grenada")] + GD, + + [Description("United Kingdom")] + GB, + + [Description("Gabon")] + GA, + + [Description("El Salvador")] + SV, + + [Description("Guinea")] + GN, + + [Description("Gambia")] + GM, + + [Description("Greenland")] + GL, + + [Description("Gibraltar")] + GI, + + [Description("Ghana")] + GH, + + [Description("Oman")] + OM, + + [Description("Tunisia")] + TN, + + [Description("Jordan")] + JO, + + [Description("Croatia")] + HR, + + [Description("Haiti")] + HT, + + [Description("Hungary")] + HU, + + [Description("Hong Kong")] + HK, + + [Description("Honduras")] + HN, + + [Description("Heard Island and McDonald Islands")] + HM, + + [Description("Venezuela")] + VE, + + [Description("Puerto Rico")] + PR, + + [Description("Palestinian Territory")] + PS, + + [Description("Palau")] + PW, + + [Description("Portugal")] + PT, + + [Description("Svalbard and Jan Mayen")] + SJ, + + [Description("Paraguay")] + PY, + + [Description("Iraq")] + IQ, + + [Description("Panama")] + PA, + + [Description("French Polynesia")] + PF, + + [Description("Papua New Guinea")] + PG, + + [Description("Peru")] + PE, + + [Description("Pakistan")] + PK, + + [Description("Philippines")] + PH, + + [Description("Pitcairn")] + PN, + + [Description("Poland")] + PL, + + [Description("Saint Pierre and Miquelon")] + PM, + + [Description("Zambia")] + ZM, + + [Description("Western Sahara")] + EH, + + [Description("Estonia")] + EE, + + [Description("Egypt")] + EG, + + [Description("South Africa")] + ZA, + + [Description("Ecuador")] + EC, + + [Description("Italy")] + IT, + + [Description("Vietnam")] + VN, + + [Description("Solomon Islands")] + SB, + + [Description("Ethiopia")] + ET, + + [Description("Somalia")] + SO, + + [Description("Zimbabwe")] + ZW, + + [Description("Saudi Arabia")] + SA, + + [Description("Spain")] + ES, + + [Description("Eritrea")] + ER, + + [Description("Montenegro")] + ME, + + [Description("Moldova")] + MD, + + [Description("Madagascar")] + MG, + + [Description("Saint Martin")] + MF, + + [Description("Morocco")] + MA, + + [Description("Monaco")] + MC, + + [Description("Uzbekistan")] + UZ, + + [Description("Myanmar")] + MM, + + [Description("Mali")] + ML, + + [Description("Macao")] + MO, + + [Description("Mongolia")] + MN, + + [Description("Marshall Islands")] + MH, + + [Description("North Macedonia")] + MK, + + [Description("Mauritius")] + MU, + + [Description("Malta")] + MT, + + [Description("Malawi")] + MW, + + [Description("Maldives")] + MV, + + [Description("Martinique")] + MQ, + + [Description("Northern Mariana Islands")] + MP, + + [Description("Montserrat")] + MS, + + [Description("Mauritania")] + MR, + + [Description("Isle of Man")] + IM, + + [Description("Uganda")] + UG, + + [Description("Tanzania")] + TZ, + + [Description("Malaysia")] + MY, + + [Description("Mexico")] + MX, + + [Description("Israel")] + IL, + + [Description("France")] + FR, + + [Description("British Indian Ocean Territory")] + IO, + + [Description("Saint Helena")] + SH, + + [Description("Finland")] + FI, + + [Description("Fiji")] + FJ, + + [Description("Falkland Islands")] + FK, + + [Description("Micronesia")] + FM, + + [Description("Faroe Islands")] + FO, + + [Description("Nicaragua")] + NI, + + [Description("Netherlands")] + NL, + + [Description("Norway")] + NO, + + [Description("Namibia")] + NA, + + [Description("Vanuatu")] + VU, + + [Description("New Caledonia")] + NC, + + [Description("Niger")] + NE, + + [Description("Norfolk Island")] + NF, + + [Description("Nigeria")] + NG, + + [Description("New Zealand")] + NZ, + + [Description("Nepal")] + NP, + + [Description("Nauru")] + NR, + + [Description("Niue")] + NU, + + [Description("Cook Islands")] + CK, + + [Description("Kosovo")] + XK, + + [Description("Ivory Coast")] + CI, + + [Description("Switzerland")] + CH, + + [Description("Colombia")] + CO, + + [Description("China")] + CN, + + [Description("Cameroon")] + CM, + + [Description("Chile")] + CL, + + [Description("Cocos Islands")] + CC, + + [Description("Canada")] + CA, + + [Description("Republic of the Congo")] + CG, + + [Description("Central African Republic")] + CF, + + [Description("Democratic Republic of the Congo")] + CD, + + [Description("Czech Republic")] + CZ, + + [Description("Cyprus")] + CY, + + [Description("Christmas Island")] + CX, + + [Description("Costa Rica")] + CR, + + [Description("Curacao")] + CW, + + [Description("Cabo Verde")] + CV, + + [Description("Cuba")] + CU, + + [Description("Eswatini")] + SZ, + + [Description("Syria")] + SY, + + [Description("Sint Maarten")] + SX, + + [Description("Kyrgyzstan")] + KG, + + [Description("Kenya")] + KE, + + [Description("South Sudan")] + SS, + + [Description("Suriname")] + SR, + + [Description("Kiribati")] + KI, + + [Description("Cambodia")] + KH, + + [Description("Saint Kitts and Nevis")] + KN, + + [Description("Comoros")] + KM, + + [Description("Sao Tome and Principe")] + ST, + + [Description("Slovakia")] + SK, + + [Description("South Korea")] + KR, + + [Description("Slovenia")] + SI, + + [Description("North Korea")] + KP, + + [Description("Kuwait")] + KW, + + [Description("Senegal")] + SN, + + [Description("San Marino")] + SM, + + [Description("Sierra Leone")] + SL, + + [Description("Seychelles")] + SC, + + [Description("Kazakhstan")] + KZ, + + [Description("Cayman Islands")] + KY, + + [Description("Singapore")] + SG, + + [Description("Sweden")] + SE, + + [Description("Sudan")] + SD, + + [Description("Dominican Republic")] + DO, + + [Description("Dominica")] + DM, + + [Description("Djibouti")] + DJ, + + [Description("Denmark")] + DK, + + [Description("British Virgin Islands")] + VG, + + [Description("Germany")] + DE, + + [Description("Yemen")] + YE, + + [Description("Algeria")] + DZ, + + [Description("United States")] + US, + + [Description("Uruguay")] + UY, + + [Description("Mayotte")] + YT, + + [Description("United States Minor Outlying Islands")] + UM, + + [Description("Lebanon")] + LB, + + [Description("Saint Lucia")] + LC, + + [Description("Laos")] + LA, + + [Description("Tuvalu")] + TV, + + [Description("Taiwan")] + TW, + + [Description("Trinidad and Tobago")] + TT, + + [Description("Turkey")] + TR, + + [Description("Sri Lanka")] + LK, + + [Description("Liechtenstein")] + LI, + + [Description("Latvia")] + LV, + + [Description("Tonga")] + TO, + + [Description("Lithuania")] + LT, + + [Description("Luxembourg")] + LU, + + [Description("Liberia")] + LR, + + [Description("Lesotho")] + LS, + + [Description("Thailand")] + TH, + + [Description("French Southern Territories")] + TF, + + [Description("Togo")] + TG, + + [Description("Chad")] + TD, + + [Description("Turks and Caicos Islands")] + TC, + + [Description("Libya")] + LY, + + [Description("Vatican")] + VA, + + [Description("Saint Vincent and the Grenadines")] + VC, + + [Description("United Arab Emirates")] + AE, + + [Description("Andorra")] + AD, + + [Description("Antigua and Barbuda")] + AG, + + [Description("Afghanistan")] + AF, + + [Description("Anguilla")] + AI, + + [Description("U.S. Virgin Islands")] + VI, + + [Description("Iceland")] + IS, + + [Description("Iran")] + IR, + + [Description("Armenia")] + AM, + + [Description("Albania")] + AL, + + [Description("Angola")] + AO, + + [Description("Antarctica")] + AQ, + + [Description("American Samoa")] + AS, + + [Description("Argentina")] + AR, + + [Description("Australia")] + AU, + + [Description("Austria")] + AT, + + [Description("Aruba")] + AW, + + [Description("India")] + IN, + + [Description("Aland Islands")] + AX, + + [Description("Azerbaijan")] + AZ, + + [Description("Ireland")] + IE, + + [Description("Indonesia")] + ID, + + [Description("Ukraine")] + UA, + + [Description("Qatar")] + QA, + + [Description("Mozambique")] + MZ, + } +} diff --git a/osu.Game/Users/CountryStatistics.cs b/osu.Game/Users/CountryStatistics.cs index 000553c32b..03d455bc04 100644 --- a/osu.Game/Users/CountryStatistics.cs +++ b/osu.Game/Users/CountryStatistics.cs @@ -1,17 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using Newtonsoft.Json; namespace osu.Game.Users { public class CountryStatistics { - [JsonProperty] - public Country Country; - [JsonProperty(@"code")] - public string FlagName; + public CountryCode Code; [JsonProperty(@"active_users")] public long ActiveUsers; diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index d85648c078..62e966c48f 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Users/Drawables/DrawableAvatar.cs b/osu.Game/Users/Drawables/DrawableAvatar.cs index e6d7bb692d..483106d3f4 100644 --- a/osu.Game/Users/Drawables/DrawableAvatar.cs +++ b/osu.Game/Users/Drawables/DrawableAvatar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index aea40a01ae..253835b415 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -1,8 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -12,13 +15,13 @@ namespace osu.Game.Users.Drawables { public class DrawableFlag : Sprite, IHasTooltip { - private readonly Country country; + private readonly CountryCode countryCode; - public LocalisableString TooltipText => country?.FullName; + public LocalisableString TooltipText => countryCode == CountryCode.Unknown ? string.Empty : countryCode.GetDescription(); - public DrawableFlag(Country country) + public DrawableFlag(CountryCode countryCode) { - this.country = country; + this.countryCode = countryCode; } [BackgroundDependencyLoader] @@ -27,7 +30,8 @@ namespace osu.Game.Users.Drawables if (ts == null) throw new ArgumentNullException(nameof(ts)); - Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get(@"Flags/__"); + string textureName = countryCode == CountryCode.Unknown ? "__" : countryCode.ToString(); + Texture = ts.Get($@"Flags/{textureName}") ?? ts.Get(@"Flags/__"); } } } diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 8ce6ce3460..dab3dc59f9 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index d0ef760e59..9b101131b3 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -11,18 +13,18 @@ using osu.Game.Overlays; namespace osu.Game.Users.Drawables { - public class UpdateableFlag : ModelBackedDrawable + public class UpdateableFlag : ModelBackedDrawable { - public Country Country + public CountryCode CountryCode { get => Model; set => Model = value; } /// - /// Whether to show a place holder on null country. + /// Whether to show a place holder on unknown country. /// - public bool ShowPlaceholderOnNull = true; + public bool ShowPlaceholderOnUnknown = true; /// /// Perform an action in addition to showing the country ranking. @@ -30,14 +32,14 @@ namespace osu.Game.Users.Drawables /// public Action Action; - public UpdateableFlag(Country country = null) + public UpdateableFlag(CountryCode countryCode = CountryCode.Unknown) { - Country = country; + CountryCode = countryCode; } - protected override Drawable CreateDrawable(Country country) + protected override Drawable CreateDrawable(CountryCode countryCode) { - if (country == null && !ShowPlaceholderOnNull) + if (countryCode == CountryCode.Unknown && !ShowPlaceholderOnUnknown) return null; return new Container @@ -45,7 +47,7 @@ namespace osu.Game.Users.Drawables RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new DrawableFlag(country) + new DrawableFlag(countryCode) { RelativeSizeAxes = Axes.Both }, @@ -60,7 +62,7 @@ namespace osu.Game.Users.Drawables protected override bool OnClick(ClickEvent e) { Action?.Invoke(); - rankingsOverlay?.ShowCountry(Country); + rankingsOverlay?.ShowCountry(CountryCode); return true; } } diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index d0f693c37c..a4cba8b920 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -51,9 +53,9 @@ namespace osu.Game.Users protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar(User, false); - protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.Country) + protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.CountryCode) { - Size = new Vector2(39, 26), + Size = new Vector2(36, 26), Action = Action, }; diff --git a/osu.Game/Users/IUser.cs b/osu.Game/Users/IUser.cs index d9a352872f..b7f545f68b 100644 --- a/osu.Game/Users/IUser.cs +++ b/osu.Game/Users/IUser.cs @@ -4,14 +4,14 @@ using System; using osu.Game.Database; -#nullable enable - namespace osu.Game.Users { public interface IUser : IHasOnlineID, IEquatable { string Username { get; } + CountryCode CountryCode { get; } + bool IsBot { get; } bool IEquatable.Equals(IUser? other) diff --git a/osu.Game/Users/Medal.cs b/osu.Game/Users/Medal.cs index 2e4f6de1d7..75718e714b 100644 --- a/osu.Game/Users/Medal.cs +++ b/osu.Game/Users/Medal.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + namespace osu.Game.Users { public class Medal diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 2f945d6e1c..6de797ca3a 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.Rooms; diff --git a/osu.Game/Users/UserBrickPanel.cs b/osu.Game/Users/UserBrickPanel.cs index 3debdb6e72..a214b72795 100644 --- a/osu.Game/Users/UserBrickPanel.cs +++ b/osu.Game/Users/UserBrickPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index 3f1f838b27..c799bbb1ea 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index c37eeb1cbf..38d8f6fb33 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Users/UserListPanel.cs b/osu.Game/Users/UserListPanel.cs index f06e412315..6d45481dbe 100644 --- a/osu.Game/Users/UserListPanel.cs +++ b/osu.Game/Users/UserListPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 40d70ca406..d150b38c45 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index f8d26fe421..918a1b6968 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Newtonsoft.Json; using osu.Framework.Localisation; diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 7f275b3b2a..075463c1e0 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Localisation; using osuTK.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Utils/ModUtils.cs b/osu.Game/Utils/ModUtils.cs index ea092a8ca3..edf9cc80da 100644 --- a/osu.Game/Utils/ModUtils.cs +++ b/osu.Game/Utils/ModUtils.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; diff --git a/osu.Game/Utils/Optional.cs b/osu.Game/Utils/Optional.cs index fdb7623be5..301767ba08 100644 --- a/osu.Game/Utils/Optional.cs +++ b/osu.Game/Utils/Optional.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - namespace osu.Game.Utils { /// diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index c12fd607b4..33dc548e9a 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Diagnostics; using System.IO; diff --git a/osu.Game/Utils/TaskChain.cs b/osu.Game/Utils/TaskChain.cs index df28faf9fb..7e7d26aa5d 100644 --- a/osu.Game/Utils/TaskChain.cs +++ b/osu.Game/Utils/TaskChain.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable enable - using System; using System.Threading; using System.Threading.Tasks; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 63b8cf4cb5..4fa4b804ab 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -20,12 +20,12 @@ - + - - - - + + + + @@ -36,10 +36,10 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + diff --git a/osu.iOS.props b/osu.iOS.props index a0fafa635b..dc012ab2fa 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -61,8 +61,8 @@ - - + + @@ -84,8 +84,8 @@ - - + + diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs index 14e3627752..1d29d59fff 100644 --- a/osu.iOS/AppDelegate.cs +++ b/osu.iOS/AppDelegate.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System.Threading.Tasks; using Foundation; using osu.Framework.iOS; diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs index ffabdb4698..c5b2d0b451 100644 --- a/osu.iOS/Application.cs +++ b/osu.iOS/Application.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.iOS; using UIKit; diff --git a/osu.iOS/IOSMouseSettings.cs b/osu.iOS/IOSMouseSettings.cs new file mode 100644 index 0000000000..1979a881f7 --- /dev/null +++ b/osu.iOS/IOSMouseSettings.cs @@ -0,0 +1,36 @@ +// Copyright (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.Localisation; +using osu.Game.Configuration; +using osu.Game.Localisation; +using osu.Game.Overlays.Settings; + +namespace osu.iOS +{ + public class IOSMouseSettings : SettingsSubsection + { + protected override LocalisableString Header => MouseSettingsStrings.Mouse; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager osuConfig) + { + Children = new Drawable[] + { + new SettingsCheckbox + { + LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust, + TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip, + Current = osuConfig.GetBindable(OsuSetting.MouseDisableWheel), + }, + new SettingsCheckbox + { + LabelText = MouseSettingsStrings.DisableMouseButtons, + Current = osuConfig.GetBindable(OsuSetting.MouseDisableButtons), + }, + }; + } + } +} diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index 9c1795e45e..452b573389 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -1,10 +1,15 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using Foundation; using osu.Framework.Graphics; +using osu.Framework.Input.Handlers; +using osu.Framework.iOS.Input; using osu.Game; +using osu.Game.Overlays.Settings; using osu.Game.Updater; using osu.Game.Utils; using Xamarin.Essentials; @@ -24,6 +29,18 @@ namespace osu.iOS // Because we have the home indicator (mostly) hidden we don't really care about drawing in this region. Edges.Bottom; + public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler) + { + switch (handler) + { + case IOSMouseHandler _: + return new IOSMouseSettings(); + + default: + return base.CreateSettingsSubsectionFor(handler); + } + } + private class IOSBatteryInfo : BatteryInfo { public override double ChargeLevel => Battery.ChargeLevel; diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 1203c3659b..b9da874f30 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -23,6 +23,7 @@ + diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 286a1eb29f..b16e309e52 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -7,11 +7,15 @@ ExplicitlyExcluded SOLUTION WARNING + WARNING + WARNING WARNING WARNING HINT HINT WARNING + WARNING + WARNING WARNING True WARNING @@ -59,13 +63,16 @@ HINT HINT WARNING + DO_NOT_SHOW WARNING WARNING WARNING WARNING + DO_NOT_SHOW WARNING WARNING WARNING + DO_NOT_SHOW WARNING WARNING WARNING @@ -91,6 +98,7 @@ WARNING HINT DO_NOT_SHOW + HINT HINT HINT ERROR @@ -118,7 +126,7 @@ WARNING WARNING WARNING - HINT + HINT WARNING WARNING WARNING @@ -126,6 +134,8 @@ HINT HINT WARNING + HINT + HINT HINT HINT HINT @@ -133,6 +143,8 @@ HINT HINT WARNING + HINT + HINT WARNING WARNING WARNING @@ -143,6 +155,7 @@ DO_NOT_SHOW DO_NOT_SHOW DO_NOT_SHOW + WARNING WARNING WARNING WARNING @@ -263,6 +276,7 @@ Explicit ExpressionBody BlockBody + ExplicitlyTyped True NEXT_LINE True @@ -791,10 +805,11 @@ See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> True - True + True True True True + True True True True