From 3b600f0a7b2dda8fa17ba85ee1563526bad44ece Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 20 Nov 2020 10:45:19 +0300 Subject: [PATCH 001/202] Target net5.0 instead of netcoreapp3 --- global.json | 2 +- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/global.json b/global.json index 10b61047ac..2cb4c02970 100644 --- a/global.json +++ b/global.json @@ -2,7 +2,7 @@ "sdk": { "allowPrerelease": false, "rollForward": "minor", - "version": "3.1.100" + "version": "5.0.100" }, "msbuild-sdks": { "Microsoft.Build.Traversal": "2.2.3" diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 62e8f7c518..7f5154f456 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + net5.0 WinExe true A free-to-win rhythm game. Rhythm is just a *click* away! diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index ff26f4afaa..7805bfcefc 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0 Exe false 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 dfe3bf8af4..a51b9830be 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 @@ -9,7 +9,7 @@ WinExe - netcoreapp3.1 + net5.0 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 892f27d27f..d314671bce 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 @@ -9,7 +9,7 @@ WinExe - netcoreapp3.1 + net5.0 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 3639c3616f..b0799bd3f5 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 @@ -9,7 +9,7 @@ WinExe - netcoreapp3.1 + net5.0 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 b59f3a4344..d3dbba4bfc 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 @@ -9,7 +9,7 @@ WinExe - netcoreapp3.1 + net5.0 diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index c692bcd5e4..34de54411b 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -10,7 +10,7 @@ WinExe - netcoreapp3.1 + net5.0 diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 5d55196dcf..d820794980 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -11,7 +11,7 @@ WinExe - netcoreapp3.1 + net5.0 From ca0e1c8cee1ffd03b2bb5fe773741012b90bb654 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 20 Nov 2020 10:47:57 +0300 Subject: [PATCH 002/202] Update NuGet packages --- osu.Desktop/osu.Desktop.csproj | 4 ++-- osu.Game.Tournament/osu.Game.Tournament.csproj | 2 +- osu.Game/osu.Game.csproj | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 7f5154f456..2052c4bc25 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,11 +24,11 @@ - + - + diff --git a/osu.Game.Tournament/osu.Game.Tournament.csproj b/osu.Game.Tournament/osu.Game.Tournament.csproj index 9cce40c9d3..b049542bb0 100644 --- a/osu.Game.Tournament/osu.Game.Tournament.csproj +++ b/osu.Game.Tournament/osu.Game.Tournament.csproj @@ -9,6 +9,6 @@ - + \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 54f3fcede6..1670bf5b11 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -21,8 +21,8 @@ - - + + @@ -31,6 +31,6 @@ - + From f562a7ea0df68baee20551108bb4bd9fd13d5747 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 20 Nov 2020 11:52:17 +0300 Subject: [PATCH 003/202] Fix FileNotFoundException on startup --- osu.Desktop/osu.Desktop.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 2052c4bc25..53b9cdcf92 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,6 +24,8 @@ + + From 044622036cbc94adae124f68ec5fbff18befb2b4 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 20 Nov 2020 11:53:17 +0300 Subject: [PATCH 004/202] Disable CA1416 --- osu.Desktop/OsuGameDesktop.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 0feab9a717..e2a06d7877 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -58,8 +58,10 @@ namespace osu.Desktop try { +#pragma warning disable CA1416 // Validate platform compatibility using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString()?.Split('"')[1].Replace("osu!.exe", ""); +#pragma warning restore CA1416 // Validate platform compatibility if (checkExists(stableInstallPath)) return stableInstallPath; From 1a676ef0d82c4d4cfd0d7fbac2338da3a763272f Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 20 Nov 2020 12:06:08 +0300 Subject: [PATCH 005/202] Resolve CA1416 properly using new API --- osu.Desktop/OsuGameDesktop.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index e2a06d7877..f9c932b260 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.Versioning; using System.Threading.Tasks; using Microsoft.Win32; using osu.Desktop.Overlays; @@ -56,19 +57,12 @@ namespace osu.Desktop string stableInstallPath; - try + if (OperatingSystem.IsWindows()) { -#pragma warning disable CA1416 // Validate platform compatibility - using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString()?.Split('"')[1].Replace("osu!.exe", ""); -#pragma warning restore CA1416 // Validate platform compatibility - + stableInstallPath = getStableInstallPathFromRegistry(); if (checkExists(stableInstallPath)) return stableInstallPath; } - catch - { - } stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); if (checkExists(stableInstallPath)) @@ -81,6 +75,13 @@ namespace osu.Desktop return null; } + [SupportedOSPlatform("windows")] + private string getStableInstallPathFromRegistry() + { + 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() { switch (RuntimeInfo.OS) From 743541649706d9b9165197421860dfd0b3cf264d Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 20 Nov 2020 14:13:16 +0300 Subject: [PATCH 006/202] Workaround FileNotFoundException in a test projects --- osu.Desktop/osu.Desktop.csproj | 2 -- osu.Game/osu.Game.csproj | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 53b9cdcf92..2052c4bc25 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,8 +24,6 @@ - - diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1670bf5b11..1c6139b519 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,6 +18,8 @@ + + From 1feda1152da0b15835af3ce83bed31faf5fbed65 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 21 Nov 2020 02:06:20 +0300 Subject: [PATCH 007/202] Fix InspectCode warnings --- osu.Desktop/OsuGameDesktop.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs | 5 +++++ osu.Game.Tournament/IPC/FileBasedIPC.cs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index f9c932b260..dbbf6d048b 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -79,7 +79,7 @@ namespace osu.Desktop private string getStableInstallPathFromRegistry() { using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString()?.Split('"')[1].Replace("osu!.exe", ""); + return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); } protected override UpdateManager CreateUpdateManager() diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 35473ee76c..58992366ff 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -73,6 +74,8 @@ namespace osu.Game.Tests.Visual.Gameplay switch (args.Action) { case NotifyCollectionChangedAction.Add: + Debug.Assert(args.NewItems != null, "args.NewItems != null"); + foreach (int user in args.NewItems) { if (user == api.LocalUser.Value.Id) @@ -82,6 +85,8 @@ namespace osu.Game.Tests.Visual.Gameplay break; case NotifyCollectionChangedAction.Remove: + Debug.Assert(args.OldItems != null, "args.OldItems != null"); + foreach (int user in args.OldItems) { if (user == api.LocalUser.Value.Id) diff --git a/osu.Game.Tournament/IPC/FileBasedIPC.cs b/osu.Game.Tournament/IPC/FileBasedIPC.cs index 999ce61ac8..99147951b2 100644 --- a/osu.Game.Tournament/IPC/FileBasedIPC.cs +++ b/osu.Game.Tournament/IPC/FileBasedIPC.cs @@ -243,7 +243,7 @@ namespace osu.Game.Tournament.IPC string stableInstallPath; using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) - stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty).ToString().Split('"')[1].Replace("osu!.exe", ""); + stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString().Split('"')[1].Replace("osu!.exe", ""); if (ipcFileExistsInDirectory(stableInstallPath)) return stableInstallPath; From 5d7294451f1a5a24a7eabdf7a738e6fc07278b17 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 16 Dec 2020 14:28:16 +0100 Subject: [PATCH 008/202] Refactor Import() overload to take a list of import tasks instead. --- osu.Android/OsuGameActivity.cs | 3 ++- osu.Game/Database/ArchiveModelManager.cs | 4 ++-- osu.Game/Database/ICanAcceptFiles.cs | 7 ++----- osu.Game/OsuGame.cs | 6 +++--- osu.Game/OsuGameBase.cs | 6 +++--- osu.Game/Screens/Edit/Setup/ResourcesSection.cs | 2 +- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index e801c2ca6e..bd5523f0e2 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -11,6 +11,7 @@ using Android.OS; using Android.Provider; using Android.Views; using osu.Framework.Android; +using osu.Game.Database; namespace osu.Android { @@ -82,7 +83,7 @@ namespace osu.Android using (var stream = ContentResolver.OpenInputStream(uri)) await stream.CopyToAsync(copy); - await game.Import(copy, filename); + await game.Import(new ImportTask(copy, filename)); }, TaskCreationOptions.LongRunning); } } diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 36cc4cce39..9f69ad035f 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -115,13 +115,13 @@ namespace osu.Game.Database return Import(notification, paths.Select(p => new ImportTask(p)).ToArray()); } - public Task Import(Stream stream, string filename) + public Task Import(params ImportTask[] tasks) { var notification = new ProgressNotification { State = ProgressNotificationState.Active }; PostNotification?.Invoke(notification); - return Import(notification, new ImportTask(stream, filename)); + return Import(notification, tasks); } protected async Task> Import(ProgressNotification notification, params ImportTask[] tasks) diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index 276c284c9f..5ec187975a 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.IO; using System.Threading.Tasks; namespace osu.Game.Database @@ -19,11 +18,9 @@ namespace osu.Game.Database Task Import(params string[] paths); /// - /// Import the provided stream as a simple item. + /// Import the specified files from the given import tasks. /// - /// The stream to import files from. Should be in a supported archive format. - /// The filename of the archive being imported. - Task Import(Stream stream, string filename); + Task Import(params ImportTask[] tasks); /// /// An array of accepted file extensions (in the standard format of ".abc"). diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d67d790ce2..1f5b991758 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -52,7 +52,7 @@ using osu.Game.Updater; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; using osu.Game.Users; -using System.IO; +using osu.Game.Database; namespace osu.Game { @@ -427,10 +427,10 @@ namespace osu.Game }, validScreens: new[] { typeof(PlaySongSelect) }); } - public override Task Import(Stream stream, string filename) + public override Task Import(params ImportTask[] imports) { // encapsulate task as we don't want to begin the import process until in a ready state. - var importTask = new Task(async () => await base.Import(stream, filename)); + var importTask = new Task(async () => await base.Import(imports)); waitForReady(() => this, _ => importTask.Start()); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 150569f1dd..0a579cc347 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -395,14 +395,14 @@ namespace osu.Game } } - public virtual async Task Import(Stream stream, string filename) + public virtual async Task Import(params ImportTask[] tasks) { - var extension = Path.GetExtension(filename)?.ToLowerInvariant(); + var extension = Path.GetExtension(tasks.First().Path)?.ToLowerInvariant(); foreach (var importer in fileImporters) { if (importer.HandledExtensions.Contains(extension)) - await importer.Import(stream, Path.GetFileNameWithoutExtension(filename)); + await importer.Import(tasks); } } diff --git a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs index 0c957b80af..fe9b10667a 100644 --- a/osu.Game/Screens/Edit/Setup/ResourcesSection.cs +++ b/osu.Game/Screens/Edit/Setup/ResourcesSection.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Edit.Setup return Task.CompletedTask; } - Task ICanAcceptFiles.Import(Stream stream, string filename) => throw new NotImplementedException(); + Task ICanAcceptFiles.Import(params ImportTask[] tasks) => throw new NotImplementedException(); protected override void LoadComplete() { From 9d8906924580cc3886759de27dbbb05fb5460b00 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 16 Dec 2020 20:33:29 +0100 Subject: [PATCH 009/202] Add ability to import multiple files at once on android. --- osu.Android/OsuGameActivity.cs | 63 ++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index bd5523f0e2..bf73f33b74 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Android.App; using Android.Content; @@ -16,7 +18,7 @@ using osu.Game.Database; namespace osu.Android { [Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.FullUser, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = false)] - [IntentFilter(new[] { Intent.ActionDefault, Intent.ActionSend }, Categories = new[] { Intent.CategoryDefault }, DataPathPatterns = new[] { ".*\\.osz", ".*\\.osk" }, DataMimeType = "application/*")] + [IntentFilter(new[] { Intent.ActionDefault, Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataPathPatterns = new[] { ".*\\.osz", ".*\\.osk" }, DataMimeType = "application/*")] public class OsuGameActivity : AndroidGameActivity { private OsuGameAndroid game; @@ -49,41 +51,64 @@ namespace osu.Android { case Intent.ActionDefault: if (intent.Scheme == ContentResolver.SchemeContent) - handleImportFromUri(intent.Data); + handleImportFromUris(intent.Data); break; case Intent.ActionSend: { var content = intent.ClipData?.GetItemAt(0); if (content != null) - handleImportFromUri(content.Uri); + handleImportFromUris(content.Uri); + break; + } + + case Intent.ActionSendMultiple: + { + var uris = new List(); + for (int i = 0; i < intent.ClipData?.ItemCount; i++) + { + var content = intent.ClipData?.GetItemAt(i); + if (content != null) + uris.Add(content.Uri); + } + handleImportFromUris(uris.ToArray()); break; } } } - private void handleImportFromUri(Uri uri) => Task.Factory.StartNew(async () => + private void handleImportFromUris(params Uri[] uris) => Task.Factory.StartNew(async () => { - // there are more performant overloads of this method, but this one is the most backwards-compatible - // (dates back to API 1). - var cursor = ContentResolver?.Query(uri, null, null, null, null); + var tasks = new List(); - if (cursor == null) - return; + await Task.WhenAll(uris.Select(async uri => + { + // there are more performant overloads of this method, but this one is the most backwards-compatible + // (dates back to API 1). + var cursor = ContentResolver?.Query(uri, null, null, null, null); - cursor.MoveToFirst(); + if (cursor == null) + return; - var filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName); - string filename = cursor.GetString(filenameColumn); + cursor.MoveToFirst(); - // SharpCompress requires archive streams to be seekable, which the stream opened by - // OpenInputStream() seems to not necessarily be. - // copy to an arbitrary-access memory stream to be able to proceed with the import. - var copy = new MemoryStream(); - using (var stream = ContentResolver.OpenInputStream(uri)) - await stream.CopyToAsync(copy); + var filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName); + string filename = cursor.GetString(filenameColumn); - await game.Import(new ImportTask(copy, filename)); + // SharpCompress requires archive streams to be seekable, which the stream opened by + // OpenInputStream() seems to not necessarily be. + // copy to an arbitrary-access memory stream to be able to proceed with the import. + var copy = new MemoryStream(); + using (var stream = ContentResolver.OpenInputStream(uri)) + await stream.CopyToAsync(copy); + + lock (tasks) + { + tasks.Add(new ImportTask(copy, filename)); + } + })); + + await game.Import(tasks.ToArray()); }, TaskCreationOptions.LongRunning); } } From cc0442a9a17880bd6f427638f831f97f6f50cb50 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 16 Dec 2020 20:42:30 +0100 Subject: [PATCH 010/202] Fix CI inspections. --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 0a579cc347..521778a9cd 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -397,7 +397,7 @@ namespace osu.Game public virtual async Task Import(params ImportTask[] tasks) { - var extension = Path.GetExtension(tasks.First().Path)?.ToLowerInvariant(); + var extension = Path.GetExtension(tasks.First().Path).ToLowerInvariant(); foreach (var importer in fileImporters) { From 926281831b85353c1ddf878167abfbbad965a56f Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 19 Dec 2020 10:36:27 +0100 Subject: [PATCH 011/202] Fix missing XMLDoc bit. --- osu.Game/Database/ICanAcceptFiles.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index 5ec187975a..74fd6fcc36 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -20,6 +20,7 @@ namespace osu.Game.Database /// /// Import the specified files from the given import tasks. /// + /// The import tasks from which the files should be imported. Task Import(params ImportTask[] tasks); /// From 4fba0c8e6a3279216294a5a75fa2f79687d0a0c1 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 19 Dec 2020 10:55:39 +0100 Subject: [PATCH 012/202] Remove not used using statement. --- osu.Game/OsuGame.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4ebf7fbe63..e382ff5d48 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -51,7 +51,6 @@ using osu.Game.Screens.Select; using osu.Game.Updater; using osu.Game.Utils; using LogLevel = osu.Framework.Logging.LogLevel; -using osu.Game.Users; using osu.Game.Database; namespace osu.Game From f1aefcdf86a9ef784644614915bd11c1476c9816 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 19 Dec 2020 22:48:39 +0100 Subject: [PATCH 013/202] Handle multiple extensions in the import files. --- osu.Game/OsuGameBase.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 521778a9cd..ca87772209 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -397,13 +397,18 @@ namespace osu.Game public virtual async Task Import(params ImportTask[] tasks) { - var extension = Path.GetExtension(tasks.First().Path).ToLowerInvariant(); + var importTasks = new List(); - foreach (var importer in fileImporters) + foreach (var extension in tasks.Select(t => Path.GetExtension(t.Path)).Distinct()) { - if (importer.HandledExtensions.Contains(extension)) - await importer.Import(tasks); + var importList = tasks.Where(t => t.Path.EndsWith(extension, StringComparison.OrdinalIgnoreCase)); + var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(extension)); + + if (importer != null) + importTasks.Add(importer.Import(importList.ToArray())); } + + await Task.WhenAll(importTasks); } public IEnumerable HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions); From 668f89d8b230103d8daee7fd639fde069baa4d99 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Tue, 22 Dec 2020 17:33:11 +0200 Subject: [PATCH 014/202] Copy test from #11019 --- .../TestSceneSectionsContainer.cs | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs new file mode 100644 index 0000000000..5c2e6e457d --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs @@ -0,0 +1,122 @@ +// 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.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Containers; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneSectionsContainer : OsuManualInputManagerTestScene + { + private readonly SectionsContainer container; + private float custom; + private const float header_height = 100; + + public TestSceneSectionsContainer() + { + container = new SectionsContainer + { + RelativeSizeAxes = Axes.Y, + Width = 300, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + FixedHeader = new Box + { + Alpha = 0.5f, + Width = 300, + Height = header_height, + Colour = Color4.Red + } + }; + container.SelectedSection.ValueChanged += section => + { + if (section.OldValue != null) + section.OldValue.Selected = false; + if (section.NewValue != null) + section.NewValue.Selected = true; + }; + Add(container); + } + + [Test] + public void TestSelection() + { + AddStep("clear", () => container.Clear()); + AddStep("add 1/8th", () => append(1 / 8.0f)); + AddStep("add third", () => append(1 / 3.0f)); + AddStep("add half", () => append(1 / 2.0f)); + AddStep("add full", () => append(1)); + AddSliderStep("set custom", 0.1f, 1.1f, 0.5f, i => custom = i); + AddStep("add custom", () => append(custom)); + AddStep("scroll to previous", () => container.ScrollTo( + container.Children.Reverse().SkipWhile(s => s != container.SelectedSection.Value).Skip(1).FirstOrDefault() ?? container.Children.First() + )); + AddStep("scroll to next", () => container.ScrollTo( + container.Children.SkipWhile(s => s != container.SelectedSection.Value).Skip(1).FirstOrDefault() ?? container.Children.Last() + )); + AddStep("scroll up", () => triggerUserScroll(1)); + AddStep("scroll down", () => triggerUserScroll(-1)); + } + + [Test] + public void TestCorrectSectionSelected() + { + const int sections_count = 11; + float[] alternating = { 0.07f, 0.33f, 0.16f, 0.33f }; + AddStep("clear", () => container.Clear()); + AddStep("fill with sections", () => + { + for (int i = 0; i < sections_count; i++) + append(alternating[i % alternating.Length]); + }); + + void step(int scrollIndex) + { + AddStep($"scroll to section {scrollIndex + 1}", () => container.ScrollTo(container.Children[scrollIndex])); + AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[scrollIndex]); + } + + for (int i = 1; i < sections_count; i++) + step(i); + for (int i = sections_count - 2; i >= 0; i--) + step(i); + + AddStep("scroll almost to end", () => container.ScrollTo(container.Children[sections_count - 2])); + AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[sections_count - 2]); + AddStep("scroll down", () => triggerUserScroll(-1)); + AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[sections_count - 1]); + } + + private static readonly ColourInfo selected_colour = ColourInfo.GradientVertical(Color4.Yellow, Color4.Gold); + private static readonly ColourInfo default_colour = ColourInfo.GradientVertical(Color4.White, Color4.DarkGray); + + private void append(float multiplier) + { + container.Add(new TestSection + { + Width = 300, + Height = (container.ChildSize.Y - header_height) * multiplier, + Colour = default_colour + }); + } + + private void triggerUserScroll(float direction) + { + InputManager.MoveMouseTo(container); + InputManager.ScrollVerticalBy(direction); + } + + private class TestSection : Box + { + public bool Selected + { + set => Colour = value ? selected_colour : default_colour; + } + } + } +} From 78c14fd69693f688f40595699eba849486f49463 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Tue, 22 Dec 2020 17:36:44 +0200 Subject: [PATCH 015/202] Refactor code into UserTrackingScrollContainer --- .../Graphics/Containers/SectionsContainer.cs | 4 +- .../Containers/UserTrackingScrollContainer.cs | 49 +++++++++++++++++++ osu.Game/Overlays/OverlayScrollContainer.cs | 4 +- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 20 +------- 5 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 81968de304..6e9520ef8f 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.Containers protected override Container Content => scrollContentContainer; - private readonly OsuScrollContainer scrollContainer; + private readonly UserTrackingScrollContainer scrollContainer; private readonly Container headerBackgroundContainer; private readonly MarginPadding originalSectionsMargin; private Drawable expandableHeader, fixedHeader, footer, headerBackground; @@ -139,7 +139,7 @@ namespace osu.Game.Graphics.Containers public void ScrollToTop() => scrollContainer.ScrollTo(0); [NotNull] - protected virtual OsuScrollContainer CreateScrollContainer() => new OsuScrollContainer(); + protected virtual UserTrackingScrollContainer CreateScrollContainer() => new UserTrackingScrollContainer(); [NotNull] protected virtual FlowContainer CreateScrollContentContainer() => diff --git a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs new file mode 100644 index 0000000000..b8ce34b204 --- /dev/null +++ b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.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 osu.Framework.Graphics; + +namespace osu.Game.Graphics.Containers +{ + public class UserTrackingScrollContainer : UserTrackingScrollContainer + { + public UserTrackingScrollContainer() + { + } + + public UserTrackingScrollContainer(Direction direction) + : base(direction) + { + } + } + + public class UserTrackingScrollContainer : OsuScrollContainer + where T : Drawable + { + /// + /// Whether the last scroll event was user triggered, directly on the scroll container. + /// + public bool UserScrolling { get; private set; } + + public UserTrackingScrollContainer() + { + } + + public UserTrackingScrollContainer(Direction direction) + : base(direction) + { + } + + protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = default) + { + UserScrolling = true; + base.OnUserScroll(value, animated, distanceDecay); + } + + public new void ScrollTo(float value, bool animated = true, double? distanceDecay = null) + { + UserScrolling = false; + base.ScrollTo(value, animated, distanceDecay); + } + } +} diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index b67d5db1a4..0004719b87 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -17,9 +17,9 @@ using osuTK.Graphics; namespace osu.Game.Overlays { /// - /// which provides . Mostly used in . + /// which provides . Mostly used in . /// - public class OverlayScrollContainer : OsuScrollContainer + public class OverlayScrollContainer : UserTrackingScrollContainer { /// /// Scroll position at which the will be shown. diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 81027667fa..7f29545c2e 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -202,7 +202,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both; } - protected override OsuScrollContainer CreateScrollContainer() => new OverlayScrollContainer(); + protected override UserTrackingScrollContainer CreateScrollContainer() => new OverlayScrollContainer(); protected override FlowContainer CreateScrollContentContainer() => new FillFlowContainer { diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index d76f0abb9e..e9a8d28316 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -901,15 +901,10 @@ namespace osu.Game.Screens.Select } } - protected class CarouselScrollContainer : OsuScrollContainer + protected class CarouselScrollContainer : UserTrackingScrollContainer { private bool rightMouseScrollBlocked; - /// - /// Whether the last scroll event was user triggered, directly on the scroll container. - /// - public bool UserScrolling { get; private set; } - public CarouselScrollContainer() { // size is determined by the carousel itself, due to not all content necessarily being loaded. @@ -919,19 +914,6 @@ namespace osu.Game.Screens.Select Masking = false; } - // ReSharper disable once OptionalParameterHierarchyMismatch 2020.3 EAP4 bug. (https://youtrack.jetbrains.com/issue/RSRP-481535?p=RIDER-51910) - protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = default) - { - UserScrolling = true; - base.OnUserScroll(value, animated, distanceDecay); - } - - public new void ScrollTo(float value, bool animated = true, double? distanceDecay = null) - { - UserScrolling = false; - base.ScrollTo(value, animated, distanceDecay); - } - protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == MouseButton.Right) From 2cf76ebc75c6e0dc4bfbe428a9ee099c21a5eeb9 Mon Sep 17 00:00:00 2001 From: Endrik Tombak Date: Tue, 22 Dec 2020 17:51:12 +0200 Subject: [PATCH 016/202] Scroll to 20% and select section intersecting below there --- .../Graphics/Containers/SectionsContainer.cs | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 6e9520ef8f..b5f81c516a 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Layout; +using osu.Framework.Utils; namespace osu.Game.Graphics.Containers { @@ -20,6 +21,8 @@ namespace osu.Game.Graphics.Containers where T : Drawable { public Bindable SelectedSection { get; } = new Bindable(); + private Drawable lastClickedSection; + private T smallestSection; public Drawable ExpandableHeader { @@ -131,10 +134,21 @@ namespace osu.Game.Graphics.Containers lastKnownScroll = float.NaN; headerHeight = float.NaN; footerHeight = float.NaN; + + if (drawable == null) + return; + + if (smallestSection == null || smallestSection.Height > drawable.Height) + smallestSection = drawable; } - public void ScrollTo(Drawable section) => - scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(section) - (FixedHeader?.BoundingBox.Height ?? 0)); + private const float scroll_target_multiplier = 0.2f; + + public void ScrollTo(Drawable section) + { + lastClickedSection = section; + scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(section) - scrollContainer.DisplayableContent * scroll_target_multiplier - (FixedHeader?.BoundingBox.Height ?? 0)); + } public void ScrollToTop() => scrollContainer.ScrollTo(0); @@ -183,6 +197,10 @@ namespace osu.Game.Graphics.Containers { lastKnownScroll = currentScroll; + // reset last clicked section because user started scrolling themselves + if (scrollContainer.UserScrolling) + lastClickedSection = null; + if (ExpandableHeader != null && FixedHeader != null) { float offset = Math.Min(ExpandableHeader.LayoutSize.Y, currentScroll); @@ -194,18 +212,27 @@ namespace osu.Game.Graphics.Containers headerBackgroundContainer.Height = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0); headerBackgroundContainer.Y = ExpandableHeader?.Y ?? 0; - float scrollOffset = FixedHeader?.LayoutSize.Y ?? 0; + // scroll offset is our fixed header height if we have it plus 20% of content height + // plus 5% to fix floating point errors and to not have a section instantly unselect when scrolling upwards + // but the 5% can't be bigger than our smallest section height, otherwise it won't get selected correctly + float sectionOrContent = Math.Min(smallestSection?.Height / 2.0f ?? 0, scrollContainer.DisplayableContent * 0.05f); + float scrollOffset = (FixedHeader?.LayoutSize.Y ?? 0) + scrollContainer.DisplayableContent * scroll_target_multiplier + sectionOrContent; Func diff = section => scrollContainer.GetChildPosInContent(section) - currentScroll - scrollOffset; - if (scrollContainer.IsScrolledToEnd()) + if (Precision.AlmostBigger(0, scrollContainer.Current)) { - SelectedSection.Value = Children.LastOrDefault(); + SelectedSection.Value = lastClickedSection as T ?? Children.FirstOrDefault(); + return; } - else + + if (Precision.AlmostBigger(scrollContainer.Current, scrollContainer.ScrollableExtent)) { - SelectedSection.Value = Children.TakeWhile(section => diff(section) <= 0).LastOrDefault() - ?? Children.FirstOrDefault(); + SelectedSection.Value = lastClickedSection as T ?? Children.LastOrDefault(); + return; } + + SelectedSection.Value = Children.TakeWhile(section => diff(section) <= 0).LastOrDefault() + ?? Children.FirstOrDefault(); } } From 6a80e1303d540187093c794302f5982fa171ae0e Mon Sep 17 00:00:00 2001 From: Lucas A Date: Wed, 23 Dec 2020 12:56:04 +0100 Subject: [PATCH 017/202] LINQ-ify Import() logic and ignore case of file extensions. --- osu.Game/OsuGameBase.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index ca87772209..7def93255b 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -397,18 +397,13 @@ namespace osu.Game public virtual async Task Import(params ImportTask[] tasks) { - var importTasks = new List(); - - foreach (var extension in tasks.Select(t => Path.GetExtension(t.Path)).Distinct()) + var extensions = tasks.Select(t => Path.GetExtension(t.Path).ToLowerInvariant()).Distinct(); + await Task.WhenAll(extensions.Select(ext => { - var importList = tasks.Where(t => t.Path.EndsWith(extension, StringComparison.OrdinalIgnoreCase)); - var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(extension)); + var imports = tasks.Where(t => t.Path.EndsWith(ext, StringComparison.OrdinalIgnoreCase)); - if (importer != null) - importTasks.Add(importer.Import(importList.ToArray())); - } - - await Task.WhenAll(importTasks); + return fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(ext))?.Import(imports.ToArray()) ?? Task.CompletedTask; + })); } public IEnumerable HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions); From e9e0e18dc53a83c18c6aff7a2aac27b92445c1cb Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sun, 27 Dec 2020 14:11:30 +0100 Subject: [PATCH 018/202] Fix missed change in merge conflict... --- osu.Android/OsuGameActivity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index c397608bc6..7f2ef82d12 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -54,7 +54,7 @@ namespace osu.Android { case Intent.ActionDefault: if (intent.Scheme == ContentResolver.SchemeContent) - handleImportFromUri(intent.Data); + handleImportFromUris(intent.Data); else if (osu_url_schemes.Contains(intent.Scheme)) game.HandleLink(intent.DataString); break; From 013b9b62a1ff7dfd22db139d0571259bcd89de43 Mon Sep 17 00:00:00 2001 From: Firmatorenio Date: Tue, 29 Dec 2020 20:22:56 +0600 Subject: [PATCH 019/202] add SV multipliers to taiko difficulty mods --- osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs | 9 +++++++++ osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs | 9 +++++++++ osu.Game/Rulesets/Mods/ModHardRock.cs | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index d1ad4c9d8d..5ff91eec9f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.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 osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods @@ -8,5 +9,13 @@ namespace osu.Game.Rulesets.Taiko.Mods public class TaikoModEasy : ModEasy { public override string Description => @"Beats move slower, and less accuracy required!"; + + private const double slider_multiplier = 0.8; + + public override void ApplyToDifficulty(BeatmapDifficulty difficulty) + { + base.ApplyToDifficulty(difficulty); + difficulty.SliderMultiplier *= slider_multiplier; + } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index 49d225cdb5..37c8dab2de 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.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 osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Mods @@ -9,5 +10,13 @@ namespace osu.Game.Rulesets.Taiko.Mods { public override double ScoreMultiplier => 1.06; public override bool Ranked => true; + + private const double slider_multiplier = 1.87; + + public override void ApplyToDifficulty(BeatmapDifficulty difficulty) + { + base.ApplyToDifficulty(difficulty); + difficulty.SliderMultiplier *= slider_multiplier; + } } } diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 0e589735c1..4edcb0b074 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mods { } - public void ApplyToDifficulty(BeatmapDifficulty difficulty) + public virtual void ApplyToDifficulty(BeatmapDifficulty difficulty) { const float ratio = 1.4f; difficulty.CircleSize = Math.Min(difficulty.CircleSize * 1.3f, 10.0f); // CS uses a custom 1.3 ratio. From 669c42a38d7f3ac2d015754166b7af7aacbd13c9 Mon Sep 17 00:00:00 2001 From: Firmatorenio Date: Wed, 30 Dec 2020 20:57:41 +0600 Subject: [PATCH 020/202] add remarks explaining HR SV multiplier --- osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs | 3 +++ osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index 5ff91eec9f..ad6fdf59e2 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -10,6 +10,9 @@ namespace osu.Game.Rulesets.Taiko.Mods { public override string Description => @"Beats move slower, and less accuracy required!"; + /// + /// Multiplier factor added to the scrolling speed. + /// private const double slider_multiplier = 0.8; public override void ApplyToDifficulty(BeatmapDifficulty difficulty) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index 37c8dab2de..a5a8b75f80 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -11,7 +11,15 @@ namespace osu.Game.Rulesets.Taiko.Mods public override double ScoreMultiplier => 1.06; public override bool Ranked => true; - private const double slider_multiplier = 1.87; + /// + /// Multiplier factor added to the scrolling speed. + /// + /// + /// This factor is made up of two parts: the base part (1.4) and the aspect ratio adjustment (4/3). + /// Stable applies the latter by dividing the width of the user's display by the width of a display with the same height, but 4:3 aspect ratio. + /// TODO: Revisit if taiko playfield ever changes away from a hard-coded 16:9 (see https://github.com/ppy/osu/issues/5685). + /// + private const double slider_multiplier = 1.4 * 4 / 3; public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { From 4266c67bb66dc58fcdbc4406afe38a7d47c392d9 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 2 Jan 2021 19:19:55 +0100 Subject: [PATCH 021/202] Remove duplicated code path in switch. --- osu.Android/OsuGameActivity.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 42d9ad33ab..788e5f82be 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -62,13 +62,6 @@ namespace osu.Android break; case Intent.ActionSend: - { - var content = intent.ClipData?.GetItemAt(0); - if (content != null) - handleImportFromUris(content.Uri); - break; - } - case Intent.ActionSendMultiple: { var uris = new List(); From 249be461d511b10f541ef331b3b1aebe666d74be Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 12 Jan 2021 11:09:55 +0300 Subject: [PATCH 022/202] Add "explicit maps" search filter control --- .../Online/API/Requests/SearchBeatmapSetsRequest.cs | 8 +++++++- .../BeatmapListing/BeatmapListingFilterControl.cs | 4 +++- .../BeatmapListing/BeatmapListingSearchControl.cs | 6 +++++- osu.Game/Overlays/BeatmapListing/SearchExplicit.cs | 11 +++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Overlays/BeatmapListing/SearchExplicit.cs diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index bbaa7e745f..939d3c6cb4 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -30,6 +30,8 @@ namespace osu.Game.Online.API.Requests public SearchPlayed Played { get; } + public SearchExplicit Explicit { get; } + [CanBeNull] public IReadOnlyCollection Ranks { get; } @@ -50,7 +52,8 @@ namespace osu.Game.Online.API.Requests SearchLanguage language = SearchLanguage.Any, IReadOnlyCollection extra = null, IReadOnlyCollection ranks = null, - SearchPlayed played = SearchPlayed.Any) + SearchPlayed played = SearchPlayed.Any, + SearchExplicit explicitMaps = SearchExplicit.Hide) { this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); this.ruleset = ruleset; @@ -64,6 +67,7 @@ namespace osu.Game.Online.API.Requests Extra = extra; Ranks = ranks; Played = played; + Explicit = explicitMaps; } protected override WebRequest CreateWebRequest() @@ -93,6 +97,8 @@ namespace osu.Game.Online.API.Requests if (Played != SearchPlayed.Any) req.AddParameter("played", Played.ToString().ToLowerInvariant()); + req.AddParameter("nsfw", Explicit == SearchExplicit.Show ? "true" : "false"); + req.AddCursor(cursor); return req; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs index d991dcfcfb..650adcb4a9 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs @@ -141,6 +141,7 @@ namespace osu.Game.Overlays.BeatmapListing searchControl.Extra.CollectionChanged += (_, __) => queueUpdateSearch(); searchControl.Ranks.CollectionChanged += (_, __) => queueUpdateSearch(); searchControl.Played.BindValueChanged(_ => queueUpdateSearch()); + searchControl.Explicit.BindValueChanged(_ => queueUpdateSearch()); sortCriteria.BindValueChanged(_ => queueUpdateSearch()); sortDirection.BindValueChanged(_ => queueUpdateSearch()); @@ -193,7 +194,8 @@ namespace osu.Game.Overlays.BeatmapListing searchControl.Language.Value, searchControl.Extra, searchControl.Ranks, - searchControl.Played.Value); + searchControl.Played.Value, + searchControl.Explicit.Value); getSetsRequest.Success += response => { diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index e232bf045f..c14d693f7d 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -42,6 +42,8 @@ namespace osu.Game.Overlays.BeatmapListing public Bindable Played => playedFilter.Current; + public Bindable Explicit => explicitFilter.Current; + public BeatmapSetInfo BeatmapSet { set @@ -65,6 +67,7 @@ namespace osu.Game.Overlays.BeatmapListing private readonly BeatmapSearchMultipleSelectionFilterRow extraFilter; private readonly BeatmapSearchScoreFilterRow ranksFilter; private readonly BeatmapSearchFilterRow playedFilter; + private readonly BeatmapSearchFilterRow explicitFilter; private readonly Box background; private readonly UpdateableBeatmapSetCover beatmapCover; @@ -125,7 +128,8 @@ namespace osu.Game.Overlays.BeatmapListing languageFilter = new BeatmapSearchFilterRow(@"Language"), extraFilter = new BeatmapSearchMultipleSelectionFilterRow(@"Extra"), ranksFilter = new BeatmapSearchScoreFilterRow(), - playedFilter = new BeatmapSearchFilterRow(@"Played") + playedFilter = new BeatmapSearchFilterRow(@"Played"), + explicitFilter = new BeatmapSearchFilterRow(@"Explicit Maps"), } } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs new file mode 100644 index 0000000000..3e57cdd48c --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs @@ -0,0 +1,11 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Overlays.BeatmapListing +{ + public enum SearchExplicit + { + Hide, + Show + } +} From 24c18397397648894f0b943ec98e2f63735c71cf Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 12 Jan 2021 11:10:25 +0300 Subject: [PATCH 023/202] Add global web setting for allowing explicit content --- osu.Game/Configuration/OsuConfigManager.cs | 3 +++ .../BeatmapListing/BeatmapListingSearchControl.cs | 12 +++++++++++- .../Overlays/Settings/Sections/Online/WebSettings.cs | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index eb34a0885d..5e7a843baf 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -60,6 +60,8 @@ namespace osu.Game.Configuration Set(OsuSetting.ExternalLinkWarning, true); Set(OsuSetting.PreferNoVideo, false); + Set(OsuSetting.AllowExplicitContent, false); + // Audio Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); @@ -270,5 +272,6 @@ namespace osu.Game.Configuration EditorWaveformOpacity, DiscordRichPresence, AutomaticallyDownloadWhenSpectating, + AllowExplicitContent, } } diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index c14d693f7d..3761aee312 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -11,6 +11,7 @@ using osu.Framework.Bindables; using osu.Framework.Input.Events; using osu.Game.Beatmaps.Drawables; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; @@ -140,10 +141,19 @@ namespace osu.Game.Overlays.BeatmapListing categoryFilter.Current.Value = SearchCategory.Leaderboard; } + private IBindable allowExplicitContent; + [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load(OverlayColourProvider colourProvider, OsuConfigManager config) { background.Colour = colourProvider.Dark6; + + allowExplicitContent = config.GetBindable(OsuSetting.AllowExplicitContent); + allowExplicitContent.BindValueChanged(allow => + { + // Update search control if global "explicit allowed" setting changed. + Explicit.Value = allow.NewValue ? SearchExplicit.Show : SearchExplicit.Hide; + }, true); } public void TakeFocus() => textBox.TakeFocus(); diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 8134c350a6..da7ef46f65 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -33,6 +33,12 @@ namespace osu.Game.Overlays.Settings.Sections.Online Keywords = new[] { "spectator" }, Current = config.GetBindable(OsuSetting.AutomaticallyDownloadWhenSpectating), }, + new SettingsCheckbox + { + LabelText = "Hide warnings for explicit content in beatmaps", + Keywords = new[] { "nsfw", "18+", "offensive" }, + Current = config.GetBindable(OsuSetting.AllowExplicitContent), + } }; } } From 80fa2cf69330ff805c1de0f4464682a8f79b5156 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 12 Jan 2021 11:14:05 +0300 Subject: [PATCH 024/202] Add test coverage --- .../TestSceneBeatmapListingSearchControl.cs | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs index 3f757031f8..cb86047dea 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; @@ -19,9 +20,18 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue); - private readonly BeatmapListingSearchControl control; + private BeatmapListingSearchControl control; - public TestSceneBeatmapListingSearchControl() + private OsuConfigManager localConfig; + + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage)); + } + + [SetUp] + public void SetUp() => Schedule(() => { OsuSpriteText query; OsuSpriteText ruleset; @@ -31,30 +41,34 @@ namespace osu.Game.Tests.Visual.UserInterface OsuSpriteText extra; OsuSpriteText ranks; OsuSpriteText played; + OsuSpriteText explicitMap; - Add(control = new BeatmapListingSearchControl + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - Add(new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - Children = new Drawable[] + control = new BeatmapListingSearchControl { - query = new OsuSpriteText(), - ruleset = new OsuSpriteText(), - category = new OsuSpriteText(), - genre = new OsuSpriteText(), - language = new OsuSpriteText(), - extra = new OsuSpriteText(), - ranks = new OsuSpriteText(), - played = new OsuSpriteText() + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + query = new OsuSpriteText(), + ruleset = new OsuSpriteText(), + category = new OsuSpriteText(), + genre = new OsuSpriteText(), + language = new OsuSpriteText(), + extra = new OsuSpriteText(), + ranks = new OsuSpriteText(), + played = new OsuSpriteText(), + explicitMap = new OsuSpriteText(), + } } - }); + }; control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true); control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true); @@ -64,7 +78,8 @@ namespace osu.Game.Tests.Visual.UserInterface 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.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true); - } + control.Explicit.BindValueChanged(e => explicitMap.Text = $"Explicit Maps: {e.NewValue}", true); + }); [Test] public void TestCovers() @@ -74,6 +89,16 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Set null beatmap", () => control.BeatmapSet = null); } + [Test] + public void TestExplicitConfig() + { + AddStep("configure explicit content to allowed", () => localConfig.Set(OsuSetting.AllowExplicitContent, true)); + AddAssert("explicit control set to show", () => control.Explicit.Value == SearchExplicit.Show); + + AddStep("configure explicit content to disallowed", () => localConfig.Set(OsuSetting.AllowExplicitContent, false)); + AddAssert("explicit control set to hide", () => control.Explicit.Value == SearchExplicit.Hide); + } + private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo { OnlineInfo = new BeatmapSetOnlineInfo From 5f10bcce02411a22f783ba3a5bbb9d7ab66f43af Mon Sep 17 00:00:00 2001 From: Mysfit Date: Wed, 13 Jan 2021 00:09:22 -0500 Subject: [PATCH 025/202] Added beatmap colour settings checkbox and associated tests. --- .../TestSceneLegacyBeatmapSkin.cs | 78 +++++++++++++++++-- .../TestSceneSkinFallbacks.cs | 25 ++++++ osu.Game/Configuration/OsuConfigManager.cs | 2 + .../Overlays/Settings/Sections/SkinSection.cs | 5 ++ .../Play/PlayerSettings/VisualSettings.cs | 3 + .../Skinning/BeatmapSkinProvidingContainer.cs | 7 +- 6 files changed, 110 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index a768626005..83b1e28476 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -7,9 +7,12 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Play; using osu.Game.Skinning; @@ -24,34 +27,81 @@ namespace osu.Game.Rulesets.Osu.Tests [Resolved] private AudioManager audio { get; set; } - [TestCase(true)] - [TestCase(false)] - public void TestBeatmapComboColours(bool customSkinColoursPresent) + private readonly Bindable beatmapSkins = new Bindable(); + private readonly Bindable beatmapColours = new Bindable(); + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); + config.BindWith(OsuSetting.BeatmapColours, beatmapColours); + } + + [TestCase(true, true, true)] + [TestCase(true, false, true)] + [TestCase(false, true, true)] + [TestCase(false, false, true)] + public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin, bool useBeatmapColour) { ExposedPlayer player = null; - AddStep("load coloured beatmap", () => player = loadBeatmap(customSkinColoursPresent, true)); + configureSettings(useBeatmapSkin, useBeatmapColour); + AddStep("load coloured beatmap", () => player = loadBeatmap(userHasCustomColours, true)); AddUntilStep("wait for player", () => player.IsLoaded); AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); } - [Test] - public void TestBeatmapNoComboColours() + [TestCase(true, false)] + [TestCase(false, false)] + public void TestBeatmapComboColoursOverride(bool useBeatmapSkin, bool useBeatmapColour) { ExposedPlayer player = null; + configureSettings(useBeatmapSkin, useBeatmapColour); + AddStep("load coloured beatmap", () => player = loadBeatmap(true, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is user custom skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + } + + [TestCase(true, false)] + [TestCase(false, false)] + public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin, bool useBeatmapColour) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, useBeatmapColour); + AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + } + + [TestCase(true, true)] + [TestCase(false, true)] + [TestCase(true, false)] + [TestCase(false, false)] + public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, useBeatmapColour); AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); AddUntilStep("wait for player", () => player.IsLoaded); AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } - [Test] - public void TestBeatmapNoComboColoursSkinOverride() + [TestCase(true, true)] + [TestCase(false, true)] + [TestCase(true, false)] + [TestCase(false, false)] + public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) { ExposedPlayer player = null; + configureSettings(useBeatmapSkin, useBeatmapColour); AddStep("load custom-skin colour", () => player = loadBeatmap(true, false)); AddUntilStep("wait for player", () => player.IsLoaded); @@ -69,6 +119,18 @@ namespace osu.Game.Rulesets.Osu.Tests return player; } + private void configureSettings(bool beatmapSkins, bool beatmapColours) + { + AddStep($"{(beatmapSkins ? "enable" : "disable")} beatmap skins", () => + { + this.beatmapSkins.Value = beatmapSkins; + }); + AddStep($"{(beatmapColours ? "enable" : "disable")} beatmap colours", () => + { + this.beatmapColours.Value = beatmapColours; + }); + } + private class ExposedPlayer : Player { private readonly bool userHasCustomColours; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs index 856bfd7e80..10baca438d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs @@ -52,6 +52,31 @@ namespace osu.Game.Rulesets.Osu.Tests checkNextHitObject(null); } + [Test] + public void TestBeatmapColourDefault() + { + AddStep("enable user provider", () => testUserSkin.Enabled = true); + + AddStep("enable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, true)); + AddStep("enable beatmap colours", () => LocalConfig.Set(OsuSetting.BeatmapColours, true)); + checkNextHitObject("beatmap"); + + AddStep("enable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, true)); + AddStep("disable beatmap colours", () => LocalConfig.Set(OsuSetting.BeatmapColours, false)); + checkNextHitObject("beatmap"); + + AddStep("disable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, false)); + AddStep("enable beatmap colours", () => LocalConfig.Set(OsuSetting.BeatmapColours, true)); + checkNextHitObject("user"); + + AddStep("disable beatmap skin", () => LocalConfig.Set(OsuSetting.BeatmapSkins, false)); + AddStep("disable beatmap colours", () => LocalConfig.Set(OsuSetting.BeatmapColours, false)); + checkNextHitObject("user"); + + AddStep("disable user provider", () => testUserSkin.Enabled = false); + checkNextHitObject(null); + } + private void checkNextHitObject(string skin) => AddUntilStep($"check skin from {skin}", () => { diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index eb34a0885d..5a8f7b4477 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -82,6 +82,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowStoryboard, true); Set(OsuSetting.BeatmapSkins, true); + Set(OsuSetting.BeatmapColours, true); Set(OsuSetting.BeatmapHitsounds, true); Set(OsuSetting.CursorRotation, true); @@ -250,6 +251,7 @@ namespace osu.Game.Configuration ScreenshotCaptureMenuCursor, SongSelectRightMouseScroll, BeatmapSkins, + BeatmapColours, BeatmapHitsounds, IncreaseFirstObjectVisibility, ScoreDisplayMode, diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 5898482e4a..e29f97c33e 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -70,6 +70,11 @@ namespace osu.Game.Overlays.Settings.Sections Current = config.GetBindable(OsuSetting.BeatmapSkins) }, new SettingsCheckbox + { + LabelText = "Beatmap colours", + Current = config.GetBindable(OsuSetting.BeatmapColours) + }, + new SettingsCheckbox { LabelText = "Beatmap hitsounds", Current = config.GetBindable(OsuSetting.BeatmapHitsounds) diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 8f29fe7893..a97078c461 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -14,6 +14,7 @@ namespace osu.Game.Screens.Play.PlayerSettings private readonly PlayerSliderBar blurSliderBar; private readonly PlayerCheckbox showStoryboardToggle; private readonly PlayerCheckbox beatmapSkinsToggle; + private readonly PlayerCheckbox beatmapColorsToggle; private readonly PlayerCheckbox beatmapHitsoundsToggle; public VisualSettings() @@ -43,6 +44,7 @@ namespace osu.Game.Screens.Play.PlayerSettings }, showStoryboardToggle = new PlayerCheckbox { LabelText = "Storyboard / Video" }, beatmapSkinsToggle = new PlayerCheckbox { LabelText = "Beatmap skins" }, + beatmapColorsToggle = new PlayerCheckbox { LabelText = "Beatmap colours" }, beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = "Beatmap hitsounds" } }; } @@ -54,6 +56,7 @@ namespace osu.Game.Screens.Play.PlayerSettings blurSliderBar.Current = config.GetBindable(OsuSetting.BlurLevel); showStoryboardToggle.Current = config.GetBindable(OsuSetting.ShowStoryboard); beatmapSkinsToggle.Current = config.GetBindable(OsuSetting.BeatmapSkins); + beatmapColorsToggle.Current = config.GetBindable(OsuSetting.BeatmapColours); beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); } } diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index fc01f0bd31..ffc35b3ab6 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -15,6 +15,7 @@ namespace osu.Game.Skinning public class BeatmapSkinProvidingContainer : SkinProvidingContainer { private Bindable beatmapSkins; + private Bindable beatmapColours; private Bindable beatmapHitsounds; protected override bool AllowConfigurationLookup @@ -24,10 +25,10 @@ namespace osu.Game.Skinning if (beatmapSkins == null) throw new InvalidOperationException($"{nameof(BeatmapSkinProvidingContainer)} needs to be loaded before being consumed."); - return beatmapSkins.Value; + return beatmapColours.Value; } } - + protected override bool AllowDrawableLookup(ISkinComponent component) { if (beatmapSkins == null) @@ -62,6 +63,7 @@ namespace osu.Game.Skinning var config = parent.Get(); beatmapSkins = config.GetBindable(OsuSetting.BeatmapSkins); + beatmapColours = config.GetBindable(OsuSetting.BeatmapColours); beatmapHitsounds = config.GetBindable(OsuSetting.BeatmapHitsounds); return base.CreateChildDependencies(parent); @@ -71,6 +73,7 @@ namespace osu.Game.Skinning private void load() { beatmapSkins.BindValueChanged(_ => TriggerSourceChanged()); + beatmapColours.BindValueChanged(_ => TriggerSourceChanged()); beatmapHitsounds.BindValueChanged(_ => TriggerSourceChanged()); } } From 7bfb5954a8e7553dbd429f5901865525045d809a Mon Sep 17 00:00:00 2001 From: Mysfit Date: Wed, 13 Jan 2021 00:25:54 -0500 Subject: [PATCH 026/202] Fix whitespace formatting. --- osu.Game/Skinning/BeatmapSkinProvidingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index ffc35b3ab6..c16547589d 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Skinning return beatmapColours.Value; } } - + protected override bool AllowDrawableLookup(ISkinComponent component) { if (beatmapSkins == null) From 80bcd78a4802131d02576bebcf87c16f8297f2af Mon Sep 17 00:00:00 2001 From: Mysfit Date: Wed, 13 Jan 2021 02:04:59 -0500 Subject: [PATCH 027/202] Removed unnecessary using. --- osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 83b1e28476..138182c7c4 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -12,7 +12,6 @@ using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Play; using osu.Game.Skinning; From e8daea91d22e87e95d2deaf8caf70817c6277ebc Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 12 Jan 2021 18:13:05 +0300 Subject: [PATCH 028/202] Add online beatmap "explicit content" property --- osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs | 5 +++++ osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 06dee4d3f5..48f1f0ce68 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -31,6 +31,11 @@ namespace osu.Game.Beatmaps /// public BeatmapSetOnlineStatus Status { get; set; } + /// + /// Whether or not this beatmap set has explicit content. + /// + public bool HasExplicitContent { get; set; } + /// /// Whether or not this beatmap set has a background video. /// diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 720d6bfff4..bd1800e9f7 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -42,6 +42,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"bpm")] private double bpm { get; set; } + [JsonProperty(@"nsfw")] + private bool hasExplicitContent { get; set; } + [JsonProperty(@"video")] private bool hasVideo { get; set; } @@ -94,6 +97,7 @@ namespace osu.Game.Online.API.Requests.Responses FavouriteCount = favouriteCount, BPM = bpm, Status = Status, + HasExplicitContent = hasExplicitContent, HasVideo = hasVideo, HasStoryboard = hasStoryboard, Submitted = submitted, From ee6baeb57e0d51e8d65a3c8c70e25701cc58ada8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 12 Jan 2021 18:15:00 +0300 Subject: [PATCH 029/202] Add "explicit" marker pill --- .../BeatmapSet/ExplicitBeatmapPill.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs b/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs new file mode 100644 index 0000000000..77528c65c3 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays.BeatmapSet +{ + public class ExplicitBeatmapPill : CompositeDrawable + { + public ExplicitBeatmapPill() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, OverlayColourProvider colourProvider) + { + InternalChild = new CircularContainer + { + Masking = true, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider?.Background5 ?? colours.Gray2, + }, + new OsuSpriteText + { + Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f }, + Text = "EXPLICIT", + Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold), + // todo: this is --hsl-orange-2 from the new palette in https://github.com/ppy/osu-web/blob/8ceb46f/resources/assets/less/colors.less#L128-L151, + // should probably take the whole palette from there onto OsuColour for a nicer look in code. + Colour = Color4.FromHsl(new Vector4(45f / 360, 0.8f, 0.6f, 1f)), + } + } + }; + } + } +} From f6637eec36a460c5551e81d5b8776c12fad0caa9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 11:29:30 +0300 Subject: [PATCH 030/202] Add explicit pill to beatmap panels --- .../BeatmapListing/Panels/GridBeatmapPanel.cs | 29 +++++++++++++++---- .../BeatmapListing/Panels/ListBeatmapPanel.cs | 27 ++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs index 28c36e6c56..b7002a96e5 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.BeatmapSet; using osuTK; using osuTK.Graphics; @@ -24,7 +25,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels private const float horizontal_padding = 10; private const float vertical_padding = 5; - private FillFlowContainer bottomPanel, statusContainer; + private FillFlowContainer bottomPanel, statusContainer, titleContainer; private PlayButton playButton; private Box progressBar; @@ -73,12 +74,20 @@ namespace osu.Game.Overlays.BeatmapListing.Panels AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Left = horizontal_padding, Right = horizontal_padding }, Direction = FillDirection.Vertical, - Children = new[] + Children = new Drawable[] { - new OsuSpriteText + titleContainer = new FillFlowContainer { - Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) + }, + } }, new OsuSpriteText { @@ -194,6 +203,16 @@ namespace osu.Game.Overlays.BeatmapListing.Panels }, }); + if (SetInfo.OnlineInfo?.HasExplicitContent ?? false) + { + titleContainer.Add(new ExplicitBeatmapPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 10f, Top = 2f }, + }); + } + if (SetInfo.OnlineInfo?.HasVideo ?? false) { statusContainer.Add(new IconPill(FontAwesome.Solid.Film)); diff --git a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs index 433ea37f06..69671ab75b 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.BeatmapSet; using osuTK; using osuTK.Graphics; @@ -26,7 +27,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels private const float vertical_padding = 5; private const float height = 70; - private FillFlowContainer statusContainer; + private FillFlowContainer statusContainer, titleContainer; protected BeatmapPanelDownloadButton DownloadButton; private PlayButton playButton; private Box progressBar; @@ -98,10 +99,18 @@ namespace osu.Game.Overlays.BeatmapListing.Panels Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuSpriteText + titleContainer = new FillFlowContainer { - Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + new OsuSpriteText + { + Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) + }, + } }, new OsuSpriteText { @@ -208,6 +217,16 @@ namespace osu.Game.Overlays.BeatmapListing.Panels }, }); + if (SetInfo.OnlineInfo?.HasExplicitContent ?? false) + { + titleContainer.Add(new ExplicitBeatmapPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 10f, Top = 2f }, + }); + } + if (SetInfo.OnlineInfo?.HasVideo ?? false) { statusContainer.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); From 78631323ba35174543cbb09d2c8fd4f545888077 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 11:32:36 +0300 Subject: [PATCH 031/202] Add explicit pill to beatmap overlay --- osu.Game/Overlays/BeatmapSet/Header.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 321e496511..fbdee91d42 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -34,6 +34,7 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Box coverGradient; private readonly OsuSpriteText title, artist; private readonly AuthorInfo author; + private readonly ExplicitBeatmapPill explicitPill; private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapAvailability beatmapAvailability; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; @@ -146,6 +147,13 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Margin = new MarginPadding { Left = 3, Bottom = 4 }, // To better lineup with the font }, + explicitPill = new ExplicitBeatmapPill + { + Alpha = 0f, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 10f, Top = 4 }, + } } }, artist = new OsuSpriteText @@ -253,6 +261,8 @@ namespace osu.Game.Overlays.BeatmapSet title.Text = setInfo.NewValue.Metadata.Title ?? string.Empty; artist.Text = setInfo.NewValue.Metadata.Artist ?? string.Empty; + explicitPill.Alpha = setInfo.NewValue.OnlineInfo.HasExplicitContent ? 1 : 0; + onlineStatusPill.FadeIn(500, Easing.OutQuint); onlineStatusPill.Status = setInfo.NewValue.OnlineInfo.Status; From 1502b07ea86d7673dbbffa2fc2ec83612ca8d81c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 11:33:00 +0300 Subject: [PATCH 032/202] Add explicit pill to playlist items --- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index e3bce4029f..7987d715e3 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -23,6 +23,7 @@ using osu.Game.Online; using osu.Game.Online.Chat; using osu.Game.Online.Rooms; using osu.Game.Overlays.BeatmapListing.Panels; +using osu.Game.Overlays.BeatmapSet; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; @@ -41,6 +42,7 @@ namespace osu.Game.Screens.OnlinePlay private Container difficultyIconContainer; private LinkFlowContainer beatmapText; private LinkFlowContainer authorText; + private ExplicitBeatmapPill explicitPill; private ModDisplay modDisplay; private readonly Bindable beatmap = new Bindable(); @@ -116,6 +118,9 @@ namespace osu.Game.Screens.OnlinePlay authorText.AddUserLink(Item.Beatmap.Value?.Metadata.Author); } + bool hasExplicitContent = Item.Beatmap.Value.BeatmapSet.OnlineInfo?.HasExplicitContent == true; + explicitPill.Alpha = hasExplicitContent ? 1 : 0; + modDisplay.Current.Value = requiredMods.ToArray(); } @@ -165,18 +170,37 @@ namespace osu.Game.Screens.OnlinePlay { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Spacing = new Vector2(15, 0), + Spacing = new Vector2(10f, 0), Children = new Drawable[] { - authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, - modDisplay = new ModDisplay + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10f, 0), + Children = new Drawable[] + { + authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, + explicitPill = new ExplicitBeatmapPill + { + Alpha = 0f, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Top = 3f }, + } + }, + }, + new Container { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, - Scale = new Vector2(0.4f), - DisplayUnrankedText = false, - ExpansionMode = ExpansionMode.AlwaysExpanded + Child = modDisplay = new ModDisplay + { + Scale = new Vector2(0.4f), + DisplayUnrankedText = false, + ExpansionMode = ExpansionMode.AlwaysExpanded + } } } } From 7fd55efc434fb5522de44429cc27e27c32cd6969 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 11:57:29 +0300 Subject: [PATCH 033/202] Add test cases for displaying explicit beatmaps --- .../Multiplayer/TestSceneDrawableRoomPlaylist.cs | 9 +++++++++ .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 11 +++++++++++ osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs | 7 ++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 65c0cfd328..17d85d1120 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -222,6 +222,15 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("download buttons shown", () => playlist.ChildrenOfType().All(d => d.IsPresent)); } + [Test] + public void TestExplicitBeatmapItem() + { + var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; + beatmap.BeatmapSet.OnlineInfo.HasExplicitContent = true; + + createPlaylist(beatmap); + } + private void moveToItem(int index, Vector2? offset = null) => AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType>().ElementAt(index), offset)); diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index c5d1fd6887..689321698a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -235,6 +235,17 @@ namespace osu.Game.Tests.Visual.Online AddAssert("left-most beatmap selected", () => overlay.Header.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected); } + [Test] + public void TestExplicitBeatmap() + { + AddStep("show explicit map", () => + { + var beatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet; + beatmapSet.OnlineInfo.HasExplicitContent = true; + overlay.ShowBeatmapSet(beatmapSet); + }); + } + [Test] public void TestHide() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 74ece5da05..fd5f306e07 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -99,13 +99,16 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - var normal = CreateWorkingBeatmap(Ruleset.Value).BeatmapSetInfo; + var normal = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet; normal.OnlineInfo.HasVideo = true; normal.OnlineInfo.HasStoryboard = true; var undownloadable = getUndownloadableBeatmapSet(); var manyDifficulties = getManyDifficultiesBeatmapSet(rulesets); + var explicitMap = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet; + explicitMap.OnlineInfo.HasExplicitContent = true; + Child = new BasicScrollContainer { RelativeSizeAxes = Axes.Both, @@ -121,9 +124,11 @@ namespace osu.Game.Tests.Visual.Online new GridBeatmapPanel(normal), new GridBeatmapPanel(undownloadable), new GridBeatmapPanel(manyDifficulties), + new GridBeatmapPanel(explicitMap), new ListBeatmapPanel(normal), new ListBeatmapPanel(undownloadable), new ListBeatmapPanel(manyDifficulties), + new ListBeatmapPanel(explicitMap) }, }, }; From f827c620813468f2c670f393c424b84e8b11f634 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 11:58:55 +0300 Subject: [PATCH 034/202] Add empty online info to test beatmap This is for `BeatmapSetOverlay` to not eat a null reference trying to access `Beatmap.OnlineInfo`. --- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 035cb64099..fa6dc5647d 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -32,6 +32,7 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.BeatmapSet.Files = new List(); BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo }; BeatmapInfo.Length = 75000; + BeatmapInfo.OnlineInfo = new BeatmapOnlineInfo(); BeatmapInfo.BeatmapSet.OnlineInfo = new BeatmapSetOnlineInfo { Status = BeatmapSetOnlineStatus.Ranked, From 268f9d661f16c55aa1c8ebadb4f44e05baa7373a Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 13:00:14 +0300 Subject: [PATCH 035/202] Dispose of local config on disposal --- .../UserInterface/TestSceneBeatmapListingSearchControl.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs index cb86047dea..dc46da6293 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs @@ -99,6 +99,12 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("explicit control set to hide", () => control.Explicit.Value == SearchExplicit.Hide); } + protected override void Dispose(bool isDisposing) + { + localConfig?.Dispose(); + base.Dispose(isDisposing); + } + private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo { OnlineInfo = new BeatmapSetOnlineInfo From 9d59d784f8674b1319a175c1edb74d079de76dfe Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 17:06:44 +0300 Subject: [PATCH 036/202] Add Colour{1-4} properties to `OverlayColourProvider` --- osu.Game/Overlays/OverlayColourProvider.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/OverlayColourProvider.cs b/osu.Game/Overlays/OverlayColourProvider.cs index 9816f313ad..f33223d7aa 100644 --- a/osu.Game/Overlays/OverlayColourProvider.cs +++ b/osu.Game/Overlays/OverlayColourProvider.cs @@ -16,6 +16,11 @@ namespace osu.Game.Overlays this.colourScheme = colourScheme; } + public Color4 Colour1 => getColour(1, 0.7f); + public Color4 Colour2 => getColour(0.8f, 0.6f); + public Color4 Colour3 => getColour(0.6f, 0.5f); + public Color4 Colour4 => getColour(0.4f, 0.3f); + public Color4 Highlight1 => getColour(1, 0.7f); public Color4 Content1 => getColour(0.4f, 1); public Color4 Content2 => getColour(0.4f, 0.9f); From e275dd02e08ab8d9e890d2d0a2b1f822e1c53f6c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 17:07:11 +0300 Subject: [PATCH 037/202] Create static colour properties for now --- osu.Game/Overlays/OverlayColourProvider.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/OverlayColourProvider.cs b/osu.Game/Overlays/OverlayColourProvider.cs index f33223d7aa..abd1e43f25 100644 --- a/osu.Game/Overlays/OverlayColourProvider.cs +++ b/osu.Game/Overlays/OverlayColourProvider.cs @@ -11,6 +11,13 @@ namespace osu.Game.Overlays { private readonly OverlayColourScheme colourScheme; + public static OverlayColourProvider Red { get; } = new OverlayColourProvider(OverlayColourScheme.Red); + public static OverlayColourProvider Pink { get; } = new OverlayColourProvider(OverlayColourScheme.Pink); + public static OverlayColourProvider Orange { get; } = new OverlayColourProvider(OverlayColourScheme.Orange); + public static OverlayColourProvider Green { get; } = new OverlayColourProvider(OverlayColourScheme.Green); + public static OverlayColourProvider Purple { get; } = new OverlayColourProvider(OverlayColourScheme.Purple); + public static OverlayColourProvider Blue { get; } = new OverlayColourProvider(OverlayColourScheme.Blue); + public OverlayColourProvider(OverlayColourScheme colourScheme) { this.colourScheme = colourScheme; From 43daa7c7c09463acac11095bc93f304e1c20ae83 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 13 Jan 2021 17:07:42 +0300 Subject: [PATCH 038/202] Use `Colour2` of orange theme for explicit pill --- osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs b/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs index 77528c65c3..ad19dffccb 100644 --- a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs +++ b/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs @@ -7,8 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { @@ -38,9 +36,7 @@ namespace osu.Game.Overlays.BeatmapSet Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f }, Text = "EXPLICIT", Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold), - // todo: this is --hsl-orange-2 from the new palette in https://github.com/ppy/osu-web/blob/8ceb46f/resources/assets/less/colors.less#L128-L151, - // should probably take the whole palette from there onto OsuColour for a nicer look in code. - Colour = Color4.FromHsl(new Vector4(45f / 360, 0.8f, 0.6f, 1f)), + Colour = OverlayColourProvider.Orange.Colour2, } } }; From 1248d39d7e5fa6a7a30271a1346059594e0e021d Mon Sep 17 00:00:00 2001 From: Mysfit Date: Wed, 13 Jan 2021 13:07:07 -0500 Subject: [PATCH 039/202] Reverted change to AllowConfigurationLookup and added a separate AllowColourLookup bool with config case based on lookup type in SkinProvidingContainer GetConfig call. --- .../Skinning/BeatmapSkinProvidingContainer.cs | 11 ++++++ osu.Game/Skinning/SkinProvidingContainer.cs | 34 ++++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs index c16547589d..57c08a903f 100644 --- a/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs +++ b/osu.Game/Skinning/BeatmapSkinProvidingContainer.cs @@ -25,6 +25,17 @@ namespace osu.Game.Skinning if (beatmapSkins == null) throw new InvalidOperationException($"{nameof(BeatmapSkinProvidingContainer)} needs to be loaded before being consumed."); + return beatmapSkins.Value; + } + } + + protected override bool AllowColourLookup + { + get + { + if (beatmapColours == null) + throw new InvalidOperationException($"{nameof(BeatmapSkinProvidingContainer)} needs to be loaded before being consumed."); + return beatmapColours.Value; } } diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index adf62ed452..3232a30110 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -32,6 +32,8 @@ namespace osu.Game.Skinning protected virtual bool AllowConfigurationLookup => true; + protected virtual bool AllowColourLookup => true; + public SkinProvidingContainer(ISkin skin) { this.skin = skin; @@ -68,11 +70,35 @@ namespace osu.Game.Skinning public IBindable GetConfig(TLookup lookup) { - if (AllowConfigurationLookup && skin != null) + if (skin != null) { - var bindable = skin.GetConfig(lookup); - if (bindable != null) - return bindable; + switch (lookup) + { + // todo: the GlobalSkinColours switch is pulled from LegacySkin and should not exist. + // will likely change based on how databased storage of skin configuration goes. + case GlobalSkinColours global: + switch (global) + { + case GlobalSkinColours.ComboColours: + var bindable = skin.GetConfig(lookup); + if (bindable != null && AllowColourLookup) + return bindable; + else + return fallbackSource?.GetConfig(lookup); + } + + break; + + default: + if (AllowConfigurationLookup) + { + var bindable = skin.GetConfig(lookup); + if (bindable != null) + return bindable; + } + + break; + } } return fallbackSource?.GetConfig(lookup); From 8b95817f7abf8f5674ffa11d37c1eb37ce259806 Mon Sep 17 00:00:00 2001 From: Mysfit Date: Wed, 13 Jan 2021 16:05:46 -0500 Subject: [PATCH 040/202] Moved SkinProvidingContainer bindable fetching to common method. Replaced redundant test boolean declarations with inline values. --- .../TestSceneLegacyBeatmapSkin.cs | 28 +++++++++---------- osu.Game/Skinning/SkinProvidingContainer.cs | 24 ++++++++-------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 138182c7c4..22b028906f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -36,41 +36,41 @@ namespace osu.Game.Rulesets.Osu.Tests config.BindWith(OsuSetting.BeatmapColours, beatmapColours); } - [TestCase(true, true, true)] - [TestCase(true, false, true)] - [TestCase(false, true, true)] - [TestCase(false, false, true)] - public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin, bool useBeatmapColour) + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) { ExposedPlayer player = null; - configureSettings(useBeatmapSkin, useBeatmapColour); + configureSettings(useBeatmapSkin, true); AddStep("load coloured beatmap", () => player = loadBeatmap(userHasCustomColours, true)); AddUntilStep("wait for player", () => player.IsLoaded); AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); } - [TestCase(true, false)] - [TestCase(false, false)] - public void TestBeatmapComboColoursOverride(bool useBeatmapSkin, bool useBeatmapColour) + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapComboColoursOverride(bool useBeatmapSkin) { ExposedPlayer player = null; - configureSettings(useBeatmapSkin, useBeatmapColour); + configureSettings(useBeatmapSkin, false); AddStep("load coloured beatmap", () => player = loadBeatmap(true, true)); AddUntilStep("wait for player", () => player.IsLoaded); AddAssert("is user custom skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); } - [TestCase(true, false)] - [TestCase(false, false)] - public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin, bool useBeatmapColour) + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) { ExposedPlayer player = null; - configureSettings(useBeatmapSkin, useBeatmapColour); + configureSettings(useBeatmapSkin, false); AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); AddUntilStep("wait for player", () => player.IsLoaded); diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index 3232a30110..ae9a84932a 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -80,30 +80,28 @@ namespace osu.Game.Skinning switch (global) { case GlobalSkinColours.ComboColours: - var bindable = skin.GetConfig(lookup); - if (bindable != null && AllowColourLookup) - return bindable; - else - return fallbackSource?.GetConfig(lookup); + return getBindable(lookup, AllowColourLookup); } break; default: - if (AllowConfigurationLookup) - { - var bindable = skin.GetConfig(lookup); - if (bindable != null) - return bindable; - } - - break; + return getBindable(lookup, AllowConfigurationLookup); } } return fallbackSource?.GetConfig(lookup); } + private IBindable getBindable(TLookup lookup, bool bindableReturnCheck) + { + var bindable = skin.GetConfig(lookup); + if (bindable != null && bindableReturnCheck) + return bindable; + else + return fallbackSource?.GetConfig(lookup); + } + protected virtual void TriggerSourceChanged() => SourceChanged?.Invoke(); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 562634dfd2de90736dfb812c9d8834c0c97bcb4c Mon Sep 17 00:00:00 2001 From: Jesse Myers Date: Wed, 13 Jan 2021 16:49:14 -0500 Subject: [PATCH 041/202] Improve naming around the config lookup with fallback private method. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Skinning/SkinProvidingContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index ae9a84932a..2dc19667e4 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -93,10 +93,10 @@ namespace osu.Game.Skinning return fallbackSource?.GetConfig(lookup); } - private IBindable getBindable(TLookup lookup, bool bindableReturnCheck) + private IBindable lookupWithFallback(TLookup lookup, bool canUseSkinLookup) { var bindable = skin.GetConfig(lookup); - if (bindable != null && bindableReturnCheck) + if (bindable != null && canUseSkinLookup) return bindable; else return fallbackSource?.GetConfig(lookup); From abf718242b11519825228a2f6098dff745231608 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 14 Jan 2021 05:40:43 +0300 Subject: [PATCH 042/202] Make explicit marker font semi-bold --- osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs b/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs index ad19dffccb..aefb3299a5 100644 --- a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs +++ b/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.BeatmapSet { Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f }, Text = "EXPLICIT", - Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold), + Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold), Colour = OverlayColourProvider.Orange.Colour2, } } From 6281c1086ac377503c89a5648608e47ab6b71e89 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 14 Jan 2021 05:41:09 +0300 Subject: [PATCH 043/202] Space out explicit marker in beatmap overlay --- osu.Game/Overlays/BeatmapSet/Header.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index fbdee91d42..9f2b40dfa4 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -152,7 +152,7 @@ namespace osu.Game.Overlays.BeatmapSet Alpha = 0f, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Left = 10f, Top = 4 }, + Margin = new MarginPadding { Left = 15f, Top = 4 }, } } }, From 99e43c77c23709c90100cea34210c5a2d054a206 Mon Sep 17 00:00:00 2001 From: Mysfit Date: Thu, 14 Jan 2021 16:53:55 -0500 Subject: [PATCH 044/202] Simplified colour config checks in SkinProvidingContainer.cs --- osu.Game/Skinning/SkinProvidingContainer.cs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index 2dc19667e4..d2645eff68 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; using osu.Game.Audio; +using osuTK.Graphics; namespace osu.Game.Skinning { @@ -72,22 +73,12 @@ namespace osu.Game.Skinning { if (skin != null) { - switch (lookup) - { - // todo: the GlobalSkinColours switch is pulled from LegacySkin and should not exist. - // will likely change based on how databased storage of skin configuration goes. - case GlobalSkinColours global: - switch (global) - { - case GlobalSkinColours.ComboColours: - return getBindable(lookup, AllowColourLookup); - } + TValue tValueTypeCheck = default; - break; - - default: - return getBindable(lookup, AllowConfigurationLookup); - } + if (lookup is GlobalSkinColours || tValueTypeCheck is Color4) + return lookupWithFallback(lookup, AllowColourLookup); + else + return lookupWithFallback(lookup, AllowConfigurationLookup); } return fallbackSource?.GetConfig(lookup); From dc8e38cf4d8dfcdb0a33a6d4c73147ce43fe4c05 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 15 Jan 2021 07:20:13 +0300 Subject: [PATCH 045/202] Remove pointless inline comment --- osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 3761aee312..5c6267b726 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -151,7 +151,6 @@ namespace osu.Game.Overlays.BeatmapListing allowExplicitContent = config.GetBindable(OsuSetting.AllowExplicitContent); allowExplicitContent.BindValueChanged(allow => { - // Update search control if global "explicit allowed" setting changed. Explicit.Value = allow.NewValue ? SearchExplicit.Show : SearchExplicit.Hide; }, true); } From 4cccde9007cdb1646f041da71d77184c51f490d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 13:20:46 +0900 Subject: [PATCH 046/202] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 492c88c7e4..919d83f8db 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ff016199d3..ac014f2964 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -28,7 +28,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 93be3645ee..799042626b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From 0c01a3a685c9ba1ca5c29f5e124043780c9f1d61 Mon Sep 17 00:00:00 2001 From: Mysfit Date: Thu, 14 Jan 2021 23:30:24 -0500 Subject: [PATCH 047/202] Found a better solution than TValue type checking for additional beatmap colour settings. Added unit tests for Catch Beatmap Skin settings. --- .../TestSceneLegacyBeatmapSkin.cs | 360 ++++++++++++++++++ osu.Game/Skinning/SkinProvidingContainer.cs | 5 +- 2 files changed, 361 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs new file mode 100644 index 0000000000..12ceaaa6fa --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs @@ -0,0 +1,360 @@ +// Copyright (c) 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.Audio; +using osu.Framework.Bindables; +using osu.Framework.IO.Stores; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Play; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Tests +{ + public class TestSceneLegacyBeatmapSkin : ScreenTestScene + { + [Resolved] + private AudioManager audio { get; set; } + + private readonly Bindable beatmapSkins = new Bindable(); + private readonly Bindable beatmapColours = new Bindable(); + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); + config.BindWith(OsuSetting.BeatmapColours, beatmapColours); + } + + [TestCase(true, true)] + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(false, false)] + public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, true); + AddStep("load coloured beatmap", () => player = loadBeatmap(userHasCustomColours, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); + } + + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapComboColoursOverride(bool useBeatmapSkin) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, false); + AddStep("load coloured beatmap", () => player = loadBeatmap(true, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is user custom skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + } + + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, false); + AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + } + + [TestCase(true, true)] + [TestCase(false, true)] + [TestCase(true, false)] + [TestCase(false, false)] + public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, useBeatmapColour); + AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + } + + [TestCase(true, true)] + [TestCase(false, true)] + [TestCase(true, false)] + [TestCase(false, false)] + public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, useBeatmapColour); + AddStep("load custom-skin colour", () => player = loadBeatmap(true, false)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is custom user skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + } + + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapHyperDashColours(bool useBeatmapSkin) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, true); + AddStep("load custom-skin colour", () => player = loadBeatmap(true, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is custom hyper dash colours", () => player.UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR); + AddAssert("is custom hyper dash after image colours", () => player.UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); + AddAssert("is custom hyper dash fruit colours", () => player.UsableHyperDashFruitColour == TestBeatmapSkin.HYPER_DASH_FRUIT_COLOUR); + } + + [TestCase(true)] + [TestCase(false)] + public void TestBeatmapHyperDashColoursOverride(bool useBeatmapSkin) + { + ExposedPlayer player = null; + + configureSettings(useBeatmapSkin, false); + AddStep("load custom-skin colour", () => player = loadBeatmap(true, true)); + AddUntilStep("wait for player", () => player.IsLoaded); + + AddAssert("is custom hyper dash colours", () => player.UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR); + AddAssert("is custom hyper dash after image colours", () => player.UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); + AddAssert("is custom hyper dash fruit colours", () => player.UsableHyperDashFruitColour == TestSkin.HYPER_DASH_FRUIT_COLOUR); + } + + private ExposedPlayer loadBeatmap(bool userHasCustomColours, bool beatmapHasColours) + { + ExposedPlayer player; + + Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasColours); + + LoadScreen(player = new ExposedPlayer(userHasCustomColours)); + + return player; + } + + private void configureSettings(bool beatmapSkins, bool beatmapColours) + { + AddStep($"{(beatmapSkins ? "enable" : "disable")} beatmap skins", () => + { + this.beatmapSkins.Value = beatmapSkins; + }); + AddStep($"{(beatmapColours ? "enable" : "disable")} beatmap colours", () => + { + this.beatmapColours.Value = beatmapColours; + }); + } + + private class ExposedPlayer : Player + { + private readonly bool userHasCustomColours; + + public ExposedPlayer(bool userHasCustomColours) + : base(new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) + { + this.userHasCustomColours = userHasCustomColours; + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(new TestSkin(userHasCustomColours)); + return dependencies; + } + + public IReadOnlyList UsableComboColours => + GameplayClockContainer.ChildrenOfType() + .First() + .GetConfig>(GlobalSkinColours.ComboColours)?.Value; + + public Color4 UsableHyperDashColour => + GameplayClockContainer.ChildrenOfType() + .First() + .GetConfig(new SkinCustomColourLookup(CatchSkinColour.HyperDash))? + .Value ?? Color4.Red; + + public Color4 UsableHyperDashAfterImageColour => + GameplayClockContainer.ChildrenOfType() + .First() + .GetConfig(new SkinCustomColourLookup(CatchSkinColour.HyperDashAfterImage))? + .Value ?? Color4.Red; + + public Color4 UsableHyperDashFruitColour => + GameplayClockContainer.ChildrenOfType() + .First() + .GetConfig(new SkinCustomColourLookup(CatchSkinColour.HyperDashFruit))? + .Value ?? Color4.Red; + } + + private class TestJuiceStream : JuiceStream + { + public TestJuiceStream(float x) + { + X = x; + + Path = new SliderPath(new[] + { + new PathControlPoint(Vector2.Zero), + new PathControlPoint(new Vector2(30, 0)), + }); + } + } + + private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + private readonly bool hasColours; + + public CustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) + : base(createBeatmap(new CatchRuleset().RulesetInfo), null, null, audio) + { + this.hasColours = hasColours; + } + + protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, hasColours); + + private static IBeatmap createBeatmap(RulesetInfo ruleset) + { + var beatmap = new Beatmap + { + BeatmapInfo = + { + Ruleset = ruleset, + BaseDifficulty = new BeatmapDifficulty { CircleSize = 3.6f } + } + }; + + beatmap.ControlPointInfo.Add(0, new TimingControlPoint()); + + // Should produce a hyper-dash (edge case test) + beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 56, NewCombo = true }); + beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308, NewCombo = true }); + + double startTime = 3000; + + const float left_x = 0.02f * CatchPlayfield.WIDTH; + const float right_x = 0.98f * CatchPlayfield.WIDTH; + + createObjects(() => new Fruit { X = left_x }); + createObjects(() => new TestJuiceStream(right_x), 1); + createObjects(() => new TestJuiceStream(left_x), 1); + createObjects(() => new Fruit { X = right_x }); + createObjects(() => new Fruit { X = left_x }); + createObjects(() => new Fruit { X = right_x }); + createObjects(() => new TestJuiceStream(left_x), 1); + + beatmap.ControlPointInfo.Add(startTime, new TimingControlPoint + { + BeatLength = 50 + }); + + createObjects(() => new TestJuiceStream(left_x) + { + Path = new SliderPath(new[] + { + new PathControlPoint(Vector2.Zero), + new PathControlPoint(new Vector2(512, 0)) + }) + }, 1); + + return beatmap; + + void createObjects(Func createObject, int count = 3) + { + const float spacing = 140; + + for (int i = 0; i < count; i++) + { + var hitObject = createObject(); + hitObject.StartTime = startTime + i * spacing; + beatmap.HitObjects.Add(hitObject); + } + + startTime += 700; + } + } + } + + private class TestBeatmapSkin : LegacyBeatmapSkin + { + public static Color4[] Colours { get; } = + { + new Color4(50, 100, 150, 255), + new Color4(40, 80, 120, 255), + }; + + public static readonly Color4 HYPER_DASH_COLOUR = Color4.DarkBlue; + + public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.DarkCyan; + + public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.DarkGoldenrod; + + public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) + : base(beatmap, new ResourceStore(), null) + { + if (hasColours) + { + Configuration.AddComboColours(Colours); + Configuration.CustomColours.Add(CatchSkinColour.HyperDash.ToString(), HYPER_DASH_COLOUR); + Configuration.CustomColours.Add(CatchSkinColour.HyperDashAfterImage.ToString(), HYPER_DASH_AFTER_IMAGE_COLOUR); + Configuration.CustomColours.Add(CatchSkinColour.HyperDashFruit.ToString(), HYPER_DASH_FRUIT_COLOUR); + } + } + } + + private class TestSkin : LegacySkin, ISkinSource + { + public static Color4[] Colours { get; } = + { + new Color4(150, 100, 50, 255), + new Color4(20, 20, 20, 255), + }; + + public static readonly Color4 HYPER_DASH_COLOUR = Color4.LightBlue; + + public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.LightCoral; + + public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.LightCyan; + + public TestSkin(bool hasCustomColours) + : base(new SkinInfo(), new ResourceStore(), null, string.Empty) + { + if (hasCustomColours) + { + Configuration.AddComboColours(Colours); + Configuration.CustomColours.Add(CatchSkinColour.HyperDash.ToString(), HYPER_DASH_COLOUR); + Configuration.CustomColours.Add(CatchSkinColour.HyperDashAfterImage.ToString(), HYPER_DASH_AFTER_IMAGE_COLOUR); + Configuration.CustomColours.Add(CatchSkinColour.HyperDashFruit.ToString(), HYPER_DASH_FRUIT_COLOUR); + } + } + + public event Action SourceChanged + { + add { } + remove { } + } + } + } +} diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index d2645eff68..e97822b86e 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; using osu.Game.Audio; -using osuTK.Graphics; namespace osu.Game.Skinning { @@ -73,9 +72,7 @@ namespace osu.Game.Skinning { if (skin != null) { - TValue tValueTypeCheck = default; - - if (lookup is GlobalSkinColours || tValueTypeCheck is Color4) + if (lookup is GlobalSkinColours || lookup is SkinCustomColourLookup) return lookupWithFallback(lookup, AllowColourLookup); else return lookupWithFallback(lookup, AllowConfigurationLookup); From ebbc32adfa9c4652cadff32dc5c429af9867ff09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 14:51:26 +0900 Subject: [PATCH 048/202] Change conditional used to decide legacy judgement animation to match stable In stable, the type of legacy judgement to show is based on the presence of particle textures in the skin. We were using the skin version instead, which turns out to be incorrect and not what some user skins expect. Closes #11078. --- osu.Game/Skinning/LegacySkin.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index e4e5bf2f75..7397e3d08b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -378,8 +378,12 @@ namespace osu.Game.Skinning // kind of wasteful that we throw this away, but should do for now. if (createDrawable() != null) { - if (Configuration.LegacyVersion > 1) - return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, getParticleTexture(resultComponent.Component)); + var particle = getParticleTexture(resultComponent.Component); + + if (particle != null) + { + return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, particle); + } else return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); } From 86f66727de47175b8045523c56f719a8051041a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 13:29:37 +0900 Subject: [PATCH 049/202] Update KeyBinding usages in line with interface changes --- osu.Game/Database/OsuDbContext.cs | 2 ++ osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs | 2 +- osu.Game/Input/Bindings/GlobalActionContainer.cs | 2 +- osu.Game/Input/KeyBindingStore.cs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 2ae07b3cf8..2aae62edea 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -135,6 +135,8 @@ namespace osu.Game.Database modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); modelBuilder.Entity().HasIndex(b => b.IntAction); + modelBuilder.Entity().Ignore(b => b.KeyCombination); + modelBuilder.Entity().Ignore(b => b.Action); modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index 94edc33099..d12eaa10f6 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Input.Bindings private KeyBindingStore store; - public override IEnumerable DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0); + public override IEnumerable DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0); /// /// Create a new instance. diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index b8c2fa201f..8ccdb9249e 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Input.Bindings handler = game; } - public override IEnumerable DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings).Concat(EditorKeyBindings); + public override IEnumerable DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings).Concat(EditorKeyBindings); public IEnumerable GlobalKeyBindings => new[] { diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index bc73d74d74..b25b00eb84 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -49,7 +49,7 @@ namespace osu.Game.Input } } - private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) + private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) { using (var usage = ContextFactory.GetForWrite()) { From 51255033e24c2afbbac85573ef5e7edf610eb920 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 13:41:35 +0900 Subject: [PATCH 050/202] Update some missed usages of KeyBindingContainer in tests --- osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index b2ad7ca5b4..802dbf2021 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -244,7 +244,7 @@ namespace osu.Game.Tests.Visual.Gameplay internal class TestKeyBindingContainer : KeyBindingContainer { - public override IEnumerable DefaultKeyBindings => new[] + public override IEnumerable DefaultKeyBindings => new[] { new KeyBinding(InputKey.MouseLeft, TestAction.Down), }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs index 40c4214749..6e338b7202 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs @@ -179,7 +179,7 @@ namespace osu.Game.Tests.Visual.Gameplay internal class TestKeyBindingContainer : KeyBindingContainer { - public override IEnumerable DefaultKeyBindings => new[] + public override IEnumerable DefaultKeyBindings => new[] { new KeyBinding(InputKey.MouseLeft, TestAction.Down), }; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index b9ff95cb29..8278ff9adf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -303,7 +303,7 @@ namespace osu.Game.Tests.Visual.Gameplay internal class TestKeyBindingContainer : KeyBindingContainer { - public override IEnumerable DefaultKeyBindings => new[] + public override IEnumerable DefaultKeyBindings => new[] { new KeyBinding(InputKey.MouseLeft, TestAction.Down), }; From f42a6270bbd750e2539ddad3ff97c0adb29ee521 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 14:53:55 +0900 Subject: [PATCH 051/202] Update framework (again) for native libs fix --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 919d83f8db..db5c933c41 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ac014f2964..5e9e90c78f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -28,7 +28,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 799042626b..225cf981f2 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From e0a4a666c8e5fa8224fae065d3597b49fa747103 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 15:01:16 +0900 Subject: [PATCH 052/202] Remove unnecessary workaround (mentioned package is pinned by SignalR to a working version) --- osu.Game/osu.Game.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5e9e90c78f..301ee39a61 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,8 +18,6 @@ - - From 7c612ec5561225b2a618bf11915aa693e20e7cf6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 15:11:03 +0900 Subject: [PATCH 053/202] Remove global.json --- global.json | 10 ---------- osu.sln | 1 - 2 files changed, 11 deletions(-) delete mode 100644 global.json diff --git a/global.json b/global.json deleted file mode 100644 index f5aaffcd3d..0000000000 --- a/global.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "sdk": { - "allowPrerelease": false, - "rollForward": "minor", - "version": "5.0.100" - }, - "msbuild-sdks": { - "Microsoft.Build.Traversal": "3.0.2" - } -} \ No newline at end of file diff --git a/osu.sln b/osu.sln index 1d64f6ff10..c9453359b1 100644 --- a/osu.sln +++ b/osu.sln @@ -57,7 +57,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig Directory.Build.props = Directory.Build.props - global.json = global.json osu.Android.props = osu.Android.props osu.iOS.props = osu.iOS.props CodeAnalysis\osu.ruleset = CodeAnalysis\osu.ruleset From 3f8834030416aeb80f5746a37999a83c16064d86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 15:17:38 +0900 Subject: [PATCH 054/202] Restore previous exception handling flow for stable path lookup --- osu.Desktop/OsuGameDesktop.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 55e42b160e..d1515acafa 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -59,10 +59,14 @@ namespace osu.Desktop if (OperatingSystem.IsWindows()) { - stableInstallPath = getStableInstallPathFromRegistry(); + try + { + stableInstallPath = getStableInstallPathFromRegistry(); - if (checkExists(stableInstallPath)) - return stableInstallPath; + if (!string.IsNullOrEmpty(stableInstallPath) && checkExists(stableInstallPath)) + return stableInstallPath; + } + catch { } } stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!"); From d023ad8ad1a03b500f13b90ca5d1d24a75e182ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 15:18:29 +0900 Subject: [PATCH 055/202] Remove assert messages --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 8278ff9adf..35b3bfc1f8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Gameplay switch (args.Action) { case NotifyCollectionChangedAction.Add: - Debug.Assert(args.NewItems != null, "args.NewItems != null"); + Debug.Assert(args.NewItems != null); foreach (int user in args.NewItems) { @@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Gameplay break; case NotifyCollectionChangedAction.Remove: - Debug.Assert(args.OldItems != null, "args.OldItems != null"); + Debug.Assert(args.OldItems != null); foreach (int user in args.OldItems) { From b8c85ef017184b8672adb80401375bd3c8c8e224 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Jan 2021 16:03:12 +0900 Subject: [PATCH 056/202] Revert polling changes to fix participant list display It turns out this polling was necessary to get extra data that isn't included in the main listing request. It was removed deemed useless, and in order to fix the order of rooms changing when selecting a room. Weirdly, I can't reproduce this happening any more, and on close inspection of the code can't see how it could happen in the first place. For now, let's revert this change and iterate from there, if/when the same issue arises again. I've discussed avoiding this second poll by potentially including more data (just `user_id`s?) in the main listing request, but not 100% sure on this - even if the returned data is minimal it's an extra join server-side, which could cause performance issues for large numbers of rooms. --- .../TestSceneMultiplayerRoomManager.cs | 1 + .../OnlinePlay/Multiplayer/Multiplayer.cs | 5 +++- .../Multiplayer/MultiplayerRoomManager.cs | 28 ++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs index 80d1acd145..7a3845cbf3 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerRoomManager.cs @@ -143,6 +143,7 @@ namespace osu.Game.Tests.Visual.Multiplayer RoomManager = { TimeBetweenListingPolls = { Value = 1 }, + TimeBetweenSelectionPolls = { Value = 1 } } }; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 310617a0bc..76f5c74433 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -33,6 +33,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!this.IsCurrentScreen()) { multiplayerRoomManager.TimeBetweenListingPolls.Value = 0; + multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0; } else { @@ -40,16 +41,18 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { case LoungeSubScreen _: multiplayerRoomManager.TimeBetweenListingPolls.Value = isIdle ? 120000 : 15000; + multiplayerRoomManager.TimeBetweenSelectionPolls.Value = isIdle ? 120000 : 15000; break; // Don't poll inside the match or anywhere else. default: multiplayerRoomManager.TimeBetweenListingPolls.Value = 0; + multiplayerRoomManager.TimeBetweenSelectionPolls.Value = 0; break; } } - Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value})"); + Logger.Log($"Polling adjusted (listing: {multiplayerRoomManager.TimeBetweenListingPolls.Value}, selection: {multiplayerRoomManager.TimeBetweenSelectionPolls.Value})"); } protected override Room CreateNewRoom() diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index 5c327266a3..3cb263298f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private StatefulMultiplayerClient multiplayerClient { get; set; } public readonly Bindable TimeBetweenListingPolls = new Bindable(); - + public readonly Bindable TimeBetweenSelectionPolls = new Bindable(); private readonly IBindable isConnected = new Bindable(); private readonly Bindable allowPolling = new Bindable(); @@ -119,6 +119,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer TimeBetweenPolls = { BindTarget = TimeBetweenListingPolls }, AllowPolling = { BindTarget = allowPolling } }, + new MultiplayerSelectionPollingComponent + { + TimeBetweenPolls = { BindTarget = TimeBetweenSelectionPolls }, + AllowPolling = { BindTarget = allowPolling } + } }; private class MultiplayerListingPollingComponent : ListingPollingComponent @@ -141,5 +146,26 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); } + + private class MultiplayerSelectionPollingComponent : SelectionPollingComponent + { + public readonly IBindable AllowPolling = new Bindable(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + AllowPolling.BindValueChanged(allowPolling => + { + if (!allowPolling.NewValue) + return; + + if (IsLoaded) + PollImmediately(); + }); + } + + protected override Task Poll() => !AllowPolling.Value ? Task.CompletedTask : base.Poll(); + } } } From ede5abdba4eb0f88806c38790c7a622546f70af9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Jan 2021 18:05:29 +0900 Subject: [PATCH 057/202] Fix unstable multiplayer room ordering when selection is made --- .../OnlinePlay/Components/SelectionPollingComponent.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs index 0eec155060..dcf3c94b76 100644 --- a/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/SelectionPollingComponent.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -47,9 +48,11 @@ namespace osu.Game.Screens.OnlinePlay.Components pollReq.Success += result => { - var rooms = new List(roomManager.Rooms); + // existing rooms need to be ordered by their position because the received of NotifyRoomsReceives expects to be able to sort them based on this order. + var rooms = new List(roomManager.Rooms.OrderBy(r => r.Position.Value)); int index = rooms.FindIndex(r => r.RoomID.Value == result.RoomID.Value); + if (index < 0) return; From 2b578e97e532fc0bb215566b8bd34df25d1d4625 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Jan 2021 18:25:32 +0900 Subject: [PATCH 058/202] Fix deadlock scenario when calculating fallback difficulty The previous code would run a calcaulation for the beatmap's own ruleset if the current one failed. While this does make sense, with the current way we use this component (and the implementation flow) it is quite unsafe. The to the call on `.Result` in the `catch` block, this would 100% deadlock due to the thread concurrency of the `ThreadedTaskScheduler` being 1. Even if the nested run could be run inline (it should be), the task scheduler won't even get to the point of checking whether this is feasible due to it being saturated by the already running task. I'm not sure if we still need this fallback lookup logic. After removing it, it's feasible that 0 stars will be returned during the scenario that previously caused a deadlock, but I don't necessarily think this is incorrect. There may be another reason for this needing to exist which I'm not aware of (diffcalc?) but if that's the case we may want to move the try-catch handling to the point of usage. To reproduce the deadlock scenario with 100% success (the repro instructions in the linked issue aren't that simple and require some patience and good timing), the main portion of the lookup can be changed to randomly trigger a nested lookup: ``` if (RNG.NextSingle() > 0.5f) return GetAsync(new DifficultyCacheLookup(key.Beatmap, key.Beatmap.Ruleset, key.OrderedMods)).Result; else return new StarDifficulty(attributes); ``` After switching beatmap once or twice, pausing debug and viewing the state of threads should show exactly what is going on. --- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 3b58062add..37d262abe5 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -260,17 +260,10 @@ namespace osu.Game.Beatmaps } catch (BeatmapInvalidForRulesetException e) { - // Conversion has failed for the given ruleset, so return the difficulty in the beatmap's default ruleset. - - // Ensure the beatmap's default ruleset isn't the one already being converted to. - // This shouldn't happen as it means something went seriously wrong, but if it does an endless loop should be avoided. if (rulesetInfo.Equals(beatmapInfo.Ruleset)) - { Logger.Error(e, $"Failed to convert {beatmapInfo.OnlineBeatmapID} to the beatmap's default ruleset ({beatmapInfo.Ruleset})."); - return new StarDifficulty(); - } - return GetAsync(new DifficultyCacheLookup(key.Beatmap, key.Beatmap.Ruleset, key.OrderedMods)).Result; + return new StarDifficulty(); } catch { From ed78be825f9a988df3920fdbda730120bebfe125 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 15:47:41 +0900 Subject: [PATCH 059/202] Fix editor timeline not snapping on non-precise wheel scroll For wheel input with precision, we still prefer exact tracking for now. May change this in the future based on feedback from mappers, but it makes little sense to do non-snapped scrolling when input is coming from a non-precise source. --- .../Screens/Edit/Compose/Components/Timeline/Timeline.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 20836c0e68..12f7625bf9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -138,6 +138,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline scrollToTrackTime(); } + protected override bool OnScroll(ScrollEvent e) + { + // if this is not a precision scroll event, let the editor handle the seek itself (for snapping support) + if (!e.AltPressed && !e.IsPrecise) + return false; + + return base.OnScroll(e); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); From 04fa32bc34852ba79a249529f627b9a6f8aa6dd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 16:14:21 +0900 Subject: [PATCH 060/202] Rename and add xmldoc for smooth seeking method --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- .../Timelines/Summary/Parts/MarkerPart.cs | 2 +- .../Compose/Components/BlueprintContainer.cs | 2 +- osu.Game/Screens/Edit/EditorClock.cs | 33 +++++++++++-------- .../Screens/Edit/Timing/ControlPointTable.cs | 2 +- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 35852f60ea..e927951d0a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -332,7 +332,7 @@ namespace osu.Game.Rulesets.Edit EditorBeatmap.Add(hitObject); if (EditorClock.CurrentTime < hitObject.StartTime) - EditorClock.SeekTo(hitObject.StartTime); + EditorClock.SeekSmoothlyTo(hitObject.StartTime); } } 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 9e9ac93d23..5a2214509c 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts return; float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); - editorClock.SeekTo(markerPos / DrawWidth * editorClock.TrackLength); + editorClock.SeekSmoothlyTo(markerPos / DrawWidth * editorClock.TrackLength); }); } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 0b45bd5597..5371beac60 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -170,7 +170,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (clickedBlueprint == null || SelectionHandler.SelectedBlueprints.FirstOrDefault(b => b.IsHovered) != clickedBlueprint) return false; - EditorClock?.SeekTo(clickedBlueprint.HitObject.StartTime); + EditorClock?.SeekSmoothlyTo(clickedBlueprint.HitObject.StartTime); return true; } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 148eef6c93..c651d6a7c4 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -111,7 +111,7 @@ namespace osu.Game.Screens.Edit if (!snapped || ControlPointInfo.TimingPoints.Count == 0) { - SeekTo(seekTime); + SeekSmoothlyTo(seekTime); return; } @@ -145,11 +145,11 @@ namespace osu.Game.Screens.Edit // Ensure the sought point is within the boundaries seekTime = Math.Clamp(seekTime, 0, TrackLength); - SeekTo(seekTime); + SeekSmoothlyTo(seekTime); } /// - /// The current time of this clock, include any active transform seeks performed via . + /// The current time of this clock, include any active transform seeks performed via . /// public double CurrentTimeAccurate => Transforms.OfType().FirstOrDefault()?.EndValue ?? CurrentTime; @@ -182,6 +182,23 @@ namespace osu.Game.Screens.Edit return underlyingClock.Seek(position); } + /// + /// Seek smoothly to the provided destination. + /// Use to perform an immediate seek. + /// + /// + public void SeekSmoothlyTo(double seekDestination) + { + seekingOrStopped.Value = true; + + if (IsRunning) + Seek(seekDestination); + else + { + transformSeekTo(seekDestination, transform_time, Easing.OutQuint); + } + } + public void ResetSpeedAdjustments() => underlyingClock.ResetSpeedAdjustments(); double IAdjustableClock.Rate @@ -243,16 +260,6 @@ namespace osu.Game.Screens.Edit } } - public void SeekTo(double seekDestination) - { - seekingOrStopped.Value = true; - - if (IsRunning) - Seek(seekDestination); - else - transformSeekTo(seekDestination, transform_time, Easing.OutQuint); - } - private void transformSeekTo(double seek, double duration = 0, Easing easing = Easing.None) => this.TransformTo(this.PopulateTransform(new TransformSeek(), seek, duration, easing)); diff --git a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs index 89d3c36250..e4b9150df1 100644 --- a/osu.Game/Screens/Edit/Timing/ControlPointTable.cs +++ b/osu.Game/Screens/Edit/Timing/ControlPointTable.cs @@ -206,7 +206,7 @@ namespace osu.Game.Screens.Edit.Timing Action = () => { selectedGroup.Value = controlGroup; - clock.SeekTo(controlGroup.Time); + clock.SeekSmoothlyTo(controlGroup.Time); }; } From 831c06a3c7c02549fe9bab75ff83afaaf30fa1ec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 16:14:38 +0900 Subject: [PATCH 061/202] Expose and consume boolean covering whether an ongoing smooth seek is running --- .../Edit/Compose/Components/Timeline/Timeline.cs | 10 ++++++---- osu.Game/Screens/Edit/EditorClock.cs | 11 +++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 20836c0e68..7df4f1ae7d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -146,12 +146,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline seekTrackToCurrent(); else if (!editorClock.IsRunning) { - // The track isn't running. There are two cases we have to be wary of: - // 1) The user flick-drags on this timeline: We want the track to follow us - // 2) The user changes the track time through some other means (scrolling in the editor or overview timeline): We want to follow the track time + // The track isn't running. There are three cases we have to be wary of: + // 1) The user flick-drags on this timeline and we are applying an interpolated seek on the clock, until interrupted by 2 or 3. + // 2) The user changes the track time through some other means (scrolling in the editor or overview timeline; clicking a hitobject etc.). We want the timeline to track the clock's time. + // 3) An ongoing seek transform is running from an external seek. We want the timeline to track the clock's time. // The simplest way to cover both cases is by checking whether the scroll position has changed and the audio hasn't been changed externally - if (Current != lastScrollPosition && editorClock.CurrentTime == lastTrackTime) + // Checking IsSeeking covers the third case, where the transform may not have been applied yet. + if (Current != lastScrollPosition && editorClock.CurrentTime == lastTrackTime && !editorClock.IsSeeking) seekTrackToCurrent(); else scrollToTrackTime(); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index c651d6a7c4..ec0f5d7154 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -35,6 +35,11 @@ namespace osu.Game.Screens.Edit private readonly Bindable seekingOrStopped = new Bindable(true); + /// + /// Whether a seek is currently in progress. True for the duration of a seek performed via . + /// + public bool IsSeeking { get; private set; } + public EditorClock(WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) : this(beatmap.Beatmap.ControlPointInfo, beatmap.Track.Length, beatDivisor) { @@ -176,7 +181,7 @@ namespace osu.Game.Screens.Edit public bool Seek(double position) { - seekingOrStopped.Value = true; + seekingOrStopped.Value = IsSeeking = true; ClearTransforms(); return underlyingClock.Seek(position); @@ -246,6 +251,8 @@ namespace osu.Game.Screens.Edit { if (seekingOrStopped.Value) { + IsSeeking &= Transforms.Any(); + if (track.Value?.IsRunning != true) { // seeking in the editor can happen while the track isn't running. @@ -256,7 +263,7 @@ namespace osu.Game.Screens.Edit // we are either running a seek tween or doing an immediate seek. // in the case of an immediate seek the seeking bool will be set to false after one update. // this allows for silencing hit sounds and the likes. - seekingOrStopped.Value = Transforms.Any(); + seekingOrStopped.Value = IsSeeking; } } From 88a27124c095f5a3cff7eaddaaab92cfe1832d55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:13:27 +0900 Subject: [PATCH 062/202] Make long spinner test longer and fix step name --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 496b1b3559..c22b1dc407 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Tests [TestCase(true)] public void TestLongSpinner(bool autoplay) { - AddStep("Very short spinner", () => SetContents(() => testSingle(5, autoplay, 2000))); + AddStep("Very long spinner", () => SetContents(() => testSingle(5, autoplay, 4000))); AddUntilStep("Wait for completion", () => drawableSpinner.Result.HasResult); AddUntilStep("Check correct progress", () => drawableSpinner.Progress == (autoplay ? 1 : 0)); } From 6adb6b6700b4b19336955b397d5939679919d70b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:13:52 +0900 Subject: [PATCH 063/202] Fix spinner tests not playing spinning sound due to empty hitsamples --- osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index c22b1dc407..f697a77d94 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.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.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mods; @@ -55,7 +57,11 @@ namespace osu.Game.Rulesets.Osu.Tests var spinner = new Spinner { StartTime = Time.Current + delay, - EndTime = Time.Current + delay + length + EndTime = Time.Current + delay + length, + Samples = new List + { + new HitSampleInfo("hitnormal") + } }; spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize }); From 8a6857f151373dc2bb6edeb5239efef9932e447f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:16:12 +0900 Subject: [PATCH 064/202] Add support for playing a SkinnableSample without restarting it --- osu.Game/Skinning/PausableSkinnableSound.cs | 4 ++-- osu.Game/Skinning/SkinnableSound.cs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/PausableSkinnableSound.cs b/osu.Game/Skinning/PausableSkinnableSound.cs index 4b6099e85f..cb5234c847 100644 --- a/osu.Game/Skinning/PausableSkinnableSound.cs +++ b/osu.Game/Skinning/PausableSkinnableSound.cs @@ -67,7 +67,7 @@ namespace osu.Game.Skinning } } - public override void Play() + public override void Play(bool restart = true) { cancelPendingStart(); RequestedPlaying = true; @@ -75,7 +75,7 @@ namespace osu.Game.Skinning if (samplePlaybackDisabled.Value) return; - base.Play(); + base.Play(restart); } public override void Stop() diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 645c08cd00..b841f99598 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -119,12 +119,13 @@ namespace osu.Game.Skinning /// /// Plays the samples. /// - public virtual void Play() + /// Whether to play the sample from the beginning. + public virtual void Play(bool restart = true) { samplesContainer.ForEach(c => { if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0) - c.Play(); + c.Play(restart); }); } From 767c76921faa69b9f648e14fec3ab95f466abce1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:17:10 +0900 Subject: [PATCH 065/202] Adjust transition time of spinner sound --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 1f3bcece0c..4f61ab4a9a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -131,11 +131,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (tracking.NewValue) { spinningSample?.Play(); - spinningSample?.VolumeTo(1, 200); + spinningSample?.VolumeTo(1, 300); } else { - spinningSample?.VolumeTo(0, 200).Finally(_ => spinningSample.Stop()); + spinningSample?.VolumeTo(0, 300).Finally(_ => spinningSample.Stop()); } } From 311f8b70178cb5ebf0fdc23824fdae53b8336a7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:17:51 +0900 Subject: [PATCH 066/202] Only restart spinning sample if it was not already playing --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 4f61ab4a9a..c5ae195274 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { if (tracking.NewValue) { - spinningSample?.Play(); + spinningSample?.Play(!spinningSample.IsPlaying); spinningSample?.VolumeTo(1, 300); } else From 14b33236828438a72b5c6b4acc4edbba9e26d985 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:18:15 +0900 Subject: [PATCH 067/202] Use OnComplete instead of Finally to avoid potentially stopping on aborted transforms --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index c5ae195274..56aedebed3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } else { - spinningSample?.VolumeTo(0, 300).Finally(_ => spinningSample.Stop()); + spinningSample?.VolumeTo(0, 300).OnComplete(_ => spinningSample.Stop()); } } From d6e6b4bbeea9ec532b7d927fa3d38c7e1efbf49f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 15 Jan 2021 17:34:01 +0900 Subject: [PATCH 068/202] Revert forced cloning of ControlPointInfo This reverts commit 3c3e860dbc34d37855b79786a1abb754af1667e8. Closes https://github.com/ppy/osu/issues/11491. --- osu.Game/Beatmaps/Beatmap.cs | 10 +--------- osu.Game/Beatmaps/IBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 ++ osu.Game/Screens/Edit/EditorBeatmap.cs | 6 +++++- osu.Game/Screens/Play/GameplayBeatmap.cs | 6 +++++- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index be2006e67a..5435e86dfd 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -50,15 +50,7 @@ namespace osu.Game.Beatmaps IBeatmap IBeatmap.Clone() => Clone(); - public Beatmap Clone() - { - var clone = (Beatmap)MemberwiseClone(); - - clone.ControlPointInfo = ControlPointInfo.CreateCopy(); - // todo: deep clone other elements as required. - - return clone; - } + public Beatmap Clone() => (Beatmap)MemberwiseClone(); } public class Beatmap : Beatmap diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 8f27e0b0e9..7dd85e1232 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps /// /// The control points in this beatmap. /// - ControlPointInfo ControlPointInfo { get; } + ControlPointInfo ControlPointInfo { get; set; } /// /// The breaks in this beatmap. diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 30382c444f..d25adca92b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -111,6 +111,8 @@ namespace osu.Game.Beatmaps // Convert IBeatmap converted = converter.Convert(cancellationSource.Token); + converted.ControlPointInfo = converted.ControlPointInfo.CreateCopy(); + // Apply conversion mods to the result foreach (var mod in mods.OfType()) { diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 165d2ba278..a54a95f59d 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -74,7 +74,11 @@ namespace osu.Game.Screens.Edit public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; - public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; + public ControlPointInfo ControlPointInfo + { + get => PlayableBeatmap.ControlPointInfo; + set => PlayableBeatmap.ControlPointInfo = value; + } public List Breaks => PlayableBeatmap.Breaks; diff --git a/osu.Game/Screens/Play/GameplayBeatmap.cs b/osu.Game/Screens/Play/GameplayBeatmap.cs index 64894544f4..565595656f 100644 --- a/osu.Game/Screens/Play/GameplayBeatmap.cs +++ b/osu.Game/Screens/Play/GameplayBeatmap.cs @@ -29,7 +29,11 @@ namespace osu.Game.Screens.Play public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; - public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; + public ControlPointInfo ControlPointInfo + { + get => PlayableBeatmap.ControlPointInfo; + set => PlayableBeatmap.ControlPointInfo = value; + } public List Breaks => PlayableBeatmap.Breaks; From 3c1a86d11deefc694a00ebad3369c563a07168de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 15 Jan 2021 22:04:45 +0100 Subject: [PATCH 069/202] Trim braces for consistency --- osu.Game/Skinning/LegacySkin.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 7397e3d08b..090ffaebd7 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -381,9 +381,7 @@ namespace osu.Game.Skinning var particle = getParticleTexture(resultComponent.Component); if (particle != null) - { return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, particle); - } else return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); } From 112967c1e8d0fd75c24aed6276afd95140687e79 Mon Sep 17 00:00:00 2001 From: Mysfit Date: Fri, 15 Jan 2021 23:46:46 -0500 Subject: [PATCH 070/202] Created base class for testing beatmap colours. --- .../TestSceneLegacyBeatmapSkin.cs | 191 +++++------------- .../TestSceneLegacyBeatmapSkin.cs | 178 +++++----------- .../Beatmaps/LegacyBeatmapSkinColourTest.cs | 147 ++++++++++++++ 3 files changed, 245 insertions(+), 271 deletions(-) create mode 100644 osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs index 12ceaaa6fa..89298242e5 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs @@ -2,13 +2,10 @@ // 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.Audio; -using osu.Framework.Bindables; -using osu.Framework.IO.Stores; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -17,179 +14,114 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Skinning; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects; -using osu.Game.Screens.Play; using osu.Game.Skinning; -using osu.Game.Tests.Visual; +using osu.Game.Tests.Beatmaps; using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests { - public class TestSceneLegacyBeatmapSkin : ScreenTestScene + public class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest { [Resolved] private AudioManager audio { get; set; } - private readonly Bindable beatmapSkins = new Bindable(); - private readonly Bindable beatmapColours = new Bindable(); - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); - config.BindWith(OsuSetting.BeatmapColours, beatmapColours); + config.BindWith(OsuSetting.BeatmapSkins, BeatmapSkins); + config.BindWith(OsuSetting.BeatmapColours, BeatmapColours); } [TestCase(true, true)] [TestCase(true, false)] [TestCase(false, true)] [TestCase(false, false)] - public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) + public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, true); - AddStep("load coloured beatmap", () => player = loadBeatmap(userHasCustomColours, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); + base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin); + AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); } [TestCase(true)] [TestCase(false)] - public void TestBeatmapComboColoursOverride(bool useBeatmapSkin) + public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, false); - AddStep("load coloured beatmap", () => player = loadBeatmap(true, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is user custom skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); + base.TestBeatmapComboColoursOverride(useBeatmapSkin); + AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours)); } [TestCase(true)] [TestCase(false)] - public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) + public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, false); - AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); + base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin); + AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } [TestCase(true, true)] [TestCase(false, true)] [TestCase(true, false)] [TestCase(false, false)] - public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) + public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, useBeatmapColour); - AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false); + base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour); + AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } [TestCase(true, true)] [TestCase(false, true)] [TestCase(true, false)] [TestCase(false, false)] - public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) + public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, useBeatmapColour); - AddStep("load custom-skin colour", () => player = loadBeatmap(true, false)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is custom user skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false); + base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour); + AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours)); } [TestCase(true)] [TestCase(false)] public void TestBeatmapHyperDashColours(bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, true); - AddStep("load custom-skin colour", () => player = loadBeatmap(true, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is custom hyper dash colours", () => player.UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR); - AddAssert("is custom hyper dash after image colours", () => player.UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); - AddAssert("is custom hyper dash fruit colours", () => player.UsableHyperDashFruitColour == TestBeatmapSkin.HYPER_DASH_FRUIT_COLOUR); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); + ConfigureTest(useBeatmapSkin, true, true); + AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == CatchTestBeatmapSkin.HYPER_DASH_COLOUR); + AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == CatchTestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); + AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == CatchTestBeatmapSkin.HYPER_DASH_FRUIT_COLOUR); } [TestCase(true)] [TestCase(false)] public void TestBeatmapHyperDashColoursOverride(bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, false); - AddStep("load custom-skin colour", () => player = loadBeatmap(true, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is custom hyper dash colours", () => player.UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR); - AddAssert("is custom hyper dash after image colours", () => player.UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); - AddAssert("is custom hyper dash fruit colours", () => player.UsableHyperDashFruitColour == TestSkin.HYPER_DASH_FRUIT_COLOUR); + TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); + ConfigureTest(useBeatmapSkin, false, true); + AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == CatchTestSkin.HYPER_DASH_COLOUR); + AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == CatchTestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); + AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == CatchTestSkin.HYPER_DASH_FRUIT_COLOUR); } - private ExposedPlayer loadBeatmap(bool userHasCustomColours, bool beatmapHasColours) + protected override ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new CatchExposedPlayer(userHasCustomColours); + + private class CatchExposedPlayer : ExposedPlayer { - ExposedPlayer player; - - Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasColours); - - LoadScreen(player = new ExposedPlayer(userHasCustomColours)); - - return player; - } - - private void configureSettings(bool beatmapSkins, bool beatmapColours) - { - AddStep($"{(beatmapSkins ? "enable" : "disable")} beatmap skins", () => + public CatchExposedPlayer(bool userHasCustomColours) + : base(userHasCustomColours) { - this.beatmapSkins.Value = beatmapSkins; - }); - AddStep($"{(beatmapColours ? "enable" : "disable")} beatmap colours", () => - { - this.beatmapColours.Value = beatmapColours; - }); - } - - private class ExposedPlayer : Player - { - private readonly bool userHasCustomColours; - - public ExposedPlayer(bool userHasCustomColours) - : base(new PlayerConfiguration - { - AllowPause = false, - ShowResults = false, - }) - { - this.userHasCustomColours = userHasCustomColours; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(new TestSkin(userHasCustomColours)); + dependencies.CacheAs(new CatchTestSkin(UserHasCustomColours)); return dependencies; } - public IReadOnlyList UsableComboColours => - GameplayClockContainer.ChildrenOfType() - .First() - .GetConfig>(GlobalSkinColours.ComboColours)?.Value; - public Color4 UsableHyperDashColour => GameplayClockContainer.ChildrenOfType() .First() @@ -223,17 +155,14 @@ namespace osu.Game.Rulesets.Catch.Tests } } - private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + private class CatchCustomSkinWorkingBeatmap : CustomSkinWorkingBeatmap { - private readonly bool hasColours; - - public CustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) - : base(createBeatmap(new CatchRuleset().RulesetInfo), null, null, audio) + public CatchCustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) + : base(createBeatmap(new CatchRuleset().RulesetInfo), audio, hasColours) { - this.hasColours = hasColours; } - protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, hasColours); + protected override ISkin GetSkin() => new CatchTestBeatmapSkin(BeatmapInfo, HasColours); private static IBeatmap createBeatmap(RulesetInfo ruleset) { @@ -297,26 +226,19 @@ namespace osu.Game.Rulesets.Catch.Tests } } - private class TestBeatmapSkin : LegacyBeatmapSkin + private class CatchTestBeatmapSkin : TestBeatmapSkin { - public static Color4[] Colours { get; } = - { - new Color4(50, 100, 150, 255), - new Color4(40, 80, 120, 255), - }; - public static readonly Color4 HYPER_DASH_COLOUR = Color4.DarkBlue; public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.DarkCyan; public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.DarkGoldenrod; - public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) - : base(beatmap, new ResourceStore(), null) + public CatchTestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) + : base(beatmap, hasColours) { if (hasColours) { - Configuration.AddComboColours(Colours); Configuration.CustomColours.Add(CatchSkinColour.HyperDash.ToString(), HYPER_DASH_COLOUR); Configuration.CustomColours.Add(CatchSkinColour.HyperDashAfterImage.ToString(), HYPER_DASH_AFTER_IMAGE_COLOUR); Configuration.CustomColours.Add(CatchSkinColour.HyperDashFruit.ToString(), HYPER_DASH_FRUIT_COLOUR); @@ -324,37 +246,24 @@ namespace osu.Game.Rulesets.Catch.Tests } } - private class TestSkin : LegacySkin, ISkinSource + private class CatchTestSkin : TestSkin { - public static Color4[] Colours { get; } = - { - new Color4(150, 100, 50, 255), - new Color4(20, 20, 20, 255), - }; - public static readonly Color4 HYPER_DASH_COLOUR = Color4.LightBlue; public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.LightCoral; public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.LightCyan; - public TestSkin(bool hasCustomColours) - : base(new SkinInfo(), new ResourceStore(), null, string.Empty) + public CatchTestSkin(bool hasCustomColours) + : base(hasCustomColours) { if (hasCustomColours) { - Configuration.AddComboColours(Colours); Configuration.CustomColours.Add(CatchSkinColour.HyperDash.ToString(), HYPER_DASH_COLOUR); Configuration.CustomColours.Add(CatchSkinColour.HyperDashAfterImage.ToString(), HYPER_DASH_AFTER_IMAGE_COLOUR); Configuration.CustomColours.Add(CatchSkinColour.HyperDashFruit.ToString(), HYPER_DASH_FRUIT_COLOUR); } } - - public event Action SourceChanged - { - add { } - remove { } - } } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 22b028906f..095ce63ec5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -1,168 +1,113 @@ // Copyright (c) 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.Audio; -using osu.Framework.Bindables; -using osu.Framework.IO.Stores; -using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Screens.Play; using osu.Game.Skinning; -using osu.Game.Tests.Visual; +using osu.Game.Tests.Beatmaps; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Tests { - public class TestSceneLegacyBeatmapSkin : ScreenTestScene + public class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest { [Resolved] private AudioManager audio { get; set; } - private readonly Bindable beatmapSkins = new Bindable(); - private readonly Bindable beatmapColours = new Bindable(); - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); - config.BindWith(OsuSetting.BeatmapColours, beatmapColours); + config.BindWith(OsuSetting.BeatmapSkins, BeatmapSkins); + config.BindWith(OsuSetting.BeatmapColours, BeatmapColours); } [TestCase(true, true)] [TestCase(true, false)] [TestCase(false, true)] [TestCase(false, false)] - public void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) + public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, true); - AddStep("load coloured beatmap", () => player = loadBeatmap(userHasCustomColours, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); + TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true); + base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin); + AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours)); } [TestCase(true)] [TestCase(false)] - public void TestBeatmapComboColoursOverride(bool useBeatmapSkin) + public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, false); - AddStep("load coloured beatmap", () => player = loadBeatmap(true, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is user custom skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true); + base.TestBeatmapComboColoursOverride(useBeatmapSkin); + AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours)); } [TestCase(true)] [TestCase(false)] - public void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) + public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, false); - AddStep("load coloured beatmap", () => player = loadBeatmap(false, true)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true); + base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin); + AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } [TestCase(true, true)] [TestCase(false, true)] [TestCase(true, false)] [TestCase(false, false)] - public void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) + public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, useBeatmapColour); - AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); + TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, false); + base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour); + AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours)); } [TestCase(true, true)] [TestCase(false, true)] [TestCase(true, false)] [TestCase(false, false)] - public void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) + public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) { - ExposedPlayer player = null; - - configureSettings(useBeatmapSkin, useBeatmapColour); - AddStep("load custom-skin colour", () => player = loadBeatmap(true, false)); - AddUntilStep("wait for player", () => player.IsLoaded); - - AddAssert("is custom user skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours)); + TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, false); + base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour); + AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours)); } - private ExposedPlayer loadBeatmap(bool userHasCustomColours, bool beatmapHasColours) + protected override ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new OsuExposedPlayer(userHasCustomColours); + + private class OsuExposedPlayer : ExposedPlayer { - ExposedPlayer player; - - Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasColours); - - LoadScreen(player = new ExposedPlayer(userHasCustomColours)); - - return player; - } - - private void configureSettings(bool beatmapSkins, bool beatmapColours) - { - AddStep($"{(beatmapSkins ? "enable" : "disable")} beatmap skins", () => + public OsuExposedPlayer(bool userHasCustomColours) + : base(userHasCustomColours) { - this.beatmapSkins.Value = beatmapSkins; - }); - AddStep($"{(beatmapColours ? "enable" : "disable")} beatmap colours", () => - { - this.beatmapColours.Value = beatmapColours; - }); - } - - private class ExposedPlayer : Player - { - private readonly bool userHasCustomColours; - - public ExposedPlayer(bool userHasCustomColours) - : base(new PlayerConfiguration - { - AllowPause = false, - ShowResults = false, - }) - { - this.userHasCustomColours = userHasCustomColours; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(new TestSkin(userHasCustomColours)); + dependencies.CacheAs(new OsuTestSkin(UserHasCustomColours)); return dependencies; } - - public IReadOnlyList UsableComboColours => - GameplayClockContainer.ChildrenOfType() - .First() - .GetConfig>(GlobalSkinColours.ComboColours)?.Value; } - private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + private class OsuCustomSkinWorkingBeatmap : CustomSkinWorkingBeatmap { private readonly bool hasColours; - public CustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) - : base(new Beatmap + public OsuCustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) + : base(createBeatmap(), audio, hasColours) + { + this.hasColours = hasColours; + } + + protected override ISkin GetSkin() => new OsuTestBeatmapSkin(BeatmapInfo, hasColours); + + private static IBeatmap createBeatmap() => + new Beatmap { BeatmapInfo = { @@ -170,49 +115,22 @@ namespace osu.Game.Rulesets.Osu.Tests Ruleset = new OsuRuleset().RulesetInfo, }, HitObjects = { new HitCircle { Position = new Vector2(256, 192) } } - }, null, null, audio) - { - this.hasColours = hasColours; - } - - protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, hasColours); + }; } - private class TestBeatmapSkin : LegacyBeatmapSkin + private class OsuTestBeatmapSkin : TestBeatmapSkin { - public static Color4[] Colours { get; } = + public OsuTestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) + : base(beatmap, hasColours) { - new Color4(50, 100, 150, 255), - new Color4(40, 80, 120, 255), - }; - - public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) - : base(beatmap, new ResourceStore(), null) - { - if (hasColours) - Configuration.AddComboColours(Colours); } } - private class TestSkin : LegacySkin, ISkinSource + private class OsuTestSkin : TestSkin { - public static Color4[] Colours { get; } = + public OsuTestSkin(bool hasCustomColours) + : base(hasCustomColours) { - new Color4(150, 100, 50, 255), - new Color4(20, 20, 20, 255), - }; - - public TestSkin(bool hasCustomColours) - : base(new SkinInfo(), null, null, string.Empty) - { - if (hasCustomColours) - Configuration.AddComboColours(Colours); - } - - public event Action SourceChanged - { - add { } - remove { } } } } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs new file mode 100644 index 0000000000..b42c3ea70d --- /dev/null +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -0,0 +1,147 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; +using osu.Framework.IO.Stores; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Screens.Play; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK.Graphics; + +namespace osu.Game.Tests.Beatmaps +{ + public class LegacyBeatmapSkinColourTest : ScreenTestScene + { + protected readonly Bindable BeatmapSkins = new Bindable(); + protected readonly Bindable BeatmapColours = new Bindable(); + protected ExposedPlayer TestPlayer; + protected WorkingBeatmap TestBeatmap; + + public virtual void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin) => ConfigureTest(useBeatmapSkin, true, userHasCustomColours); + + public virtual void TestBeatmapComboColoursOverride(bool useBeatmapSkin) => ConfigureTest(useBeatmapSkin, false, true); + + public virtual void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin) => ConfigureTest(useBeatmapSkin, false, false); + + public virtual void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour) => ConfigureTest(useBeatmapSkin, useBeatmapColour, false); + + public virtual void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour) => ConfigureTest(useBeatmapSkin, useBeatmapColour, true); + + protected virtual void ConfigureTest(bool useBeatmapSkin, bool useBeatmapColours, bool userHasCustomColours) + { + configureSettings(useBeatmapSkin, useBeatmapColours); + AddStep($"load {(((CustomSkinWorkingBeatmap)TestBeatmap).HasColours ? "coloured " : "")} beatmap", () => TestPlayer = LoadBeatmap(userHasCustomColours)); + AddUntilStep("wait for player load", () => TestPlayer.IsLoaded); + } + + private void configureSettings(bool beatmapSkins, bool beatmapColours) + { + AddStep($"{(beatmapSkins ? "enable" : "disable")} beatmap skins", () => + { + BeatmapSkins.Value = beatmapSkins; + }); + AddStep($"{(beatmapColours ? "enable" : "disable")} beatmap colours", () => + { + BeatmapColours.Value = beatmapColours; + }); + } + + protected virtual ExposedPlayer LoadBeatmap(bool userHasCustomColours) + { + ExposedPlayer player; + + Beatmap.Value = TestBeatmap; + + LoadScreen(player = CreateTestPlayer(userHasCustomColours)); + + return player; + } + + protected virtual ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new ExposedPlayer(userHasCustomColours); + + protected class ExposedPlayer : Player + { + protected readonly bool UserHasCustomColours; + + public ExposedPlayer(bool userHasCustomColours) + : base(new PlayerConfiguration + { + AllowPause = false, + ShowResults = false, + }) + { + UserHasCustomColours = userHasCustomColours; + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(new TestSkin(UserHasCustomColours)); + return dependencies; + } + + public IReadOnlyList UsableComboColours => + GameplayClockContainer.ChildrenOfType() + .First() + .GetConfig>(GlobalSkinColours.ComboColours)?.Value; + } + + protected class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap + { + public readonly bool HasColours; + + public CustomSkinWorkingBeatmap(IBeatmap beatmap, AudioManager audio, bool hasColours) + : base(beatmap, null, null, audio) + { + HasColours = hasColours; + } + + protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, HasColours); + } + + protected class TestBeatmapSkin : LegacyBeatmapSkin + { + public static Color4[] Colours { get; } = + { + new Color4(50, 100, 150, 255), + new Color4(40, 80, 120, 255), + }; + + public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) + : base(beatmap, new ResourceStore(), null) + { + if (hasColours) + Configuration.AddComboColours(Colours); + } + } + + protected class TestSkin : LegacySkin, ISkinSource + { + public static Color4[] Colours { get; } = + { + new Color4(150, 100, 50, 255), + new Color4(20, 20, 20, 255), + }; + + public TestSkin(bool hasCustomColours) + : base(new SkinInfo(), new ResourceStore(), null, string.Empty) + { + if (hasCustomColours) + Configuration.AddComboColours(Colours); + } + + public event Action SourceChanged + { + add { } + remove { } + } + } + } +} From a3535f4b79a3634e31fe9fd935545b653558787f Mon Sep 17 00:00:00 2001 From: Mysfit Date: Sat, 16 Jan 2021 02:09:35 -0500 Subject: [PATCH 071/202] Further simplified beatmap colouring tests. --- .../TestSceneLegacyBeatmapSkin.cs | 144 ++---------------- .../TestSceneLegacyBeatmapSkin.cs | 38 ----- .../Beatmaps/LegacyBeatmapSkinColourTest.cs | 22 +++ 3 files changed, 35 insertions(+), 169 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs index 89298242e5..eea83ef7c1 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs @@ -1,22 +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; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Skinning; -using osu.Game.Rulesets.Catch.UI; -using osu.Game.Rulesets.Objects; using osu.Game.Skinning; using osu.Game.Tests.Beatmaps; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests @@ -90,9 +85,9 @@ namespace osu.Game.Rulesets.Catch.Tests { TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); ConfigureTest(useBeatmapSkin, true, true); - AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == CatchTestBeatmapSkin.HYPER_DASH_COLOUR); - AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == CatchTestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); - AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == CatchTestBeatmapSkin.HYPER_DASH_FRUIT_COLOUR); + AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR); + AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); + AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == TestBeatmapSkin.HYPER_DASH_FRUIT_COLOUR); } [TestCase(true)] @@ -101,9 +96,9 @@ namespace osu.Game.Rulesets.Catch.Tests { TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true); ConfigureTest(useBeatmapSkin, false, true); - AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == CatchTestSkin.HYPER_DASH_COLOUR); - AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == CatchTestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); - AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == CatchTestSkin.HYPER_DASH_FRUIT_COLOUR); + AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR); + AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR); + AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == TestSkin.HYPER_DASH_FRUIT_COLOUR); } protected override ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new CatchExposedPlayer(userHasCustomColours); @@ -115,13 +110,6 @@ namespace osu.Game.Rulesets.Catch.Tests { } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(new CatchTestSkin(UserHasCustomColours)); - return dependencies; - } - public Color4 UsableHyperDashColour => GameplayClockContainer.ChildrenOfType() .First() @@ -141,129 +129,23 @@ namespace osu.Game.Rulesets.Catch.Tests .Value ?? Color4.Red; } - private class TestJuiceStream : JuiceStream - { - public TestJuiceStream(float x) - { - X = x; - - Path = new SliderPath(new[] - { - new PathControlPoint(Vector2.Zero), - new PathControlPoint(new Vector2(30, 0)), - }); - } - } - private class CatchCustomSkinWorkingBeatmap : CustomSkinWorkingBeatmap { public CatchCustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) - : base(createBeatmap(new CatchRuleset().RulesetInfo), audio, hasColours) + : base(createBeatmap(), audio, hasColours) { } - protected override ISkin GetSkin() => new CatchTestBeatmapSkin(BeatmapInfo, HasColours); - - private static IBeatmap createBeatmap(RulesetInfo ruleset) - { - var beatmap = new Beatmap + private static IBeatmap createBeatmap() => + new Beatmap { BeatmapInfo = { - Ruleset = ruleset, - BaseDifficulty = new BeatmapDifficulty { CircleSize = 3.6f } - } + BeatmapSet = new BeatmapSetInfo(), + Ruleset = new CatchRuleset().RulesetInfo + }, + HitObjects = { new Fruit { StartTime = 1816, X = 56, NewCombo = true } } }; - - beatmap.ControlPointInfo.Add(0, new TimingControlPoint()); - - // Should produce a hyper-dash (edge case test) - beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 56, NewCombo = true }); - beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308, NewCombo = true }); - - double startTime = 3000; - - const float left_x = 0.02f * CatchPlayfield.WIDTH; - const float right_x = 0.98f * CatchPlayfield.WIDTH; - - createObjects(() => new Fruit { X = left_x }); - createObjects(() => new TestJuiceStream(right_x), 1); - createObjects(() => new TestJuiceStream(left_x), 1); - createObjects(() => new Fruit { X = right_x }); - createObjects(() => new Fruit { X = left_x }); - createObjects(() => new Fruit { X = right_x }); - createObjects(() => new TestJuiceStream(left_x), 1); - - beatmap.ControlPointInfo.Add(startTime, new TimingControlPoint - { - BeatLength = 50 - }); - - createObjects(() => new TestJuiceStream(left_x) - { - Path = new SliderPath(new[] - { - new PathControlPoint(Vector2.Zero), - new PathControlPoint(new Vector2(512, 0)) - }) - }, 1); - - return beatmap; - - void createObjects(Func createObject, int count = 3) - { - const float spacing = 140; - - for (int i = 0; i < count; i++) - { - var hitObject = createObject(); - hitObject.StartTime = startTime + i * spacing; - beatmap.HitObjects.Add(hitObject); - } - - startTime += 700; - } - } - } - - private class CatchTestBeatmapSkin : TestBeatmapSkin - { - public static readonly Color4 HYPER_DASH_COLOUR = Color4.DarkBlue; - - public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.DarkCyan; - - public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.DarkGoldenrod; - - public CatchTestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) - : base(beatmap, hasColours) - { - if (hasColours) - { - Configuration.CustomColours.Add(CatchSkinColour.HyperDash.ToString(), HYPER_DASH_COLOUR); - Configuration.CustomColours.Add(CatchSkinColour.HyperDashAfterImage.ToString(), HYPER_DASH_AFTER_IMAGE_COLOUR); - Configuration.CustomColours.Add(CatchSkinColour.HyperDashFruit.ToString(), HYPER_DASH_FRUIT_COLOUR); - } - } - } - - private class CatchTestSkin : TestSkin - { - public static readonly Color4 HYPER_DASH_COLOUR = Color4.LightBlue; - - public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.LightCoral; - - public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.LightCyan; - - public CatchTestSkin(bool hasCustomColours) - : base(hasCustomColours) - { - if (hasCustomColours) - { - Configuration.CustomColours.Add(CatchSkinColour.HyperDash.ToString(), HYPER_DASH_COLOUR); - Configuration.CustomColours.Add(CatchSkinColour.HyperDashAfterImage.ToString(), HYPER_DASH_AFTER_IMAGE_COLOUR); - Configuration.CustomColours.Add(CatchSkinColour.HyperDashFruit.ToString(), HYPER_DASH_FRUIT_COLOUR); - } - } } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index 095ce63ec5..c26419b0e8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -77,35 +77,13 @@ namespace osu.Game.Rulesets.Osu.Tests AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours)); } - protected override ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new OsuExposedPlayer(userHasCustomColours); - - private class OsuExposedPlayer : ExposedPlayer - { - public OsuExposedPlayer(bool userHasCustomColours) - : base(userHasCustomColours) - { - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(new OsuTestSkin(UserHasCustomColours)); - return dependencies; - } - } - private class OsuCustomSkinWorkingBeatmap : CustomSkinWorkingBeatmap { - private readonly bool hasColours; - public OsuCustomSkinWorkingBeatmap(AudioManager audio, bool hasColours) : base(createBeatmap(), audio, hasColours) { - this.hasColours = hasColours; } - protected override ISkin GetSkin() => new OsuTestBeatmapSkin(BeatmapInfo, hasColours); - private static IBeatmap createBeatmap() => new Beatmap { @@ -117,21 +95,5 @@ namespace osu.Game.Rulesets.Osu.Tests HitObjects = { new HitCircle { Position = new Vector2(256, 192) } } }; } - - private class OsuTestBeatmapSkin : TestBeatmapSkin - { - public OsuTestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) - : base(beatmap, hasColours) - { - } - } - - private class OsuTestSkin : TestSkin - { - public OsuTestSkin(bool hasCustomColours) - : base(hasCustomColours) - { - } - } } } diff --git a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs index b42c3ea70d..fb3432fbae 100644 --- a/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyBeatmapSkinColourTest.cs @@ -114,11 +114,22 @@ namespace osu.Game.Tests.Beatmaps new Color4(40, 80, 120, 255), }; + public static readonly Color4 HYPER_DASH_COLOUR = Color4.DarkBlue; + + public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.DarkCyan; + + public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.DarkGoldenrod; + public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours) : base(beatmap, new ResourceStore(), null) { if (hasColours) + { Configuration.AddComboColours(Colours); + Configuration.CustomColours.Add("HyperDash", HYPER_DASH_COLOUR); + Configuration.CustomColours.Add("HyperDashAfterImage", HYPER_DASH_AFTER_IMAGE_COLOUR); + Configuration.CustomColours.Add("HyperDashFruit", HYPER_DASH_FRUIT_COLOUR); + } } } @@ -130,11 +141,22 @@ namespace osu.Game.Tests.Beatmaps new Color4(20, 20, 20, 255), }; + public static readonly Color4 HYPER_DASH_COLOUR = Color4.LightBlue; + + public static readonly Color4 HYPER_DASH_AFTER_IMAGE_COLOUR = Color4.LightCoral; + + public static readonly Color4 HYPER_DASH_FRUIT_COLOUR = Color4.LightCyan; + public TestSkin(bool hasCustomColours) : base(new SkinInfo(), new ResourceStore(), null, string.Empty) { if (hasCustomColours) + { Configuration.AddComboColours(Colours); + Configuration.CustomColours.Add("HyperDash", HYPER_DASH_COLOUR); + Configuration.CustomColours.Add("HyperDashAfterImage", HYPER_DASH_AFTER_IMAGE_COLOUR); + Configuration.CustomColours.Add("HyperDashFruit", HYPER_DASH_FRUIT_COLOUR); + } } public event Action SourceChanged From bb0d2899931bbefedf3229d2b963a5d368fc6177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 16 Jan 2021 23:24:28 +0100 Subject: [PATCH 072/202] Split variable for readability --- osu.Game/OsuGameBase.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index d3273ba170..716796a585 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -426,7 +426,8 @@ namespace osu.Game { var imports = tasks.Where(t => t.Path.EndsWith(ext, StringComparison.OrdinalIgnoreCase)); - return fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(ext))?.Import(imports.ToArray()) ?? Task.CompletedTask; + var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(ext)); + return importer?.Import(imports.ToArray()) ?? Task.CompletedTask; })); } From dee46d7ba201e70c463f68f5b4cf38c43a87d085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 16 Jan 2021 23:42:28 +0100 Subject: [PATCH 073/202] Use GroupBy() instead --- osu.Game/OsuGameBase.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 716796a585..1f8ae54e55 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -421,13 +421,11 @@ namespace osu.Game public virtual async Task Import(params ImportTask[] tasks) { - var extensions = tasks.Select(t => Path.GetExtension(t.Path).ToLowerInvariant()).Distinct(); - await Task.WhenAll(extensions.Select(ext => + var tasksPerExtension = tasks.GroupBy(t => Path.GetExtension(t.Path).ToLowerInvariant()); + await Task.WhenAll(tasksPerExtension.Select(taskGroup => { - var imports = tasks.Where(t => t.Path.EndsWith(ext, StringComparison.OrdinalIgnoreCase)); - - var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(ext)); - return importer?.Import(imports.ToArray()) ?? Task.CompletedTask; + var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(taskGroup.Key)); + return importer?.Import(taskGroup.ToArray()) ?? Task.CompletedTask; })); } From 816cc7a59b146cff51773d9f3ec862e0d61af7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Jan 2021 00:35:23 +0100 Subject: [PATCH 074/202] Adjust explicit label spacing on beatmap set overlay --- osu.Game/Overlays/BeatmapSet/Header.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 9f2b40dfa4..a84ed5ac29 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -145,14 +145,14 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 3, Bottom = 4 }, // To better lineup with the font + Margin = new MarginPadding { Left = 5, Bottom = 4 }, // To better lineup with the font }, explicitPill = new ExplicitBeatmapPill { Alpha = 0f, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Left = 15f, Top = 4 }, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Left = 10, Bottom = 4 }, } } }, From eb53e32792dcb36c1aac9d612dc24f09733487dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Jan 2021 14:40:22 +0100 Subject: [PATCH 075/202] Use task completion source for room join flow On Android, users were unable to join or create multiplayer rooms. The root cause of that was that the both the wait and set of the `ManualResetEvent` in `getRoomUsers` occurred on the same thread, which created a chicken-and-egg situation - the set could not proceed until the wait had actually completed. Resolve by substituting the `ManualResetEvent` for a `TaskCompletionSource` to achieve a promise-style task, which the previous code was a crude approximation of anyway. Closes #11385. --- .../Multiplayer/StatefulMultiplayerClient.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs b/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs index fbdfb6a8c5..f0e11b2b8b 100644 --- a/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/StatefulMultiplayerClient.cs @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -128,7 +127,8 @@ namespace osu.Game.Online.Multiplayer Debug.Assert(Room != null); - var users = getRoomUsers(); + var users = await getRoomUsers(); + Debug.Assert(users != null); await Task.WhenAll(users.Select(PopulateUser)); @@ -437,24 +437,20 @@ namespace osu.Game.Online.Multiplayer /// This should be used whenever accessing users from outside of an Update thread context (ie. when not calling ). /// /// A copy of users in the current room, or null if unavailable. - private List? getRoomUsers() + private Task?> getRoomUsers() { - List? users = null; - - ManualResetEventSlim resetEvent = new ManualResetEventSlim(); + var tcs = new TaskCompletionSource?>(); // at some point we probably want to replace all these schedule calls with Room.LockForUpdate. // for now, as this would require quite some consideration due to the number of accesses to the room instance, // let's just add a manual schedule for the non-scheduled usages instead. Scheduler.Add(() => { - users = Room?.Users.ToList(); - resetEvent.Set(); + var users = Room?.Users.ToList(); + tcs.SetResult(users); }, false); - resetEvent.Wait(100); - - return users; + return tcs.Task; } /// From 5fd644fc576de33cab2f4b0daeb323b262b3b98e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 17 Jan 2021 22:40:24 +0900 Subject: [PATCH 076/202] Unify variable names --- .../TestSceneBeatmapListingSearchControl.cs | 10 +++++----- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- .../Online/API/Requests/SearchBeatmapSetsRequest.cs | 8 ++++---- .../BeatmapListing/BeatmapListingFilterControl.cs | 4 ++-- .../BeatmapListing/BeatmapListingSearchControl.cs | 10 +++++----- .../Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs | 2 +- .../Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs | 2 +- ...citBeatmapPill.cs => ExplicitContentBeatmapPill.cs} | 4 ++-- osu.Game/Overlays/BeatmapSet/Header.cs | 6 +++--- .../Overlays/Settings/Sections/Online/WebSettings.cs | 2 +- .../Screens/OnlinePlay/DrawableRoomPlaylistItem.cs | 6 +++--- 11 files changed, 29 insertions(+), 29 deletions(-) rename osu.Game/Overlays/BeatmapSet/{ExplicitBeatmapPill.cs => ExplicitContentBeatmapPill.cs} (92%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs index dc46da6293..a9747e73f9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSearchControl.cs @@ -78,7 +78,7 @@ namespace osu.Game.Tests.Visual.UserInterface 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.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true); - control.Explicit.BindValueChanged(e => explicitMap.Text = $"Explicit Maps: {e.NewValue}", true); + control.ExplicitContent.BindValueChanged(e => explicitMap.Text = $"Explicit Maps: {e.NewValue}", true); }); [Test] @@ -92,11 +92,11 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestExplicitConfig() { - AddStep("configure explicit content to allowed", () => localConfig.Set(OsuSetting.AllowExplicitContent, true)); - AddAssert("explicit control set to show", () => control.Explicit.Value == SearchExplicit.Show); + AddStep("configure explicit content to allowed", () => localConfig.Set(OsuSetting.ShowOnlineExplicitContent, true)); + AddAssert("explicit control set to show", () => control.ExplicitContent.Value == SearchExplicit.Show); - AddStep("configure explicit content to disallowed", () => localConfig.Set(OsuSetting.AllowExplicitContent, false)); - AddAssert("explicit control set to hide", () => control.Explicit.Value == SearchExplicit.Hide); + AddStep("configure explicit content to disallowed", () => localConfig.Set(OsuSetting.ShowOnlineExplicitContent, false)); + AddAssert("explicit control set to hide", () => control.ExplicitContent.Value == SearchExplicit.Hide); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 5e7a843baf..6b48501dac 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -60,7 +60,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ExternalLinkWarning, true); Set(OsuSetting.PreferNoVideo, false); - Set(OsuSetting.AllowExplicitContent, false); + Set(OsuSetting.ShowOnlineExplicitContent, false); // Audio Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); @@ -272,6 +272,6 @@ namespace osu.Game.Configuration EditorWaveformOpacity, DiscordRichPresence, AutomaticallyDownloadWhenSpectating, - AllowExplicitContent, + ShowOnlineExplicitContent, } } diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index 939d3c6cb4..5360d36f3d 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Online.API.Requests public SearchPlayed Played { get; } - public SearchExplicit Explicit { get; } + public SearchExplicit ExplicitContent { get; } [CanBeNull] public IReadOnlyCollection Ranks { get; } @@ -53,7 +53,7 @@ namespace osu.Game.Online.API.Requests IReadOnlyCollection extra = null, IReadOnlyCollection ranks = null, SearchPlayed played = SearchPlayed.Any, - SearchExplicit explicitMaps = SearchExplicit.Hide) + SearchExplicit explicitContent = SearchExplicit.Hide) { this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query); this.ruleset = ruleset; @@ -67,7 +67,7 @@ namespace osu.Game.Online.API.Requests Extra = extra; Ranks = ranks; Played = played; - Explicit = explicitMaps; + ExplicitContent = explicitContent; } protected override WebRequest CreateWebRequest() @@ -97,7 +97,7 @@ namespace osu.Game.Online.API.Requests if (Played != SearchPlayed.Any) req.AddParameter("played", Played.ToString().ToLowerInvariant()); - req.AddParameter("nsfw", Explicit == SearchExplicit.Show ? "true" : "false"); + req.AddParameter("nsfw", ExplicitContent == SearchExplicit.Show ? "true" : "false"); req.AddCursor(cursor); diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs index 650adcb4a9..bcc5a91677 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs @@ -141,7 +141,7 @@ namespace osu.Game.Overlays.BeatmapListing searchControl.Extra.CollectionChanged += (_, __) => queueUpdateSearch(); searchControl.Ranks.CollectionChanged += (_, __) => queueUpdateSearch(); searchControl.Played.BindValueChanged(_ => queueUpdateSearch()); - searchControl.Explicit.BindValueChanged(_ => queueUpdateSearch()); + searchControl.ExplicitContent.BindValueChanged(_ => queueUpdateSearch()); sortCriteria.BindValueChanged(_ => queueUpdateSearch()); sortDirection.BindValueChanged(_ => queueUpdateSearch()); @@ -195,7 +195,7 @@ namespace osu.Game.Overlays.BeatmapListing searchControl.Extra, searchControl.Ranks, searchControl.Played.Value, - searchControl.Explicit.Value); + searchControl.ExplicitContent.Value); getSetsRequest.Success += response => { diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 5c6267b726..b138a5ac52 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.BeatmapListing public Bindable Played => playedFilter.Current; - public Bindable Explicit => explicitFilter.Current; + public Bindable ExplicitContent => explicitContentFilter.Current; public BeatmapSetInfo BeatmapSet { @@ -68,7 +68,7 @@ namespace osu.Game.Overlays.BeatmapListing private readonly BeatmapSearchMultipleSelectionFilterRow extraFilter; private readonly BeatmapSearchScoreFilterRow ranksFilter; private readonly BeatmapSearchFilterRow playedFilter; - private readonly BeatmapSearchFilterRow explicitFilter; + private readonly BeatmapSearchFilterRow explicitContentFilter; private readonly Box background; private readonly UpdateableBeatmapSetCover beatmapCover; @@ -130,7 +130,7 @@ namespace osu.Game.Overlays.BeatmapListing extraFilter = new BeatmapSearchMultipleSelectionFilterRow(@"Extra"), ranksFilter = new BeatmapSearchScoreFilterRow(), playedFilter = new BeatmapSearchFilterRow(@"Played"), - explicitFilter = new BeatmapSearchFilterRow(@"Explicit Maps"), + explicitContentFilter = new BeatmapSearchFilterRow(@"Explicit Content"), } } } @@ -148,10 +148,10 @@ namespace osu.Game.Overlays.BeatmapListing { background.Colour = colourProvider.Dark6; - allowExplicitContent = config.GetBindable(OsuSetting.AllowExplicitContent); + allowExplicitContent = config.GetBindable(OsuSetting.ShowOnlineExplicitContent); allowExplicitContent.BindValueChanged(allow => { - Explicit.Value = allow.NewValue ? SearchExplicit.Show : SearchExplicit.Hide; + ExplicitContent.Value = allow.NewValue ? SearchExplicit.Show : SearchExplicit.Hide; }, true); } diff --git a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs index b7002a96e5..c1d366bb82 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/GridBeatmapPanel.cs @@ -205,7 +205,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels if (SetInfo.OnlineInfo?.HasExplicitContent ?? false) { - titleContainer.Add(new ExplicitBeatmapPill + titleContainer.Add(new ExplicitContentBeatmapPill { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs index 69671ab75b..76a30d1c11 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/ListBeatmapPanel.cs @@ -219,7 +219,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels if (SetInfo.OnlineInfo?.HasExplicitContent ?? false) { - titleContainer.Add(new ExplicitBeatmapPill + titleContainer.Add(new ExplicitContentBeatmapPill { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapPill.cs similarity index 92% rename from osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs rename to osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapPill.cs index aefb3299a5..329f8ee0a2 100644 --- a/osu.Game/Overlays/BeatmapSet/ExplicitBeatmapPill.cs +++ b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapPill.cs @@ -10,9 +10,9 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.BeatmapSet { - public class ExplicitBeatmapPill : CompositeDrawable + public class ExplicitContentBeatmapPill : CompositeDrawable { - public ExplicitBeatmapPill() + public ExplicitContentBeatmapPill() { AutoSizeAxes = Axes.Both; } diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 876a7e8917..916c21c010 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Box coverGradient; private readonly OsuSpriteText title, artist; private readonly AuthorInfo author; - private readonly ExplicitBeatmapPill explicitPill; + private readonly ExplicitContentBeatmapPill explicitContentPill; private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapAvailability beatmapAvailability; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Margin = new MarginPadding { Left = 5, Bottom = 4 }, // To better lineup with the font }, - explicitPill = new ExplicitBeatmapPill + explicitContentPill = new ExplicitContentBeatmapPill { Alpha = 0f, Anchor = Anchor.BottomLeft, @@ -261,7 +261,7 @@ namespace osu.Game.Overlays.BeatmapSet title.Text = setInfo.NewValue.Metadata.Title ?? string.Empty; artist.Text = setInfo.NewValue.Metadata.Artist ?? string.Empty; - explicitPill.Alpha = setInfo.NewValue.OnlineInfo.HasExplicitContent ? 1 : 0; + explicitContentPill.Alpha = setInfo.NewValue.OnlineInfo.HasExplicitContent ? 1 : 0; onlineStatusPill.FadeIn(500, Easing.OutQuint); onlineStatusPill.Status = setInfo.NewValue.OnlineInfo.Status; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index da7ef46f65..3e1cc1d91e 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online { LabelText = "Hide warnings for explicit content in beatmaps", Keywords = new[] { "nsfw", "18+", "offensive" }, - Current = config.GetBindable(OsuSetting.AllowExplicitContent), + Current = config.GetBindable(OsuSetting.ShowOnlineExplicitContent), } }; } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 7987d715e3..b16f82fce9 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.OnlinePlay private Container difficultyIconContainer; private LinkFlowContainer beatmapText; private LinkFlowContainer authorText; - private ExplicitBeatmapPill explicitPill; + private ExplicitContentBeatmapPill explicitContentPill; private ModDisplay modDisplay; private readonly Bindable beatmap = new Bindable(); @@ -119,7 +119,7 @@ namespace osu.Game.Screens.OnlinePlay } bool hasExplicitContent = Item.Beatmap.Value.BeatmapSet.OnlineInfo?.HasExplicitContent == true; - explicitPill.Alpha = hasExplicitContent ? 1 : 0; + explicitContentPill.Alpha = hasExplicitContent ? 1 : 0; modDisplay.Current.Value = requiredMods.ToArray(); } @@ -181,7 +181,7 @@ namespace osu.Game.Screens.OnlinePlay Children = new Drawable[] { authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both }, - explicitPill = new ExplicitBeatmapPill + explicitContentPill = new ExplicitContentBeatmapPill { Alpha = 0f, Anchor = Anchor.CentreLeft, From 5278cad393aeb1d76f7603cda445fb67b2d46234 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 17 Jan 2021 22:40:58 +0900 Subject: [PATCH 077/202] Reword setting to make more sense --- osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 3e1cc1d91e..59bcbe4d89 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Settings.Sections.Online }, new SettingsCheckbox { - LabelText = "Hide warnings for explicit content in beatmaps", + LabelText = "Show explicit content in search results", Keywords = new[] { "nsfw", "18+", "offensive" }, Current = config.GetBindable(OsuSetting.ShowOnlineExplicitContent), } From 39746cb3de8ad11221ff1766822f720918d49858 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 00:11:35 +0900 Subject: [PATCH 078/202] Test removing nuget restore from iOS/Android build scripts --- fastlane/Fastfile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 8c278604aa..18b5907e82 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -48,10 +48,6 @@ desc 'Deploy to play store' desc 'Compile the project' lane :build do |options| - nuget_restore( - project_path: 'osu.sln' - ) - souyuz( build_configuration: 'Release', solution_path: 'osu.sln', @@ -107,10 +103,6 @@ platform :ios do desc 'Compile the project' lane :build do - nuget_restore( - project_path: 'osu.sln' - ) - souyuz( platform: "ios", plist_path: "osu.iOS/Info.plist" From 585aa87c5389b16dc9c8d4c17c38365cb0100174 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 17 Jan 2021 19:17:14 +0300 Subject: [PATCH 079/202] Fix playlist item download button never shown back after hiding --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 8 +++++++- osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 17d85d1120..c6cfd3c64a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -201,11 +201,17 @@ namespace osu.Game.Tests.Visual.Multiplayer } [Test] - public void TestDownloadButtonHiddenInitiallyWhenBeatmapExists() + public void TestDownloadButtonHiddenWhenBeatmapExists() { createPlaylist(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo); AddAssert("download button hidden", () => !playlist.ChildrenOfType().Single().IsPresent); + + AddStep("delete beatmap set", () => manager.Delete(manager.QueryBeatmapSets(_ => true).Single())); + AddUntilStep("download button shown", () => playlist.ChildrenOfType().Single().IsPresent); + + AddStep("undelete beatmap set", () => manager.Undelete(manager.QueryBeatmapSets(_ => true).Single())); + AddUntilStep("download button hidden", () => !playlist.ChildrenOfType().Single().IsPresent); } [Test] diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index b16f82fce9..f8982582d5 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -249,6 +249,8 @@ namespace osu.Game.Screens.OnlinePlay [Resolved] private BeatmapManager beatmapManager { get; set; } + public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks; + public PlaylistDownloadButton(PlaylistItem playlistItem) : base(playlistItem.Beatmap.Value.BeatmapSet) { From 2b23c8eabd02a1c3743d7538bbecb9ae3d224333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Jan 2021 18:08:58 +0100 Subject: [PATCH 080/202] Use alpha directly for checking visibility in test `IsPresent` is no longer synonymous with being visible, after applying the fix to the issue in question. --- .../Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index c6cfd3c64a..874c1694eb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -205,13 +205,16 @@ namespace osu.Game.Tests.Visual.Multiplayer { createPlaylist(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo); - AddAssert("download button hidden", () => !playlist.ChildrenOfType().Single().IsPresent); + assertDownloadButtonVisible(false); AddStep("delete beatmap set", () => manager.Delete(manager.QueryBeatmapSets(_ => true).Single())); - AddUntilStep("download button shown", () => playlist.ChildrenOfType().Single().IsPresent); + assertDownloadButtonVisible(true); AddStep("undelete beatmap set", () => manager.Undelete(manager.QueryBeatmapSets(_ => true).Single())); - AddUntilStep("download button hidden", () => !playlist.ChildrenOfType().Single().IsPresent); + assertDownloadButtonVisible(false); + + void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}", + () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0)); } [Test] From ec00aaef90a9bfe8d768f01148f99a78d043401e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 Jan 2021 19:13:55 +0900 Subject: [PATCH 081/202] Add nuget deploys for all rulesets --- appveyor_deploy.yml | 73 +++++++++++++++---- .../osu.Game.Rulesets.Catch.csproj | 7 ++ .../osu.Game.Rulesets.Mania.csproj | 7 ++ .../osu.Game.Rulesets.Osu.csproj | 7 ++ .../osu.Game.Rulesets.Taiko.csproj | 7 ++ 5 files changed, 88 insertions(+), 13 deletions(-) diff --git a/appveyor_deploy.yml b/appveyor_deploy.yml index bb4482f501..737e5c43ab 100644 --- a/appveyor_deploy.yml +++ b/appveyor_deploy.yml @@ -1,21 +1,68 @@ clone_depth: 1 version: '{build}' image: Visual Studio 2019 -dotnet_csproj: - patch: true - file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects - version: $(APPVEYOR_REPO_TAG_NAME) -before_build: - - ps: dotnet --info # Useful when version mismatch between CI and local - - ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects test: off skip_non_tags: true configuration: Release -build: - project: build\Desktop.proj # Skipping Xamarin Release that's slow and covered by fastlane - parallel: true - verbosity: minimal - publish_nuget: true + +environment: + matrix: + - job_name: osu-game + - job_name: osu-ruleset + job_depends_on: osu-game + - job_name: taiko-ruleset + job_depends_on: osu-game + - job_name: catch-ruleset + job_depends_on: osu-game + - job_name: mania-ruleset + job_depends_on: osu-game + +nuget: + project_feed: true + +for: + - + matrix: + only: + - job_name: osu-game + build_script: + - cmd: dotnet pack osu.Game\osu.Game.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME% + - + matrix: + only: + - job_name: osu-ruleset + build_script: + - cmd: dotnet remove osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj reference osu.Game\osu.Game.csproj + - cmd: dotnet add osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME% + - cmd: dotnet pack osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME% + - + matrix: + only: + - job_name: taiko-ruleset + build_script: + - cmd: dotnet remove osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj reference osu.Game\osu.Game.csproj + - cmd: dotnet add osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME% + - cmd: dotnet pack osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME% + - + matrix: + only: + - job_name: catch-ruleset + build_script: + - cmd: dotnet remove osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj reference osu.Game\osu.Game.csproj + - cmd: dotnet add osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME% + - cmd: dotnet pack osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME% + - + matrix: + only: + - job_name: mania-ruleset + build_script: + - cmd: dotnet remove osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj reference osu.Game\osu.Game.csproj + - cmd: dotnet add osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME% + - cmd: dotnet pack osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME% + +artifacts: + - path: '**\*.nupkg' + deploy: - provider: Environment - name: nuget + name: nuget \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index b19affbf9f..5bdf39824c 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -5,6 +5,13 @@ true catch the fruit. to the beat. + + + osu!catch + ppy.osu.Game.Rulesets.Catch + true + + diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 07ef1022ae..c30fe8494f 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -5,6 +5,13 @@ true smash the keys. to the beat. + + + osu!mania + ppy.osu.Game.Rulesets.Mania + true + + diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index bffeaabb55..36ee804259 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -5,6 +5,13 @@ true click the circles. to the beat. + + + osu!standard + ppy.osu.Game.Rulesets.Osu + true + + diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index ebed8c6d7c..00deb719e1 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -5,6 +5,13 @@ true bash the drum. to the beat. + + + osu!taiko + ppy.osu.Game.Rulesets.Taiko + true + + From 1b166d809eb5bb5f04bdbcfabfba3916cd66a114 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 18 Jan 2021 11:07:54 +0900 Subject: [PATCH 082/202] Adjust package titles --- osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj | 2 +- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 2 +- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 2 +- osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 5bdf39824c..e2f95ca177 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -7,7 +7,7 @@ - osu!catch + osu!catch (ruleset) ppy.osu.Game.Rulesets.Catch true diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index c30fe8494f..4f6840f9ca 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -7,7 +7,7 @@ - osu!mania + osu!mania (ruleset) ppy.osu.Game.Rulesets.Mania true diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 36ee804259..98f1e69bd1 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -7,7 +7,7 @@ - osu!standard + osu! (ruleset) ppy.osu.Game.Rulesets.Osu true diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 00deb719e1..b752c13d18 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -7,7 +7,7 @@ - osu!taiko + osu!taiko (ruleset) ppy.osu.Game.Rulesets.Taiko true From 94fee8c31d123b940ddf636cf6982152479cc7ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 16:13:58 +0900 Subject: [PATCH 083/202] Avoid doing a config lookup if initial conditional fails --- osu.Game/Skinning/SkinProvidingContainer.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Skinning/SkinProvidingContainer.cs b/osu.Game/Skinning/SkinProvidingContainer.cs index e97822b86e..27cf0c697a 100644 --- a/osu.Game/Skinning/SkinProvidingContainer.cs +++ b/osu.Game/Skinning/SkinProvidingContainer.cs @@ -74,8 +74,8 @@ namespace osu.Game.Skinning { if (lookup is GlobalSkinColours || lookup is SkinCustomColourLookup) return lookupWithFallback(lookup, AllowColourLookup); - else - return lookupWithFallback(lookup, AllowConfigurationLookup); + + return lookupWithFallback(lookup, AllowConfigurationLookup); } return fallbackSource?.GetConfig(lookup); @@ -83,11 +83,14 @@ namespace osu.Game.Skinning private IBindable lookupWithFallback(TLookup lookup, bool canUseSkinLookup) { - var bindable = skin.GetConfig(lookup); - if (bindable != null && canUseSkinLookup) - return bindable; - else - return fallbackSource?.GetConfig(lookup); + if (canUseSkinLookup) + { + var bindable = skin.GetConfig(lookup); + if (bindable != null) + return bindable; + } + + return fallbackSource?.GetConfig(lookup); } protected virtual void TriggerSourceChanged() => SourceChanged?.Invoke(); From 02d2b2742b66d1bf6b9899430d90580f69872db1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 16:57:36 +0900 Subject: [PATCH 084/202] Fix selection box not updating with hitcircles/sliders far in the future or past --- .../Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs | 2 +- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 093bae854e..abbb54e3c1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -30,6 +30,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.HitArea.ReceivePositionalInputAt(screenSpacePos); - public override Quad SelectionQuad => DrawableObject.HitArea.ScreenSpaceDrawQuad; + public override Quad SelectionQuad => CirclePiece.ScreenSpaceDrawQuad; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index d592e129d9..3d3dff653a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -44,6 +44,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders [Resolved(CanBeNull = true)] private IEditorChangeHandler changeHandler { get; set; } + public override Quad SelectionQuad => BodyPiece.ScreenSpaceDrawQuad; + private readonly BindableList controlPoints = new BindableList(); private readonly IBindable pathVersion = new Bindable(); From c79ab63743e14b4205e40f33d5ae4519dfbeb58e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 16:56:10 +0900 Subject: [PATCH 085/202] Fix sliders with an even number of repeats not allowing rotation/scale transforms --- osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 660e1844aa..91bb665ee2 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -236,7 +236,18 @@ namespace osu.Game.Rulesets.Osu.Edit /// /// The hit objects to calculate a quad for. private Quad getSurroundingQuad(OsuHitObject[] hitObjects) => - getSurroundingQuad(hitObjects.SelectMany(h => new[] { h.Position, h.EndPosition })); + getSurroundingQuad(hitObjects.SelectMany(h => + { + if (h is IHasPath path) + return new[] + { + h.Position, + // can't use EndPosition for reverse slider cases. + h.Position + path.Path.PositionAt(1) + }; + + return new[] { h.Position }; + })); /// /// Returns a gamefield-space quad surrounding the provided points. From 2f1d4bf51b0964aded4fa5d31be592c7da3eb482 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 17:13:47 +0900 Subject: [PATCH 086/202] Add missing braces --- osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 91bb665ee2..871339ae7b 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -239,12 +239,14 @@ namespace osu.Game.Rulesets.Osu.Edit getSurroundingQuad(hitObjects.SelectMany(h => { if (h is IHasPath path) + { return new[] { h.Position, // can't use EndPosition for reverse slider cases. h.Position + path.Path.PositionAt(1) }; + } return new[] { h.Position }; })); From 0b165dce4bbbb0647ccbdae48b8d2621173655f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 17:50:32 +0900 Subject: [PATCH 087/202] Fix multiplayer mod select showing autoplay as a choice --- osu.Game/OsuGameBase.cs | 1 + osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 +++++-- .../OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs | 5 +++++ osu.Game/Screens/Select/SongSelect.cs | 8 +++----- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 1f8ae54e55..20d88d33f2 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -327,6 +327,7 @@ namespace osu.Game if (!SelectedMods.Disabled) SelectedMods.Value = Array.Empty(); + AvailableMods.Value = dict; } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 0c8245bebe..b93602116b 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -30,6 +30,7 @@ namespace osu.Game.Overlays.Mods { public class ModSelectOverlay : WaveOverlayContainer { + private readonly Func isValidMod; public const float HEIGHT = 510; protected readonly TriangleButton DeselectAllButton; @@ -60,8 +61,10 @@ namespace osu.Game.Overlays.Mods private SampleChannel sampleOn, sampleOff; - public ModSelectOverlay() + public ModSelectOverlay(Func isValidMod = null) { + this.isValidMod = isValidMod ?? (m => true); + Waves.FirstWaveColour = Color4Extensions.FromHex(@"19b0e2"); Waves.SecondWaveColour = Color4Extensions.FromHex(@"2280a2"); Waves.ThirdWaveColour = Color4Extensions.FromHex(@"005774"); @@ -403,7 +406,7 @@ namespace osu.Game.Overlays.Mods if (mods.NewValue == null) return; foreach (var section in ModSectionsContainer.Children) - section.Mods = mods.NewValue[section.ModType]; + section.Mods = mods.NewValue[section.ModType].Where(isValidMod); } private void selectedModsChanged(ValueChangedEvent> mods) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs index 36dbb9e792..ebc06d2445 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; +using osu.Game.Overlays.Mods; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Select; @@ -109,5 +110,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer } protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); + + protected override ModSelectOverlay CreateModSelectOverlay() => new ModSelectOverlay(isValidMod); + + private bool isValidMod(Mod mod) => !(mod is ModAutoplay) && (mod as MultiMod)?.Mods.Any(mm => mm is ModAutoplay) != true; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6c0bd3a228..4fca77a176 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -251,11 +251,7 @@ namespace osu.Game.Screens.Select Children = new Drawable[] { BeatmapOptions = new BeatmapOptionsOverlay(), - ModSelect = new ModSelectOverlay - { - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - } + ModSelect = CreateModSelectOverlay() } } } @@ -305,6 +301,8 @@ namespace osu.Game.Screens.Select } } + protected virtual ModSelectOverlay CreateModSelectOverlay() => new ModSelectOverlay(); + protected virtual void ApplyFilterToCarousel(FilterCriteria criteria) { // if not the current screen, we want to get carousel in a good presentation state before displaying (resume or enter). From 1359153382232fc303dd1ded30048545c4aa0638 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 17:54:22 +0900 Subject: [PATCH 088/202] Revert "Test removing nuget restore from iOS/Android build scripts" This reverts commit 39746cb3de8ad11221ff1766822f720918d49858. --- fastlane/Fastfile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 18b5907e82..8c278604aa 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -48,6 +48,10 @@ desc 'Deploy to play store' desc 'Compile the project' lane :build do |options| + nuget_restore( + project_path: 'osu.sln' + ) + souyuz( build_configuration: 'Release', solution_path: 'osu.sln', @@ -103,6 +107,10 @@ platform :ios do desc 'Compile the project' lane :build do + nuget_restore( + project_path: 'osu.sln' + ) + souyuz( platform: "ios", plist_path: "osu.iOS/Info.plist" From 46681322d0489d0829114fc87071b7e5c8f0c525 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 17:56:00 +0900 Subject: [PATCH 089/202] Restore nuget packages per project to avoid toolchain incompatibilities with net50 --- fastlane/Fastfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 8c278604aa..1823b9e924 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -48,9 +48,8 @@ desc 'Deploy to play store' desc 'Compile the project' lane :build do |options| - nuget_restore( - project_path: 'osu.sln' - ) + nuget_restore(project_path: 'osu.Android/osu.Android.csproj') + nuget_restore(project_path: 'osu.Game/osu.Game.csproj') souyuz( build_configuration: 'Release', @@ -107,9 +106,8 @@ platform :ios do desc 'Compile the project' lane :build do - nuget_restore( - project_path: 'osu.sln' - ) + nuget_restore(project_path: 'osu.iOS/osu.iOS.csproj') + nuget_restore(project_path: 'osu.Game/osu.Game.csproj') souyuz( platform: "ios", From 0560eb41201d0094d8321927bc3498502065c994 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 18:22:21 +0900 Subject: [PATCH 090/202] Reduce final fill alpha of main menu confirm-to-exit --- osu.Game/Overlays/HoldToConfirmOverlay.cs | 13 +++++++++++-- osu.Game/Screens/Menu/ExitConfirmOverlay.cs | 5 +++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index eb325d8dd3..0542f66b5b 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -24,6 +24,13 @@ namespace osu.Game.Overlays [Resolved] private AudioManager audio { get; set; } + private readonly float finalFillAlpha; + + protected HoldToConfirmOverlay(float finalFillAlpha = 1) + { + this.finalFillAlpha = finalFillAlpha; + } + [BackgroundDependencyLoader] private void load() { @@ -42,8 +49,10 @@ namespace osu.Game.Overlays Progress.ValueChanged += p => { - audioVolume.Value = 1 - p.NewValue; - overlay.Alpha = (float)p.NewValue; + var target = p.NewValue * finalFillAlpha; + + audioVolume.Value = 1 - target; + overlay.Alpha = (float)target; }; audio.Tracks.AddAdjustment(AdjustableProperty.Volume, audioVolume); diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index db2faeb60a..a491283e5f 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -13,6 +13,11 @@ namespace osu.Game.Screens.Menu public void Abort() => AbortConfirm(); + public ExitConfirmOverlay() + : base(0.7f) + { + } + public bool OnPressed(GlobalAction action) { if (action == GlobalAction.Back) From 12443e39ae70060657f1b097bc7b9c6e35345e08 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 19:16:32 +0900 Subject: [PATCH 091/202] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index db5c933c41..9ad5946311 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 301ee39a61..2b8f81532d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 225cf981f2..4732620085 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From ced7a36788d7f61ce1163f043d872eb97ad44a02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 21:24:10 +0900 Subject: [PATCH 092/202] Update namespaces --- osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs | 1 - osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs | 2 +- osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs | 1 - osu.Game/Rulesets/UI/Playfield.cs | 2 +- osu.Game/Skinning/PoolableSkinnableSample.cs | 2 +- osu.Game/Skinning/SkinnableSound.cs | 2 +- 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs index 33e3c7cb8c..987a5812db 100644 --- a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs +++ b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs @@ -9,7 +9,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 80f1b02794..97087e31ab 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; +using osu.Framework.Audio.Sample; using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index b13b20dae2..81ec73a6c5 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index b4e0025351..c40ab4bd94 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -8,7 +8,6 @@ using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Containers; @@ -20,6 +19,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Skinning; using osuTK; using System.Diagnostics; +using osu.Framework.Audio.Sample; namespace osu.Game.Rulesets.UI { diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index cc6b85a13e..2a0f480b48 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -5,7 +5,7 @@ using System; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Track; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index b841f99598..a874e9a0db 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -7,7 +7,7 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Audio.Track; +using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; From e74ecebfd61440a47c7423b0802491ccc1930b7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 Jan 2021 23:45:57 +0900 Subject: [PATCH 093/202] nuget restore other rulesets --- fastlane/Fastfile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 1823b9e924..cc5abf5b03 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -50,6 +50,10 @@ desc 'Deploy to play store' lane :build do |options| nuget_restore(project_path: 'osu.Android/osu.Android.csproj') nuget_restore(project_path: 'osu.Game/osu.Game.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj') souyuz( build_configuration: 'Release', @@ -108,6 +112,10 @@ platform :ios do lane :build do nuget_restore(project_path: 'osu.iOS/osu.iOS.csproj') nuget_restore(project_path: 'osu.Game/osu.Game.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj') + nuget_restore(project_path: 'osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj') souyuz( platform: "ios", From 7476cb3047b400489d39af6494c782de531313ed Mon Sep 17 00:00:00 2001 From: rednir Date: Mon, 18 Jan 2021 19:51:42 +0000 Subject: [PATCH 094/202] Sort SkinSection in alphabetical order --- .../Overlays/Settings/Sections/SkinSection.cs | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 5898482e4a..0bfa0ba4f0 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -107,21 +107,20 @@ namespace osu.Game.Overlays.Settings.Sections private void updateItems() { skinItems = skins.GetAllUsableSkins(); - - // insert after lazer built-in skins - int firstNonDefault = skinItems.FindIndex(s => s.ID > 0); - if (firstNonDefault < 0) - firstNonDefault = skinItems.Count; - - skinItems.Insert(firstNonDefault, random_skin_info); - + skinItems = sortList(skinItems); + skinDropdown.Items = skinItems; } private void itemUpdated(ValueChangedEvent> weakItem) { if (weakItem.NewValue.TryGetTarget(out var item)) - Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => !i.Equals(item)).Append(item).ToArray()); + { + List newDropdownItems = skinDropdown.Items.ToList(); + newDropdownItems.Add(item); + newDropdownItems = sortList(newDropdownItems); + Schedule(() => skinDropdown.Items = newDropdownItems.ToArray()); + } } private void itemRemoved(ValueChangedEvent> weakItem) @@ -130,6 +129,24 @@ namespace osu.Game.Overlays.Settings.Sections Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != item.ID).ToArray()); } + private List sortList(List skinsList) + { + skinsList.Sort((a, b) => String.Compare(a.Name, b.Name, StringComparison.Ordinal)); + for (int i = 0; i < skinsList.Count; i++) + { + // insert lazer built-in skins before user skins + if (skinsList[i].ID <= 0) { + var itemToMove = skinsList[i]; + skinsList.RemoveAt(i); + skinsList.Insert(0, itemToMove); + } + } + skinsList.RemoveAll(s => s.ID == SkinInfo.RANDOM_SKIN); + skinsList.Insert(0, random_skin_info); + + return skinsList; + } + private class SkinSettingsDropdown : SettingsDropdown { protected override OsuDropdown CreateDropdown() => new SkinDropdownControl(); From 0b65c0cd25a727fbfa121395e515fe9e8bd295b1 Mon Sep 17 00:00:00 2001 From: rednir Date: Mon, 18 Jan 2021 20:17:42 +0000 Subject: [PATCH 095/202] Remove whitespace --- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 8e78940ac2..20953b7a9b 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -113,7 +113,6 @@ namespace osu.Game.Overlays.Settings.Sections { skinItems = skins.GetAllUsableSkins(); skinItems = sortList(skinItems); - skinDropdown.Items = skinItems; } From 5233a0449a63b3db599d11535b3484c8ebc50f47 Mon Sep 17 00:00:00 2001 From: Mysfit Date: Mon, 18 Jan 2021 16:08:06 -0500 Subject: [PATCH 096/202] Hide main room subscreen on initial mp room creation. Toggle mp room subscreen visibility based on settings overlay visibility before room is created. --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 80991569dc..df61a0ad21 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -39,6 +39,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerMatchSettingsOverlay settingsOverlay; + private readonly Bindable settingsOverlayVisibility = new Bindable(); + + private GridContainer subScreenContainer; + private IBindable isConnected; [CanBeNull] @@ -55,7 +59,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { InternalChildren = new Drawable[] { - new GridContainer + subScreenContainer = new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] @@ -178,6 +182,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer State = { Value = client.Room == null ? Visibility.Visible : Visibility.Hidden } } }; + + subScreenContainer.Hide(); + settingsOverlayVisibility.BindTo(settingsOverlay.State); + settingsOverlayVisibility.ValueChanged += settingsOverlayVisibilityChanged; } protected override void LoadComplete() @@ -258,6 +266,22 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer readyClickOperation = null; } + private void settingsOverlayVisibilityChanged(ValueChangedEvent settingsOverlayVisibilityChangedEvent) + { + if (client.Room != null) + { + subScreenContainer.Show(); + settingsOverlayVisibility.ValueChanged -= settingsOverlayVisibilityChanged; + } + else + { + if (settingsOverlayVisibilityChangedEvent.NewValue == Visibility.Visible) + subScreenContainer.Hide(); + else + subScreenContainer.Show(); + } + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From cbfb999c2845074d799d1126296584898d9be52b Mon Sep 17 00:00:00 2001 From: Mysfit Date: Mon, 18 Jan 2021 17:13:24 -0500 Subject: [PATCH 097/202] Use the client.RoomUpdated action instead of binding the value of the settings overlay visibility and creating an event from it based on its ValueChanged action. --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index df61a0ad21..38c2ca7e0c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -39,8 +39,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private MultiplayerMatchSettingsOverlay settingsOverlay; - private readonly Bindable settingsOverlayVisibility = new Bindable(); - private GridContainer subScreenContainer; private IBindable isConnected; @@ -184,8 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer }; subScreenContainer.Hide(); - settingsOverlayVisibility.BindTo(settingsOverlay.State); - settingsOverlayVisibility.ValueChanged += settingsOverlayVisibilityChanged; + client.RoomUpdated += roomUpdated; } protected override void LoadComplete() @@ -266,19 +263,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer readyClickOperation = null; } - private void settingsOverlayVisibilityChanged(ValueChangedEvent settingsOverlayVisibilityChangedEvent) + private void roomUpdated() { if (client.Room != null) { + // If the room is updated and is not null, show the room sub screen container and unsubscribe. subScreenContainer.Show(); - settingsOverlayVisibility.ValueChanged -= settingsOverlayVisibilityChanged; - } - else - { - if (settingsOverlayVisibilityChangedEvent.NewValue == Visibility.Visible) - subScreenContainer.Hide(); - else - subScreenContainer.Show(); + client.RoomUpdated -= roomUpdated; } } From f0add0a7cff7b6fe63ca0ccbf0de4caa130fd30d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 19 Jan 2021 01:34:37 +0300 Subject: [PATCH 098/202] Make BeatmapSetOverlay use OverlayHeader --- .../Online/TestSceneBeatmapSetOverlay.cs | 2 +- .../Overlays/BeatmapSet/BeatmapSetHeader.cs | 300 ++++++++++++++++- osu.Game/Overlays/BeatmapSet/Header.cs | 313 ------------------ osu.Game/Overlays/BeatmapSetOverlay.cs | 9 +- 4 files changed, 302 insertions(+), 322 deletions(-) delete mode 100644 osu.Game/Overlays/BeatmapSet/Header.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 689321698a..7ff978c7ca 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -315,7 +315,7 @@ namespace osu.Game.Tests.Visual.Online private class TestBeatmapSetOverlay : BeatmapSetOverlay { - public new Header Header => base.Header; + public new BeatmapSetHeader Header => base.Header; } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs index 6511b15fc8..bc9008d1f5 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeader.cs @@ -1,23 +1,319 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online; +using osu.Game.Online.API; +using osu.Game.Overlays.BeatmapListing.Panels; +using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { public class BeatmapSetHeader : OverlayHeader { - public readonly Bindable Ruleset = new Bindable(); + private const float transition_duration = 200; + private const float buttons_height = 45; + private const float buttons_spacing = 5; + + public readonly Bindable BeatmapSet = new Bindable(); + + public bool DownloadButtonsVisible => downloadButtonsContainer.Any(); + + public BeatmapPicker Picker { get; private set; } public BeatmapRulesetSelector RulesetSelector { get; private set; } + private IBindable state => downloadTracker.State; + + [Cached(typeof(IBindable))] + private readonly Bindable ruleset = new Bindable(); + + [Resolved] + private IAPIProvider api { get; set; } + + private readonly DownloadTracker downloadTracker; + private OsuSpriteText title, artist; + private AuthorInfo author; + private ExplicitContentBeatmapPill explicitContentPill; + private FillFlowContainer downloadButtonsContainer; + private BeatmapAvailability beatmapAvailability; + private BeatmapSetOnlineStatusPill onlineStatusPill; + private ExternalLinkButton externalLink; + private UpdateableBeatmapSetCover cover; + private Box coverGradient; + private FillFlowContainer fadeContent; + private FavouriteButton favouriteButton; + private LoadingSpinner loading; + private Details details; + + public BeatmapSetHeader() + { + Masking = true; + + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.25f), + Type = EdgeEffectType.Shadow, + Radius = 3, + Offset = new Vector2(0f, 1f), + }; + + AddInternal(downloadTracker = new DownloadTracker + { + BeatmapSet = { BindTarget = BeatmapSet } + }); + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + Picker.Beatmap.ValueChanged += b => + { + details.Beatmap = b.NewValue; + externalLink.Link = $@"{api.WebsiteRootUrl}/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b.NewValue?.Ruleset.ShortName}/{b.NewValue?.OnlineBeatmapID}"; + }; + + coverGradient.Colour = ColourInfo.GradientVertical(colourProvider.Background6.Opacity(0.3f), colourProvider.Background6.Opacity(0.8f)); + onlineStatusPill.BackgroundColour = colourProvider.Background6; + + state.BindValueChanged(_ => updateDownloadButtons()); + + BeatmapSet.BindValueChanged(setInfo => + { + Picker.BeatmapSet = RulesetSelector.BeatmapSet = author.BeatmapSet = beatmapAvailability.BeatmapSet = details.BeatmapSet = setInfo.NewValue; + cover.BeatmapSet = setInfo.NewValue; + + if (setInfo.NewValue == null) + { + onlineStatusPill.FadeTo(0.5f, 500, Easing.OutQuint); + fadeContent.Hide(); + + loading.Show(); + + downloadButtonsContainer.FadeOut(transition_duration); + favouriteButton.FadeOut(transition_duration); + } + else + { + fadeContent.FadeIn(500, Easing.OutQuint); + + loading.Hide(); + + title.Text = setInfo.NewValue.Metadata.Title ?? string.Empty; + artist.Text = setInfo.NewValue.Metadata.Artist ?? string.Empty; + + explicitContentPill.Alpha = setInfo.NewValue.OnlineInfo.HasExplicitContent ? 1 : 0; + + onlineStatusPill.FadeIn(500, Easing.OutQuint); + onlineStatusPill.Status = setInfo.NewValue.OnlineInfo.Status; + + downloadButtonsContainer.FadeIn(transition_duration); + favouriteButton.FadeIn(transition_duration); + + updateDownloadButtons(); + } + }, true); + } + + protected override Drawable CreateContent() => new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + cover = new UpdateableBeatmapSetCover + { + RelativeSizeAxes = Axes.Both, + Masking = true, + }, + coverGradient = new Box + { + RelativeSizeAxes = Axes.Both + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding + { + Vertical = BeatmapSetOverlay.Y_PADDING, + Left = BeatmapSetOverlay.X_PADDING, + Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH, + }, + Children = new Drawable[] + { + fadeContent = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = Picker = new BeatmapPicker(), + }, + new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = 15 }, + Children = new Drawable[] + { + title = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 30, weight: FontWeight.SemiBold, italics: true) + }, + externalLink = new ExternalLinkButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Left = 5, Bottom = 4 }, // To better lineup with the font + }, + explicitContentPill = new ExplicitContentBeatmapPill + { + Alpha = 0f, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Left = 10, Bottom = 4 }, + } + } + }, + artist = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true), + Margin = new MarginPadding { Bottom = 20 } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = author = new AuthorInfo(), + }, + beatmapAvailability = new BeatmapAvailability(), + new Container + { + RelativeSizeAxes = Axes.X, + Height = buttons_height, + Margin = new MarginPadding { Top = 10 }, + Children = new Drawable[] + { + favouriteButton = new FavouriteButton + { + BeatmapSet = { BindTarget = BeatmapSet } + }, + downloadButtonsContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, + Spacing = new Vector2(buttons_spacing), + }, + }, + }, + }, + }, + } + }, + loading = new LoadingSpinner + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1.5f), + }, + new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = BeatmapSetOverlay.Y_PADDING, Right = BeatmapSetOverlay.X_PADDING }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + Children = new Drawable[] + { + onlineStatusPill = new BeatmapSetOnlineStatusPill + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + TextSize = 14, + TextPadding = new MarginPadding { Horizontal = 35, Vertical = 10 } + }, + details = new Details(), + }, + }, + } + }; + + private void updateDownloadButtons() + { + if (BeatmapSet.Value == null) return; + + if ((BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) && state.Value != DownloadState.LocallyAvailable) + { + downloadButtonsContainer.Clear(); + return; + } + + switch (state.Value) + { + case DownloadState.LocallyAvailable: + // temporary for UX until new design is implemented. + downloadButtonsContainer.Child = new BeatmapPanelDownloadButton(BeatmapSet.Value) + { + Width = 50, + RelativeSizeAxes = Axes.Y, + SelectedBeatmap = { BindTarget = Picker.Beatmap } + }; + break; + + case DownloadState.Downloading: + case DownloadState.Importing: + // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. + downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); + break; + + default: + downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); + if (BeatmapSet.Value.OnlineInfo.HasVideo) + downloadButtonsContainer.Add(new HeaderDownloadButton(BeatmapSet.Value, true)); + break; + } + } + + private class DownloadTracker : BeatmapDownloadTrackingComposite + { + public new Bindable State => base.State; + } + protected override OverlayTitle CreateTitle() => new BeatmapHeaderTitle(); protected override Drawable CreateTitleContent() => RulesetSelector = new BeatmapRulesetSelector { - Current = Ruleset + Current = ruleset }; private class BeatmapHeaderTitle : OverlayTitle diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs deleted file mode 100644 index 916c21c010..0000000000 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ /dev/null @@ -1,313 +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.Bindables; -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.Game.Beatmaps.Drawables; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online; -using osu.Game.Online.API; -using osu.Game.Overlays.BeatmapListing.Panels; -using osu.Game.Overlays.BeatmapSet.Buttons; -using osu.Game.Rulesets; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Overlays.BeatmapSet -{ - public class Header : BeatmapDownloadTrackingComposite - { - private const float transition_duration = 200; - private const float buttons_height = 45; - private const float buttons_spacing = 5; - - private readonly UpdateableBeatmapSetCover cover; - private readonly Box coverGradient; - private readonly OsuSpriteText title, artist; - private readonly AuthorInfo author; - private readonly ExplicitContentBeatmapPill explicitContentPill; - private readonly FillFlowContainer downloadButtonsContainer; - private readonly BeatmapAvailability beatmapAvailability; - private readonly BeatmapSetOnlineStatusPill onlineStatusPill; - public Details Details; - - public bool DownloadButtonsVisible => downloadButtonsContainer.Any(); - - [Resolved] - private IAPIProvider api { get; set; } - - public BeatmapRulesetSelector RulesetSelector => beatmapSetHeader.RulesetSelector; - public readonly BeatmapPicker Picker; - - private readonly FavouriteButton favouriteButton; - private readonly FillFlowContainer fadeContent; - private readonly LoadingSpinner loading; - private readonly BeatmapSetHeader beatmapSetHeader; - - [Cached(typeof(IBindable))] - private readonly Bindable ruleset = new Bindable(); - - public Header() - { - ExternalLinkButton externalLink; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Masking = true; - - EdgeEffect = new EdgeEffectParameters - { - Colour = Color4.Black.Opacity(0.25f), - Type = EdgeEffectType.Shadow, - Radius = 3, - Offset = new Vector2(0f, 1f), - }; - - InternalChild = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - beatmapSetHeader = new BeatmapSetHeader - { - Ruleset = { BindTarget = ruleset }, - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - cover = new UpdateableBeatmapSetCover - { - RelativeSizeAxes = Axes.Both, - Masking = true, - }, - coverGradient = new Box - { - RelativeSizeAxes = Axes.Both - }, - }, - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Vertical = BeatmapSetOverlay.Y_PADDING, - Left = BeatmapSetOverlay.X_PADDING, - Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH, - }, - Children = new Drawable[] - { - fadeContent = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = Picker = new BeatmapPicker(), - }, - new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 15 }, - Children = new Drawable[] - { - title = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 30, weight: FontWeight.SemiBold, italics: true) - }, - externalLink = new ExternalLinkButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 5, Bottom = 4 }, // To better lineup with the font - }, - explicitContentPill = new ExplicitContentBeatmapPill - { - Alpha = 0f, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Margin = new MarginPadding { Left = 10, Bottom = 4 }, - } - } - }, - artist = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true), - Margin = new MarginPadding { Bottom = 20 } - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = author = new AuthorInfo(), - }, - beatmapAvailability = new BeatmapAvailability(), - new Container - { - RelativeSizeAxes = Axes.X, - Height = buttons_height, - Margin = new MarginPadding { Top = 10 }, - Children = new Drawable[] - { - favouriteButton = new FavouriteButton - { - BeatmapSet = { BindTarget = BeatmapSet } - }, - downloadButtonsContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, - Spacing = new Vector2(buttons_spacing), - }, - }, - }, - }, - }, - } - }, - loading = new LoadingSpinner - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1.5f), - }, - new FillFlowContainer - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = BeatmapSetOverlay.Y_PADDING, Right = BeatmapSetOverlay.X_PADDING }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(10), - Children = new Drawable[] - { - onlineStatusPill = new BeatmapSetOnlineStatusPill - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - TextSize = 14, - TextPadding = new MarginPadding { Horizontal = 35, Vertical = 10 } - }, - Details = new Details(), - }, - }, - }, - }, - } - }; - - Picker.Beatmap.ValueChanged += b => - { - Details.Beatmap = b.NewValue; - externalLink.Link = $@"{api.WebsiteRootUrl}/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b.NewValue?.Ruleset.ShortName}/{b.NewValue?.OnlineBeatmapID}"; - }; - } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - coverGradient.Colour = ColourInfo.GradientVertical(colourProvider.Background6.Opacity(0.3f), colourProvider.Background6.Opacity(0.8f)); - onlineStatusPill.BackgroundColour = colourProvider.Background6; - - State.BindValueChanged(_ => updateDownloadButtons()); - - BeatmapSet.BindValueChanged(setInfo => - { - Picker.BeatmapSet = RulesetSelector.BeatmapSet = author.BeatmapSet = beatmapAvailability.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; - cover.BeatmapSet = setInfo.NewValue; - - if (setInfo.NewValue == null) - { - onlineStatusPill.FadeTo(0.5f, 500, Easing.OutQuint); - fadeContent.Hide(); - - loading.Show(); - - downloadButtonsContainer.FadeOut(transition_duration); - favouriteButton.FadeOut(transition_duration); - } - else - { - fadeContent.FadeIn(500, Easing.OutQuint); - - loading.Hide(); - - title.Text = setInfo.NewValue.Metadata.Title ?? string.Empty; - artist.Text = setInfo.NewValue.Metadata.Artist ?? string.Empty; - - explicitContentPill.Alpha = setInfo.NewValue.OnlineInfo.HasExplicitContent ? 1 : 0; - - onlineStatusPill.FadeIn(500, Easing.OutQuint); - onlineStatusPill.Status = setInfo.NewValue.OnlineInfo.Status; - - downloadButtonsContainer.FadeIn(transition_duration); - favouriteButton.FadeIn(transition_duration); - - updateDownloadButtons(); - } - }, true); - } - - private void updateDownloadButtons() - { - if (BeatmapSet.Value == null) return; - - if ((BeatmapSet.Value.OnlineInfo.Availability?.DownloadDisabled ?? false) && State.Value != DownloadState.LocallyAvailable) - { - downloadButtonsContainer.Clear(); - return; - } - - switch (State.Value) - { - case DownloadState.LocallyAvailable: - // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new BeatmapPanelDownloadButton(BeatmapSet.Value) - { - Width = 50, - RelativeSizeAxes = Axes.Y, - SelectedBeatmap = { BindTarget = Picker.Beatmap } - }; - break; - - case DownloadState.Downloading: - case DownloadState.Importing: - // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); - break; - - default: - downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); - if (BeatmapSet.Value.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new HeaderDownloadButton(BeatmapSet.Value, true)); - break; - } - } - } -} diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index bbec62a85a..86f0f4f614 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -19,15 +19,12 @@ using osuTK; namespace osu.Game.Overlays { - public class BeatmapSetOverlay : FullscreenOverlay // we don't provide a standard header for now. + public class BeatmapSetOverlay : FullscreenOverlay { public const float X_PADDING = 40; public const float Y_PADDING = 25; public const float RIGHT_WIDTH = 275; - //todo: should be an OverlayHeader? or maybe not? - protected new readonly Header Header; - [Resolved] private RulesetStore rulesets { get; set; } @@ -39,7 +36,7 @@ namespace osu.Game.Overlays private readonly Box background; public BeatmapSetOverlay() - : base(OverlayColourScheme.Blue, null) + : base(OverlayColourScheme.Blue, new BeatmapSetHeader()) { OverlayScrollContainer scroll; Info info; @@ -72,7 +69,7 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - Header = new Header(), + Header, info = new Info() } }, From 1e99357a9790884a7a84e4c052a6ab65921586a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 Jan 2021 12:13:27 +0900 Subject: [PATCH 099/202] Update build configurations to net5.0 paths --- .../.idea/runConfigurations/Benchmarks.xml | 6 +++--- .../runConfigurations/CatchRuleset__Tests_.xml | 6 +++--- .../runConfigurations/ManiaRuleset__Tests_.xml | 6 +++--- .../runConfigurations/OsuRuleset__Tests_.xml | 6 +++--- .../runConfigurations/TaikoRuleset__Tests_.xml | 6 +++--- .../.idea/runConfigurations/Tournament.xml | 6 +++--- .../runConfigurations/Tournament__Tests_.xml | 6 +++--- .../.idea/runConfigurations/osu_.xml | 6 +++--- .../.idea/runConfigurations/osu___Tests_.xml | 6 +++--- .../runConfigurations/osu___legacy_osuTK_.xml | 6 +++--- .vscode/launch.json | 18 +++++++++--------- .../.vscode/launch.json | 4 ++-- .../.vscode/launch.json | 4 ++-- .../.vscode/launch.json | 4 ++-- .../.vscode/launch.json | 4 ++-- osu.Game.Tournament.Tests/.vscode/launch.json | 4 ++-- 16 files changed, 49 insertions(+), 49 deletions(-) diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml index 1815c271b4..8fa7608b8e 100644 --- a/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/Benchmarks.xml @@ -1,8 +1,8 @@ - public class BookmarkPart : TimelinePart { - protected override void LoadBeatmap(WorkingBeatmap beatmap) + protected override void LoadBeatmap(EditorBeatmap beatmap) { base.LoadBeatmap(beatmap); foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks) 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 ceccbffc9c..e8a4b5c8c7 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Timing; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary.Visualisations; @@ -14,10 +13,10 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// public class BreakPart : TimelinePart { - protected override void LoadBeatmap(WorkingBeatmap beatmap) + protected override void LoadBeatmap(EditorBeatmap beatmap) { base.LoadBeatmap(beatmap); - foreach (var breakPeriod in beatmap.Beatmap.Breaks) + foreach (var breakPeriod in beatmap.Breaks) Add(new BreakVisualisation(breakPeriod)); } 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 e76ab71e54..70afc1e308 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -4,7 +4,6 @@ using System.Collections.Specialized; using System.Linq; using osu.Framework.Bindables; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts @@ -16,12 +15,12 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { private readonly IBindableList controlPointGroups = new BindableList(); - protected override void LoadBeatmap(WorkingBeatmap beatmap) + protected override void LoadBeatmap(EditorBeatmap beatmap) { base.LoadBeatmap(beatmap); controlPointGroups.UnbindAll(); - controlPointGroups.BindTo(beatmap.Beatmap.ControlPointInfo.Groups); + controlPointGroups.BindTo(beatmap.ControlPointInfo.Groups); controlPointGroups.BindCollectionChanged((sender, args) => { switch (args.Action) 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 5a2214509c..d551333616 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -2,15 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osuTK; 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.Threading; -using osu.Game.Beatmaps; using osu.Game.Graphics; +using osuTK; namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { @@ -54,9 +53,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts scheduledSeek?.Cancel(); scheduledSeek = Schedule(() => { - if (Beatmap.Value == null) - return; - float markerPos = Math.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth); editorClock.SeekSmoothlyTo(markerPos / DrawWidth * editorClock.TrackLength); }); @@ -68,7 +64,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts marker.X = (float)editorClock.CurrentTime; } - protected override void LoadBeatmap(WorkingBeatmap beatmap) + protected override void LoadBeatmap(EditorBeatmap beatmap) { // block base call so we don't clear our marker (can be reused on beatmap change). } 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 5b8f7c747b..5aba81aa7d 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -21,7 +21,10 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts /// public class TimelinePart : Container where T : Drawable { - protected readonly IBindable Beatmap = new Bindable(); + private readonly IBindable beatmap = new Bindable(); + + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } protected readonly IBindable Track = new Bindable(); @@ -33,10 +36,9 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts { AddInternal(this.content = content ?? new Container { RelativeSizeAxes = Axes.Both }); - Beatmap.ValueChanged += b => + beatmap.ValueChanged += b => { updateRelativeChildSize(); - LoadBeatmap(b.NewValue); }; Track.ValueChanged += _ => updateRelativeChildSize(); @@ -45,24 +47,26 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts [BackgroundDependencyLoader] private void load(IBindable beatmap, EditorClock clock) { - Beatmap.BindTo(beatmap); + this.beatmap.BindTo(beatmap); + LoadBeatmap(EditorBeatmap); + Track.BindTo(clock.Track); } private void updateRelativeChildSize() { // the track may not be loaded completely (only has a length once it is). - if (!Beatmap.Value.Track.IsLoaded) + if (!beatmap.Value.Track.IsLoaded) { content.RelativeChildSize = Vector2.One; Schedule(updateRelativeChildSize); return; } - content.RelativeChildSize = new Vector2((float)Math.Max(1, Beatmap.Value.Track.Length), 1); + content.RelativeChildSize = new Vector2((float)Math.Max(1, beatmap.Value.Track.Length), 1); } - protected virtual void LoadBeatmap(WorkingBeatmap beatmap) + protected virtual void LoadBeatmap(EditorBeatmap beatmap) { content.Clear(); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 13191df13c..18600bcdee 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -5,7 +5,6 @@ using System.Collections.Specialized; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; @@ -23,12 +22,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.Both; } - protected override void LoadBeatmap(WorkingBeatmap beatmap) + protected override void LoadBeatmap(EditorBeatmap beatmap) { base.LoadBeatmap(beatmap); controlPointGroups.UnbindAll(); - controlPointGroups.BindTo(beatmap.Beatmap.ControlPointInfo.Groups); + controlPointGroups.BindTo(beatmap.ControlPointInfo.Groups); controlPointGroups.BindCollectionChanged((sender, args) => { switch (args.Action) From f3061a8e837e4a59522d9a4faeac1b0e9f98aa00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Jan 2021 18:47:41 +0900 Subject: [PATCH 170/202] Update squirrel to fix incorrect desktop icon creation on install --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 4554f8b83a..e201b250d4 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -25,7 +25,7 @@ - + From 439f03e3b3d78dbdbc8ba3d6db559c13043f1e86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Jan 2021 19:25:38 +0900 Subject: [PATCH 171/202] Fix failing test due to missing dependency --- .../Visual/Editing/TestSceneEditorSummaryTimeline.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs index 3adc1bd425..94a9fd7b35 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs @@ -5,6 +5,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components.Timelines.Summary; using osuTK; @@ -13,6 +15,9 @@ namespace osu.Game.Tests.Visual.Editing [TestFixture] public class TestSceneEditorSummaryTimeline : EditorClockTestScene { + [Cached(typeof(EditorBeatmap))] + private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap()); + [BackgroundDependencyLoader] private void load() { From f89eb7d75db7982d3cdc6200b4737c630094eb87 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 13:22:37 +0100 Subject: [PATCH 172/202] Split and rename TournamentModDisplay component --- .../Components/TournamentBeatmapPanel.cs | 64 +++---------------- .../Components/TournamentModDisplay.cs | 56 ++++++++++++++++ 2 files changed, 64 insertions(+), 56 deletions(-) create mode 100644 osu.Game.Tournament/Components/TournamentModDisplay.cs diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 92ac123097..2ed99d2fb5 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -9,14 +9,11 @@ using osu.Framework.Bindables; 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.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Rulesets; -using osu.Game.Screens.Play.HUD; using osu.Game.Tournament.Models; using osuTK.Graphics; @@ -25,7 +22,7 @@ namespace osu.Game.Tournament.Components public class TournamentBeatmapPanel : CompositeDrawable { public readonly BeatmapInfo Beatmap; - private readonly string mods; + private readonly string mod; private const float horizontal_padding = 10; private const float vertical_padding = 10; @@ -40,7 +37,7 @@ namespace osu.Game.Tournament.Components if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); Beatmap = beatmap; - this.mods = mods; + this.mod = mods; Width = 400; Height = HEIGHT; } @@ -124,13 +121,16 @@ namespace osu.Game.Tournament.Components }, }); - if (!string.IsNullOrEmpty(mods)) + if (!string.IsNullOrEmpty(mod)) { - AddInternal(new ModSprite + AddInternal(new TournamentModDisplay { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Mod = mods + Margin = new MarginPadding(10), + Width = 60, + RelativeSizeAxes = Axes.Y, + ModAcronym = mod }); } } @@ -184,53 +184,5 @@ namespace osu.Game.Tournament.Components Alpha = 1; } } - - private class ModSprite : Container - { - public string Mod; - - [Resolved] - private LadderInfo ladderInfo { get; set; } - - [Resolved] - private RulesetStore rulesets { get; set; } - - public ModSprite() - { - Margin = new MarginPadding(10); - Width = 60; - RelativeSizeAxes = Axes.Y; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - var texture = textures.Get($"mods/{Mod}"); - - if (texture != null) - { - Child = new Sprite - { - FillMode = FillMode.Fit, - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Texture = texture - }; - } - else - { - Child = new ModDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Current = - { - Value = rulesets.GetRuleset(ladderInfo.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods().Where(mod => mod.Acronym == Mod).ToArray() - } - }; - } - } - } } } diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModDisplay.cs new file mode 100644 index 0000000000..a22969c20d --- /dev/null +++ b/osu.Game.Tournament/Components/TournamentModDisplay.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Rulesets; +using osu.Game.Rulesets.UI; +using osu.Game.Tournament.Models; +using osuTK; + +namespace osu.Game.Tournament.Components +{ + public class TournamentModDisplay : CompositeDrawable + { + public string ModAcronym; + + [Resolved] + private LadderInfo ladderInfo { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + var texture = textures.Get($"mods/{ModAcronym}"); + + if (texture != null) + { + AddInternal(new Sprite + { + FillMode = FillMode.Fit, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Texture = texture + }); + } + else + { + var mod = rulesets.GetRuleset(ladderInfo.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); + + AddInternal(new ModIcon(mod) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.5f) + }); + } + } + } +} From 74310da7cf550af33367a4dd0e3d49eebacf32a5 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 13:24:43 +0100 Subject: [PATCH 173/202] Change parameter to be singular mod instead of plural --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 2ed99d2fb5..e02709a045 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -32,12 +32,12 @@ namespace osu.Game.Tournament.Components private readonly Bindable currentMatch = new Bindable(); private Box flash; - public TournamentBeatmapPanel(BeatmapInfo beatmap, string mods = null) + public TournamentBeatmapPanel(BeatmapInfo beatmap, string mod = null) { if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); Beatmap = beatmap; - this.mod = mods; + this.mod = mod; Width = 400; Height = HEIGHT; } From ca08a19c409e4a454a0d6a66d7ce57d2ea845228 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 13:28:46 +0100 Subject: [PATCH 174/202] Rename mod to modIcon --- osu.Game.Tournament/Components/TournamentModDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModDisplay.cs index a22969c20d..827b3d6a69 100644 --- a/osu.Game.Tournament/Components/TournamentModDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentModDisplay.cs @@ -42,9 +42,9 @@ namespace osu.Game.Tournament.Components } else { - var mod = rulesets.GetRuleset(ladderInfo.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); + var modIcon = rulesets.GetRuleset(ladderInfo.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); - AddInternal(new ModIcon(mod) + AddInternal(new ModIcon(modIcon) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 07bd9013585ebae924cf44c501b079bb9d9b01b0 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 14:20:58 +0100 Subject: [PATCH 175/202] Add visual test for Tournament Mod Display --- .../TestSceneTournamentModDisplay.cs | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs new file mode 100644 index 0000000000..9689ecd4ae --- /dev/null +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Rulesets; +using osu.Game.Tournament.Components; + +namespace osu.Game.Tournament.Tests.Components +{ + public class TestSceneTournamentModDisplay : TournamentTestScene + { + [Resolved] + private IAPIProvider api { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } + + private FillFlowContainer fillFlow; + + private BeatmapInfo beatmap; + + [BackgroundDependencyLoader] + private void load() + { + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 490154 }); + req.Success += success; + api.Queue(req); + + Add(fillFlow = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Full, + Spacing = new osuTK.Vector2(10) + }); + } + + [Test] + public void TestModDisplay() + { + AddUntilStep("beatmap is available", () => beatmap != null); + AddStep("add maps with available mods for ruleset", () => displayForRuleset(Ladder.Ruleset.Value.ID ?? 0)); + } + + private void displayForRuleset(int rulesetId) + { + fillFlow.Clear(); + var mods = rulesets.GetRuleset(rulesetId).CreateInstance().GetAllMods(); + + foreach (var mod in mods) + { + fillFlow.Add(new TournamentBeatmapPanel(beatmap, mod.Acronym)); + } + } + + private void success(APIBeatmap apiBeatmap) => beatmap = apiBeatmap.ToBeatmap(rulesets); + } +} From 5e0ccb6c91d3e1d55968882b80d3ba0eca1971a0 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 14:21:22 +0100 Subject: [PATCH 176/202] Remove unncessary test step --- .../TestSceneTournamentModDisplay.cs | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs index 9689ecd4ae..b4d9fa4222 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.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 NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -43,24 +42,19 @@ namespace osu.Game.Tournament.Tests.Components }); } - [Test] - public void TestModDisplay() + private void success(APIBeatmap apiBeatmap) { - AddUntilStep("beatmap is available", () => beatmap != null); - AddStep("add maps with available mods for ruleset", () => displayForRuleset(Ladder.Ruleset.Value.ID ?? 0)); - } - - private void displayForRuleset(int rulesetId) - { - fillFlow.Clear(); - var mods = rulesets.GetRuleset(rulesetId).CreateInstance().GetAllMods(); + beatmap = apiBeatmap.ToBeatmap(rulesets); + var mods = rulesets.GetRuleset(Ladder.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods(); foreach (var mod in mods) { - fillFlow.Add(new TournamentBeatmapPanel(beatmap, mod.Acronym)); + fillFlow.Add(new TournamentBeatmapPanel(beatmap, mod.Acronym) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }); } } - - private void success(APIBeatmap apiBeatmap) => beatmap = apiBeatmap.ToBeatmap(rulesets); } } From 6a85f5ca8bf2a9506ed55d9a60f870b820326e2b Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 14:21:53 +0100 Subject: [PATCH 177/202] Add null checks to prevent nullrefexception in automated test --- osu.Game.Tournament/Components/TournamentModDisplay.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModDisplay.cs index 827b3d6a69..e91c27345e 100644 --- a/osu.Game.Tournament/Components/TournamentModDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentModDisplay.cs @@ -42,7 +42,15 @@ namespace osu.Game.Tournament.Components } else { - var modIcon = rulesets.GetRuleset(ladderInfo.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); + var ruleset = rulesets.AvailableRulesets.FirstOrDefault(r => r == ladderInfo.Ruleset.Value); + + if (ruleset == null) + return; + + var modIcon = ruleset.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); + + if (modIcon == null) + return; AddInternal(new ModIcon(modIcon) { From a741d91aed91f338ffecd3a4596b551c8804b52e Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 14:57:35 +0100 Subject: [PATCH 178/202] use null propragtor for Ruleset.Value and rulset instead of null checks --- .../Components/TournamentModDisplay.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModDisplay.cs index e91c27345e..369a58858e 100644 --- a/osu.Game.Tournament/Components/TournamentModDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentModDisplay.cs @@ -18,14 +18,11 @@ namespace osu.Game.Tournament.Components { public string ModAcronym; - [Resolved] - private LadderInfo ladderInfo { get; set; } - [Resolved] private RulesetStore rulesets { get; set; } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(TextureStore textures, LadderInfo ladderInfo) { var texture = textures.Get($"mods/{ModAcronym}"); @@ -42,12 +39,8 @@ namespace osu.Game.Tournament.Components } else { - var ruleset = rulesets.AvailableRulesets.FirstOrDefault(r => r == ladderInfo.Ruleset.Value); - - if (ruleset == null) - return; - - var modIcon = ruleset.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); + var ruleset = rulesets.GetRuleset(ladderInfo.Ruleset.Value?.ID ?? 0); + var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); if (modIcon == null) return; From b036f0165a077bc49cb0fd9d7e8713fb6a18fd89 Mon Sep 17 00:00:00 2001 From: Shivam Date: Mon, 25 Jan 2021 15:47:31 +0100 Subject: [PATCH 179/202] move value set to constructor and make private readonly --- .../Components/TournamentBeatmapPanel.cs | 3 +-- .../Components/TournamentModDisplay.cs | 11 ++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index e02709a045..8cc4566c08 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -123,14 +123,13 @@ namespace osu.Game.Tournament.Components if (!string.IsNullOrEmpty(mod)) { - AddInternal(new TournamentModDisplay + AddInternal(new TournamentModDisplay(mod) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Margin = new MarginPadding(10), Width = 60, RelativeSizeAxes = Axes.Y, - ModAcronym = mod }); } } diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModDisplay.cs index 369a58858e..3df8550667 100644 --- a/osu.Game.Tournament/Components/TournamentModDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentModDisplay.cs @@ -16,15 +16,20 @@ namespace osu.Game.Tournament.Components { public class TournamentModDisplay : CompositeDrawable { - public string ModAcronym; + private readonly string modAcronym; [Resolved] private RulesetStore rulesets { get; set; } + public TournamentModDisplay(string mod) + { + modAcronym = mod; + } + [BackgroundDependencyLoader] private void load(TextureStore textures, LadderInfo ladderInfo) { - var texture = textures.Get($"mods/{ModAcronym}"); + var texture = textures.Get($"mods/{modAcronym}"); if (texture != null) { @@ -40,7 +45,7 @@ namespace osu.Game.Tournament.Components else { var ruleset = rulesets.GetRuleset(ladderInfo.Ruleset.Value?.ID ?? 0); - var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == ModAcronym); + var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == modAcronym); if (modIcon == null) return; From 9efce5717f40e2ade16c4dee2cb89501d6c27c0d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 25 Jan 2021 22:11:50 +0300 Subject: [PATCH 180/202] Fix beatmap listing placeholder disappearing on second time display --- osu.Game/Overlays/BeatmapListingOverlay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 2f7f21e403..b65eaad0a2 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -176,6 +176,9 @@ namespace osu.Game.Overlays loadingLayer.Hide(); lastFetchDisplayedTime = Time.Current; + if (content == currentContent) + return; + var lastContent = currentContent; if (lastContent != null) From 9312de7c2387f4534090304550f3910c54b98e39 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 25 Jan 2021 23:40:26 +0300 Subject: [PATCH 181/202] Move online beatmap listing overlay to separate test scene --- ...ingOverlay.cs => TestSceneOnlineBeatmapListingOverlay.cs} | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/Online/{TestSceneBeatmapListingOverlay.cs => TestSceneOnlineBeatmapListingOverlay.cs} (80%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs similarity index 80% rename from osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs rename to osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs index 6cb1687d1f..fe1701a554 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs @@ -6,13 +6,14 @@ using NUnit.Framework; namespace osu.Game.Tests.Visual.Online { - public class TestSceneBeatmapListingOverlay : OsuTestScene + [Description("uses online API")] + public class TestSceneOnlineBeatmapListingOverlay : OsuTestScene { protected override bool UseOnlineAPI => true; private readonly BeatmapListingOverlay overlay; - public TestSceneBeatmapListingOverlay() + public TestSceneOnlineBeatmapListingOverlay() { Add(overlay = new BeatmapListingOverlay()); } From 75d6dbdbb7290c215505e408f15781b96128d929 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 25 Jan 2021 22:18:23 +0300 Subject: [PATCH 182/202] Fix beatmap listing placeholder potentially getting disposed --- osu.Game/Overlays/BeatmapListingOverlay.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 0c9c995dd6..2f7f21e403 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -180,18 +180,24 @@ namespace osu.Game.Overlays if (lastContent != null) { - lastContent.FadeOut(100, Easing.OutQuint).Expire(); + lastContent.FadeOut(100, Easing.OutQuint); // Consider the case when the new content is smaller than the last content. // If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird. // At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0. // To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so. - lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y).Then().Schedule(() => panelTarget.Remove(lastContent)); + lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y).Then().Schedule(() => + { + panelTarget.Remove(lastContent); + + // the content may be reused again (e.g. notFoundContent), clear Y-axis bypass for displaying back properly. + lastContent.BypassAutoSizeAxes = Axes.None; + }); } if (!content.IsAlive) panelTarget.Add(content); - content.FadeIn(200, Easing.OutQuint); + content.FadeInFromZero(200, Easing.OutQuint); currentContent = content; } From c317d6016967a321c70d02ee81d012129e8b5767 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 25 Jan 2021 23:41:05 +0300 Subject: [PATCH 183/202] Add offline test scene for beatmap listing overlay --- .../Online/TestSceneBeatmapListingOverlay.cs | 81 +++++++++++++++++++ .../API/Requests/Responses/APIBeatmapSet.cs | 2 +- osu.Game/Overlays/BeatmapListingOverlay.cs | 2 +- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs new file mode 100644 index 0000000000..1349264bf9 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs @@ -0,0 +1,81 @@ +// 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.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapListing; +using osu.Game.Rulesets; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneBeatmapListingOverlay : OsuTestScene + { + private readonly List setsForResponse = new List(); + + private BeatmapListingOverlay overlay; + + [BackgroundDependencyLoader] + private void load() + { + Child = overlay = new BeatmapListingOverlay { State = { Value = Visibility.Visible } }; + + ((DummyAPIAccess)API).HandleRequest = req => + { + if (req is SearchBeatmapSetsRequest searchBeatmapSetsRequest) + { + searchBeatmapSetsRequest.TriggerSuccess(new SearchBeatmapSetsResponse + { + BeatmapSets = setsForResponse, + }); + } + }; + } + + [Test] + public void TestNoBeatmapsPlaceholder() + { + AddStep("fetch for 0 beatmaps", () => fetchFor()); + AddUntilStep("placeholder shown", () => overlay.ChildrenOfType().SingleOrDefault()?.IsPresent == true); + + AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet)); + AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType().Any()); + + AddStep("fetch for 0 beatmaps", () => fetchFor()); + AddUntilStep("placeholder shown", () => overlay.ChildrenOfType().SingleOrDefault()?.IsPresent == true); + + // fetch once more to ensure nothing happens in displaying placeholder again when it already is present. + AddStep("fetch for 0 beatmaps again", () => fetchFor()); + AddUntilStep("placeholder shown", () => overlay.ChildrenOfType().SingleOrDefault()?.IsPresent == true); + } + + private void fetchFor(params BeatmapSetInfo[] beatmaps) + { + setsForResponse.Clear(); + setsForResponse.AddRange(beatmaps.Select(b => new TestAPIBeatmapSet(b))); + + // trigger arbitrary change for fetching. + overlay.ChildrenOfType().Single().Query.TriggerChange(); + } + + private class TestAPIBeatmapSet : APIBeatmapSet + { + private readonly BeatmapSetInfo beatmapSet; + + public TestAPIBeatmapSet(BeatmapSetInfo beatmapSet) + { + this.beatmapSet = beatmapSet; + } + + public override BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) => beatmapSet; + } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index bd1800e9f7..45d9c9405f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -81,7 +81,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"beatmaps")] private IEnumerable beatmaps { get; set; } - public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) + public virtual BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) { var beatmapSet = new BeatmapSetInfo { diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index b65eaad0a2..c5cc0a9c85 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -211,7 +211,7 @@ namespace osu.Game.Overlays base.Dispose(isDisposing); } - private class NotFoundDrawable : CompositeDrawable + public class NotFoundDrawable : CompositeDrawable { public NotFoundDrawable() { From 0d8d0d685219e162e385f0bb506735d7fedcb2e0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 26 Jan 2021 01:03:29 +0300 Subject: [PATCH 184/202] Apply alternative way of fixing --- osu.Game/Overlays/BeatmapListingOverlay.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 2f7f21e403..fc90968ec4 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -178,21 +178,18 @@ namespace osu.Game.Overlays var lastContent = currentContent; - if (lastContent != null) + // "not found" placeholder is reused, only remove without disposing through expire. + if (lastContent == notFoundContent) + lastContent.FadeOut(100, Easing.OutQuint).Schedule(() => panelTarget.Remove(lastContent)); + else if (lastContent != null) { - lastContent.FadeOut(100, Easing.OutQuint); + lastContent.FadeOut(100, Easing.OutQuint).Expire(); // Consider the case when the new content is smaller than the last content. // If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird. // At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0. // To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so. - lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y).Then().Schedule(() => - { - panelTarget.Remove(lastContent); - - // the content may be reused again (e.g. notFoundContent), clear Y-axis bypass for displaying back properly. - lastContent.BypassAutoSizeAxes = Axes.None; - }); + lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y).Then().Schedule(() => panelTarget.Remove(lastContent)); } if (!content.IsAlive) From ca0242debef0c77bde87d7f4fecdc84f3b65a8b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 15:42:48 +0900 Subject: [PATCH 185/202] Tidy up logic to correctly expire in cases where expiry is expected --- osu.Game/Overlays/BeatmapListingOverlay.cs | 27 +++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index fc90968ec4..de566c92cb 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -178,24 +178,29 @@ namespace osu.Game.Overlays var lastContent = currentContent; - // "not found" placeholder is reused, only remove without disposing through expire. - if (lastContent == notFoundContent) - lastContent.FadeOut(100, Easing.OutQuint).Schedule(() => panelTarget.Remove(lastContent)); - else if (lastContent != null) + if (lastContent != null) { - lastContent.FadeOut(100, Easing.OutQuint).Expire(); + var transform = lastContent.FadeOut(100, Easing.OutQuint); - // Consider the case when the new content is smaller than the last content. - // If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird. - // At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0. - // To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so. - lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y).Then().Schedule(() => panelTarget.Remove(lastContent)); + if (lastContent == notFoundContent) + { + // not found display may be used multiple times, so don't expire/dispose it. + transform.Schedule(() => panelTarget.Remove(lastContent)); + } + else + { + // Consider the case when the new content is smaller than the last content. + // If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird. + // At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0. + // To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so. + lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y).Then().Schedule(() => lastContent.Expire()); + } } if (!content.IsAlive) panelTarget.Add(content); - content.FadeInFromZero(200, Easing.OutQuint); + content.FadeInFromZero(200, Easing.OutQuint); currentContent = content; } From 60ae87ec383645e61194bf51f19e94d55a342023 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 16:25:49 +0900 Subject: [PATCH 186/202] Add MessagePack package --- osu.Game/osu.Game.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2b8f81532d..3e971d9d4f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,6 +22,7 @@ + From e4fc6041635c4aebfbb791c6e671324ad9156abf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 16:26:03 +0900 Subject: [PATCH 187/202] Setup all multiplayer model classes for MessagePack support --- osu.Game/Online/API/APIMod.cs | 7 ++++++- osu.Game/Online/Multiplayer/MultiplayerRoom.cs | 10 +++++++++- osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs | 7 +++++++ osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs | 8 +++++++- osu.Game/Online/Rooms/BeatmapAvailability.cs | 6 +++++- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/API/APIMod.cs b/osu.Game/Online/API/APIMod.cs index c8b76b9685..69ce3825ee 100644 --- a/osu.Game/Online/API/APIMod.cs +++ b/osu.Game/Online/API/APIMod.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Humanizer; +using MessagePack; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Game.Configuration; @@ -13,16 +14,20 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Online.API { + [MessagePackObject] public class APIMod : IMod { [JsonProperty("acronym")] + [Key(0)] public string Acronym { get; set; } [JsonProperty("settings")] + [Key(1)] public Dictionary Settings { get; set; } = new Dictionary(); [JsonConstructor] - private APIMod() + [SerializationConstructor] + public APIMod() { } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs index 12fcf25ace..c5fa6253ed 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoom.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoom.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using MessagePack; using Newtonsoft.Json; namespace osu.Game.Online.Multiplayer @@ -13,35 +14,42 @@ namespace osu.Game.Online.Multiplayer /// A multiplayer room. /// [Serializable] + [MessagePackObject] public class MultiplayerRoom { /// /// The ID of the room, used for database persistence. /// + [Key(0)] public readonly long RoomID; /// /// The current state of the room (ie. whether it is in progress or otherwise). /// + [Key(1)] public MultiplayerRoomState State { get; set; } /// /// All currently enforced game settings for this room. /// + [Key(2)] public MultiplayerRoomSettings Settings { get; set; } = new MultiplayerRoomSettings(); /// /// All users currently in this room. /// + [Key(3)] public List Users { get; set; } = new List(); /// /// The host of this room, in control of changing room settings. /// + [Key(4)] public MultiplayerRoomUser? Host { get; set; } [JsonConstructor] - public MultiplayerRoom(in long roomId) + [SerializationConstructor] + public MultiplayerRoom(long roomId) { RoomID = roomId; } diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs index 857b38ea60..0ead5db84c 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomSettings.cs @@ -7,22 +7,29 @@ using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; +using MessagePack; using osu.Game.Online.API; namespace osu.Game.Online.Multiplayer { [Serializable] + [MessagePackObject] public class MultiplayerRoomSettings : IEquatable { + [Key(0)] public int BeatmapID { get; set; } + [Key(1)] public int RulesetID { get; set; } + [Key(2)] public string BeatmapChecksum { get; set; } = string.Empty; + [Key(3)] public string Name { get; set; } = "Unnamed room"; [NotNull] + [Key(4)] public IEnumerable Mods { get; set; } = Enumerable.Empty(); public bool Equals(MultiplayerRoomSettings other) diff --git a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs index 2590acbc81..b300be9f60 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerRoomUser.cs @@ -4,6 +4,7 @@ #nullable enable using System; +using MessagePack; using Newtonsoft.Json; using osu.Game.Online.Rooms; using osu.Game.Users; @@ -11,21 +12,26 @@ using osu.Game.Users; namespace osu.Game.Online.Multiplayer { [Serializable] + [MessagePackObject] public class MultiplayerRoomUser : IEquatable { + [Key(0)] public readonly int UserID; + [Key(1)] public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle; /// /// The availability state of the current beatmap. /// + [Key(2)] public BeatmapAvailability BeatmapAvailability { get; set; } = BeatmapAvailability.LocallyAvailable(); + [IgnoreMember] public User? User { get; set; } [JsonConstructor] - public MultiplayerRoomUser(in int userId) + public MultiplayerRoomUser(int userId) { UserID = userId; } diff --git a/osu.Game/Online/Rooms/BeatmapAvailability.cs b/osu.Game/Online/Rooms/BeatmapAvailability.cs index e7dbc5f436..38bd236718 100644 --- a/osu.Game/Online/Rooms/BeatmapAvailability.cs +++ b/osu.Game/Online/Rooms/BeatmapAvailability.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using MessagePack; using Newtonsoft.Json; namespace osu.Game.Online.Rooms @@ -9,20 +10,23 @@ namespace osu.Game.Online.Rooms /// /// The local availability information about a certain beatmap for the client. /// + [MessagePackObject] public class BeatmapAvailability : IEquatable { /// /// The beatmap's availability state. /// + [Key(0)] public readonly DownloadState State; /// /// The beatmap's downloading progress, null when not in state. /// + [Key(1)] public readonly double? DownloadProgress; [JsonConstructor] - private BeatmapAvailability(DownloadState state, double? downloadProgress = null) + public BeatmapAvailability(DownloadState state, double? downloadProgress = null) { State = state; DownloadProgress = downloadProgress; From 9537090d28bb29994e5a2902c4091e69bc15856b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 16:39:35 +0900 Subject: [PATCH 188/202] Setup all spectator model classes for MessagePack --- osu.Game/Online/Spectator/FrameDataBundle.cs | 4 ++++ osu.Game/Online/Spectator/FrameHeader.cs | 10 +++++++++- osu.Game/Online/Spectator/SpectatorState.cs | 5 +++++ osu.Game/Replays/Legacy/LegacyReplayFrame.cs | 13 +++++++++++++ osu.Game/Rulesets/Replays/ReplayFrame.cs | 4 ++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Spectator/FrameDataBundle.cs b/osu.Game/Online/Spectator/FrameDataBundle.cs index a8d0434324..0e59cdf4ce 100644 --- a/osu.Game/Online/Spectator/FrameDataBundle.cs +++ b/osu.Game/Online/Spectator/FrameDataBundle.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using MessagePack; using Newtonsoft.Json; using osu.Game.Replays.Legacy; using osu.Game.Scoring; @@ -12,10 +13,13 @@ using osu.Game.Scoring; namespace osu.Game.Online.Spectator { [Serializable] + [MessagePackObject] public class FrameDataBundle { + [Key(0)] public FrameHeader Header { get; set; } + [Key(1)] public IEnumerable Frames { get; set; } public FrameDataBundle(ScoreInfo score, IEnumerable frames) diff --git a/osu.Game/Online/Spectator/FrameHeader.cs b/osu.Game/Online/Spectator/FrameHeader.cs index 135b356eda..adfcbcd95a 100644 --- a/osu.Game/Online/Spectator/FrameHeader.cs +++ b/osu.Game/Online/Spectator/FrameHeader.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using MessagePack; using Newtonsoft.Json; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -12,31 +13,37 @@ using osu.Game.Scoring; namespace osu.Game.Online.Spectator { [Serializable] + [MessagePackObject] public class FrameHeader { /// /// The current accuracy of the score. /// + [Key(0)] public double Accuracy { get; set; } /// /// The current combo of the score. /// + [Key(1)] public int Combo { get; set; } /// /// The maximum combo achieved up to the current point in time. /// + [Key(2)] public int MaxCombo { get; set; } /// /// Cumulative hit statistics. /// + [Key(3)] public Dictionary Statistics { get; set; } /// /// The time at which this frame was received by the server. /// + [Key(4)] public DateTimeOffset ReceivedTime { get; set; } /// @@ -54,7 +61,8 @@ namespace osu.Game.Online.Spectator } [JsonConstructor] - public FrameHeader(int combo, int maxCombo, double accuracy, Dictionary statistics, DateTimeOffset receivedTime) + [SerializationConstructor] + public FrameHeader(double accuracy, int combo, int maxCombo, Dictionary statistics, DateTimeOffset receivedTime) { Combo = combo; MaxCombo = maxCombo; diff --git a/osu.Game/Online/Spectator/SpectatorState.cs b/osu.Game/Online/Spectator/SpectatorState.cs index 101ce3d5d5..96a875bc14 100644 --- a/osu.Game/Online/Spectator/SpectatorState.cs +++ b/osu.Game/Online/Spectator/SpectatorState.cs @@ -5,18 +5,23 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using MessagePack; using osu.Game.Online.API; namespace osu.Game.Online.Spectator { [Serializable] + [MessagePackObject] public class SpectatorState : IEquatable { + [Key(0)] public int? BeatmapID { get; set; } + [Key(1)] public int? RulesetID { get; set; } [NotNull] + [Key(2)] public IEnumerable Mods { get; set; } = Enumerable.Empty(); public bool Equals(SpectatorState other) => BeatmapID == other?.BeatmapID && Mods.SequenceEqual(other?.Mods) && RulesetID == other?.RulesetID; diff --git a/osu.Game/Replays/Legacy/LegacyReplayFrame.cs b/osu.Game/Replays/Legacy/LegacyReplayFrame.cs index 74bacae9e1..ab9ccda9b9 100644 --- a/osu.Game/Replays/Legacy/LegacyReplayFrame.cs +++ b/osu.Game/Replays/Legacy/LegacyReplayFrame.cs @@ -1,38 +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 MessagePack; using Newtonsoft.Json; using osu.Game.Rulesets.Replays; using osuTK; namespace osu.Game.Replays.Legacy { + [MessagePackObject] public class LegacyReplayFrame : ReplayFrame { [JsonIgnore] + [IgnoreMember] public Vector2 Position => new Vector2(MouseX ?? 0, MouseY ?? 0); + [Key(1)] public float? MouseX; + + [Key(2)] public float? MouseY; [JsonIgnore] + [IgnoreMember] public bool MouseLeft => MouseLeft1 || MouseLeft2; [JsonIgnore] + [IgnoreMember] public bool MouseRight => MouseRight1 || MouseRight2; [JsonIgnore] + [IgnoreMember] public bool MouseLeft1 => ButtonState.HasFlag(ReplayButtonState.Left1); [JsonIgnore] + [IgnoreMember] public bool MouseRight1 => ButtonState.HasFlag(ReplayButtonState.Right1); [JsonIgnore] + [IgnoreMember] public bool MouseLeft2 => ButtonState.HasFlag(ReplayButtonState.Left2); [JsonIgnore] + [IgnoreMember] public bool MouseRight2 => ButtonState.HasFlag(ReplayButtonState.Right2); + [Key(3)] public ReplayButtonState ButtonState; public LegacyReplayFrame(double time, float? mouseX, float? mouseY, ReplayButtonState buttonState) diff --git a/osu.Game/Rulesets/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs index 85e068ae79..7de53211a2 100644 --- a/osu.Game/Rulesets/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -1,10 +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 MessagePack; + namespace osu.Game.Rulesets.Replays { + [MessagePackObject] public class ReplayFrame { + [Key(0)] public double Time; public ReplayFrame() From 20cfa991bffbe1cb4255b6cc45cda39b16cc28f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 17:41:21 +0900 Subject: [PATCH 189/202] Switch clients to MessagePack mode --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 2 +- osu.Game/Online/Spectator/SpectatorStreamingClient.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 50dc8f661c..3221456e75 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -70,7 +70,7 @@ namespace osu.Game.Online.Multiplayer { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); }) - .AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }) + .AddMessagePackProtocol() .Build(); // this is kind of SILLY diff --git a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs index 344b73f3d9..cc866b7ad9 100644 --- a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs +++ b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs @@ -121,7 +121,7 @@ namespace osu.Game.Online.Spectator { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); }) - .AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }) + .AddMessagePackProtocol() .Build(); // until strong typed client support is added, each method must be manually bound (see https://github.com/dotnet/aspnetcore/issues/15198) From 15885c17af58234c63ea154178f2156854e95bd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 18:07:43 +0900 Subject: [PATCH 190/202] Remove unused usings --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 1 - osu.Game/Online/Spectator/SpectatorStreamingClient.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 3221456e75..0d779232d0 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -9,7 +9,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; diff --git a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs index cc866b7ad9..dac2131035 100644 --- a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs +++ b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; From a5f3418e561efcf05800d4d2d61f9182091467a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 19:11:19 +0900 Subject: [PATCH 191/202] Avoid tooltip display --- .../Components/TournamentModDisplay.cs | 2 +- osu.Game/Overlays/Mods/ModButton.cs | 16 +++------------- osu.Game/Rulesets/UI/ModIcon.cs | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModDisplay.cs index 3df8550667..fa9ee7edff 100644 --- a/osu.Game.Tournament/Components/TournamentModDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentModDisplay.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tournament.Components if (modIcon == null) return; - AddInternal(new ModIcon(modIcon) + AddInternal(new ModIcon(modIcon, false) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index ab8efdabcc..8e0d1f5bbd 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -236,13 +236,13 @@ namespace osu.Game.Overlays.Mods { iconsContainer.AddRange(new[] { - backgroundIcon = new PassThroughTooltipModIcon(Mods[1]) + backgroundIcon = new ModIcon(Mods[1], false) { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, Position = new Vector2(1.5f), }, - foregroundIcon = new PassThroughTooltipModIcon(Mods[0]) + foregroundIcon = new ModIcon(Mods[0], false) { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, @@ -252,7 +252,7 @@ namespace osu.Game.Overlays.Mods } else { - iconsContainer.Add(foregroundIcon = new PassThroughTooltipModIcon(Mod) + iconsContainer.Add(foregroundIcon = new ModIcon(Mod, false) { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -297,15 +297,5 @@ namespace osu.Game.Overlays.Mods Mod = mod; } - - private class PassThroughTooltipModIcon : ModIcon - { - public override string TooltipText => null; - - public PassThroughTooltipModIcon(Mod mod) - : base(mod) - { - } - } } } diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 8ea6c74349..04a2e052fa 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -16,6 +16,9 @@ using osu.Framework.Bindables; namespace osu.Game.Rulesets.UI { + /// + /// Display the specified mod at a fixed size. + /// public class ModIcon : Container, IHasTooltip { public readonly BindableBool Selected = new BindableBool(); @@ -28,9 +31,10 @@ namespace osu.Game.Rulesets.UI private readonly ModType type; - public virtual string TooltipText => mod.IconTooltip; + public virtual string TooltipText => showTooltip ? mod.IconTooltip : null; private Mod mod; + private readonly bool showTooltip; public Mod Mod { @@ -42,9 +46,15 @@ namespace osu.Game.Rulesets.UI } } - public ModIcon(Mod mod) + /// + /// Construct a new instance. + /// + /// The mod to be displayed + /// Whether a tooltip describing the mod should display on hover. + public ModIcon(Mod mod, bool showTooltip = true) { this.mod = mod ?? throw new ArgumentNullException(nameof(mod)); + this.showTooltip = showTooltip; type = mod.Type; From 64a3c712aa8be74bb2d32fddeb55fc364a3cb0fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 19:15:19 +0900 Subject: [PATCH 192/202] Rename class and add xmldoc --- osu.Game.Tournament/Components/TournamentBeatmapPanel.cs | 2 +- .../{TournamentModDisplay.cs => TournamentModIcon.cs} | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) rename osu.Game.Tournament/Components/{TournamentModDisplay.cs => TournamentModIcon.cs} (86%) diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs index 8cc4566c08..d1197b1a61 100644 --- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs +++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs @@ -123,7 +123,7 @@ namespace osu.Game.Tournament.Components if (!string.IsNullOrEmpty(mod)) { - AddInternal(new TournamentModDisplay(mod) + AddInternal(new TournamentModIcon(mod) { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, diff --git a/osu.Game.Tournament/Components/TournamentModDisplay.cs b/osu.Game.Tournament/Components/TournamentModIcon.cs similarity index 86% rename from osu.Game.Tournament/Components/TournamentModDisplay.cs rename to osu.Game.Tournament/Components/TournamentModIcon.cs index fa9ee7edff..b53ecc02f8 100644 --- a/osu.Game.Tournament/Components/TournamentModDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentModIcon.cs @@ -14,16 +14,19 @@ using osuTK; namespace osu.Game.Tournament.Components { - public class TournamentModDisplay : CompositeDrawable + /// + /// Mod icon displayed in tournament usages, allowing user overridden graphics. + /// + public class TournamentModIcon : CompositeDrawable { private readonly string modAcronym; [Resolved] private RulesetStore rulesets { get; set; } - public TournamentModDisplay(string mod) + public TournamentModIcon(string modAcronym) { - modAcronym = mod; + this.modAcronym = modAcronym; } [BackgroundDependencyLoader] From 81ab82fafe13df7aa513c5d64f3bb205feac6102 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 26 Jan 2021 19:16:38 +0900 Subject: [PATCH 193/202] Tidy up nesting --- .../Components/TournamentModIcon.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentModIcon.cs b/osu.Game.Tournament/Components/TournamentModIcon.cs index b53ecc02f8..43ac92d285 100644 --- a/osu.Game.Tournament/Components/TournamentModIcon.cs +++ b/osu.Game.Tournament/Components/TournamentModIcon.cs @@ -32,9 +32,9 @@ namespace osu.Game.Tournament.Components [BackgroundDependencyLoader] private void load(TextureStore textures, LadderInfo ladderInfo) { - var texture = textures.Get($"mods/{modAcronym}"); + var customTexture = textures.Get($"mods/{modAcronym}"); - if (texture != null) + if (customTexture != null) { AddInternal(new Sprite { @@ -42,24 +42,24 @@ namespace osu.Game.Tournament.Components RelativeSizeAxes = Axes.Both, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Texture = texture + Texture = customTexture }); + + return; } - else + + var ruleset = rulesets.GetRuleset(ladderInfo.Ruleset.Value?.ID ?? 0); + var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == modAcronym); + + if (modIcon == null) + return; + + AddInternal(new ModIcon(modIcon, false) { - var ruleset = rulesets.GetRuleset(ladderInfo.Ruleset.Value?.ID ?? 0); - var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == modAcronym); - - if (modIcon == null) - return; - - AddInternal(new ModIcon(modIcon, false) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(0.5f) - }); - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(0.5f) + }); } } } From 45395cb5e8fcf22d495908f7c77a3b5d90624d98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 27 Jan 2021 23:00:14 +0900 Subject: [PATCH 194/202] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 9ad5946311..f8ce6befd4 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3e971d9d4f..97f4320c95 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -27,7 +27,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 4732620085..301e7378a6 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From 63f057a525e01e3c58ede431293b124c8b14d70d Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 27 Jan 2021 20:45:48 +0300 Subject: [PATCH 195/202] Fix dotnet run/publish with runtime specified not working again --- osu.Desktop/osu.Desktop.csproj | 5 +---- osu.Game/osu.Game.csproj | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index e201b250d4..cce7907c6c 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -24,16 +24,13 @@ + - - - - diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 97f4320c95..eb541c9de5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,6 +26,7 @@ + From 2c08ce05fa18828248c1fe45aea502059917c0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 27 Jan 2021 22:01:56 +0100 Subject: [PATCH 196/202] Remove game-local enum [Order] attribute In favour of the newly-added framework one. --- .../BeatmapListing/BeatmapSearchFilterRow.cs | 4 +- .../Overlays/BeatmapListing/SearchLanguage.cs | 2 +- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 4 +- osu.Game/Rulesets/Ruleset.cs | 6 +-- osu.Game/Rulesets/Scoring/HitResult.cs | 2 +- osu.Game/Utils/OrderAttribute.cs | 52 ------------------- 6 files changed, 9 insertions(+), 61 deletions(-) delete mode 100644 osu.Game/Utils/OrderAttribute.cs diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index b429a5277b..01bcbd3244 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK; using Humanizer; -using osu.Game.Utils; +using osu.Framework.Extensions.EnumExtensions; namespace osu.Game.Overlays.BeatmapListing { @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.BeatmapListing if (typeof(T).IsEnum) { - foreach (var val in OrderAttributeUtils.GetValuesInOrder()) + foreach (var val in EnumExtensions.GetValuesInOrder()) AddItem(val); } } diff --git a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs index eee5d8f7e1..015cee8ce3 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs @@ -1,7 +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 osu.Game.Utils; +using osu.Framework.Utils; namespace osu.Game.Overlays.BeatmapListing { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 324299ccba..ddd1dfa6cd 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions; +using osu.Framework.Extensions.EnumExtensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -15,7 +16,6 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Users.Drawables; -using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -105,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores var ruleset = scores.First().Ruleset.CreateInstance(); - foreach (var result in OrderAttributeUtils.GetValuesInOrder()) + foreach (var result in EnumExtensions.GetValuesInOrder()) { if (!allScoreStatistics.Contains(result)) continue; diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index b3b3d11ab3..dbc2bd4d01 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -24,9 +24,9 @@ using osu.Game.Skinning; using osu.Game.Users; using JetBrains.Annotations; using osu.Framework.Extensions; +using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Testing; using osu.Game.Screens.Ranking.Statistics; -using osu.Game.Utils; namespace osu.Game.Rulesets { @@ -272,7 +272,7 @@ namespace osu.Game.Rulesets var validResults = GetValidHitResults(); // enumerate over ordered list to guarantee return order is stable. - foreach (var result in OrderAttributeUtils.GetValuesInOrder()) + foreach (var result in EnumExtensions.GetValuesInOrder()) { switch (result) { @@ -298,7 +298,7 @@ namespace osu.Game.Rulesets /// /// is implicitly included. Special types like are ignored even when specified. /// - protected virtual IEnumerable GetValidHitResults() => OrderAttributeUtils.GetValuesInOrder(); + protected virtual IEnumerable GetValidHitResults() => EnumExtensions.GetValuesInOrder(); /// /// Get a display friendly name for the specified result type. diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 6a3a034fc1..eaa1f95744 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -3,7 +3,7 @@ using System.ComponentModel; using System.Diagnostics; -using osu.Game.Utils; +using osu.Framework.Utils; namespace osu.Game.Rulesets.Scoring { diff --git a/osu.Game/Utils/OrderAttribute.cs b/osu.Game/Utils/OrderAttribute.cs deleted file mode 100644 index aded7f9814..0000000000 --- a/osu.Game/Utils/OrderAttribute.cs +++ /dev/null @@ -1,52 +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.Linq; - -namespace osu.Game.Utils -{ - public static class OrderAttributeUtils - { - /// - /// Get values of an enum in order. Supports custom ordering via . - /// - public static IEnumerable GetValuesInOrder() - { - var type = typeof(T); - - if (!type.IsEnum) - throw new InvalidOperationException("T must be an enum"); - - IEnumerable items = (T[])Enum.GetValues(type); - - if (Attribute.GetCustomAttribute(type, typeof(HasOrderedElementsAttribute)) == null) - return items; - - return items.OrderBy(i => - { - if (type.GetField(i.ToString()).GetCustomAttributes(typeof(OrderAttribute), false).FirstOrDefault() is OrderAttribute attr) - return attr.Order; - - throw new ArgumentException($"Not all values of {nameof(T)} have {nameof(OrderAttribute)} specified."); - }); - } - } - - [AttributeUsage(AttributeTargets.Field)] - public class OrderAttribute : Attribute - { - public readonly int Order; - - public OrderAttribute(int order) - { - Order = order; - } - } - - [AttributeUsage(AttributeTargets.Enum)] - public class HasOrderedElementsAttribute : Attribute - { - } -} From 90a82f986bcd2ba59f0ebc3ccc95e942a3e5665a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Jan 2021 16:20:16 +0900 Subject: [PATCH 197/202] Fallback to using json for signalr communication if JIT is unavailable --- .../Online/Multiplayer/MultiplayerClient.cs | 22 +++++++++++++------ .../Spectator/SpectatorStreamingClient.cs | 21 ++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 0d779232d0..c10c4dd1b0 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -9,6 +9,8 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; @@ -64,13 +66,19 @@ namespace osu.Game.Online.Multiplayer if (connection != null) return; - connection = new HubConnectionBuilder() - .WithUrl(endpoint, options => - { - options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); - }) - .AddMessagePackProtocol() - .Build(); + var builder = new HubConnectionBuilder() + .WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); }); + + if (RuntimeInfo.SupportsJIT) + builder.AddMessagePackProtocol(); + else + { + // eventuall we will precompile resolvers for messagepack, but this isn't working currently + // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308. + builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); + } + + connection = builder.Build(); // this is kind of SILLY // https://github.com/dotnet/aspnetcore/issues/15198 diff --git a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs index dac2131035..7a28c179a8 100644 --- a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs +++ b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs @@ -9,6 +9,8 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -115,14 +117,19 @@ namespace osu.Game.Online.Spectator if (connection != null) return; - connection = new HubConnectionBuilder() - .WithUrl(endpoint, options => - { - options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); - }) - .AddMessagePackProtocol() - .Build(); + var builder = new HubConnectionBuilder() + .WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); }); + if (RuntimeInfo.SupportsJIT) + builder.AddMessagePackProtocol(); + else + { + // eventuall we will precompile resolvers for messagepack, but this isn't working currently + // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308. + builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); + } + + connection = builder.Build(); // until strong typed client support is added, each method must be manually bound (see https://github.com/dotnet/aspnetcore/issues/15198) connection.On(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying); connection.On(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames); From c3d40440170e98e026bfceaf3dbd25901704e7ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Jan 2021 16:53:56 +0900 Subject: [PATCH 198/202] Avoid using Dapper to fix iOS compatibility of beatmap lookup cache --- ...BeatmapManager_BeatmapOnlineLookupQueue.cs | 32 ++++++++++++------- osu.Game/osu.Game.csproj | 1 - 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs b/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs index e90ccbb805..ea91f2d2e0 100644 --- a/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs +++ b/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Dapper; using Microsoft.Data.Sqlite; using osu.Framework.Development; using osu.Framework.IO.Network; @@ -154,20 +153,31 @@ namespace osu.Game.Beatmaps { using (var db = new SqliteConnection(storage.GetDatabaseConnectionString("online"))) { - var found = db.QuerySingleOrDefault( - "SELECT * FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineBeatmapID OR filename = @Path", beatmap); + db.Open(); - if (found != null) + using (var cmd = db.CreateCommand()) { - var status = (BeatmapSetOnlineStatus)found.approved; + cmd.CommandText = "SELECT beatmapset_id, beatmap_id, approved FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineBeatmapID OR filename = @Path"; - beatmap.Status = status; - beatmap.BeatmapSet.Status = status; - beatmap.BeatmapSet.OnlineBeatmapSetID = found.beatmapset_id; - beatmap.OnlineBeatmapID = found.beatmap_id; + cmd.Parameters.Add(new SqliteParameter("@MD5Hash", beatmap.MD5Hash)); + cmd.Parameters.Add(new SqliteParameter("@OnlineBeatmapID", beatmap.OnlineBeatmapID)); + cmd.Parameters.Add(new SqliteParameter("@Path", beatmap.Path)); - LogForModel(set, $"Cached local retrieval for {beatmap}."); - return true; + using (var reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + var status = (BeatmapSetOnlineStatus)reader.GetByte(2); + + beatmap.Status = status; + beatmap.BeatmapSet.Status = status; + beatmap.BeatmapSet.OnlineBeatmapSetID = reader.GetInt32(0); + beatmap.OnlineBeatmapID = reader.GetInt32(1); + + LogForModel(set, $"Cached local retrieval for {beatmap}."); + return true; + } + } } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 97f4320c95..bfc5ff302e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,6 @@ - From a616688a47a1d2d1c952eb8fe173cd88f8a64c37 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Jan 2021 23:55:03 +0900 Subject: [PATCH 199/202] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f8ce6befd4..7060e88026 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 97f4320c95..a18eef15fc 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -27,7 +27,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 301e7378a6..48dc01f5de 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From 386f9f78423f205490c817cab468d09a32d12339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 28 Jan 2021 22:36:07 +0100 Subject: [PATCH 200/202] Fix typos in comments --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 2 +- osu.Game/Online/Spectator/SpectatorStreamingClient.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index c10c4dd1b0..b13d4fa899 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -73,7 +73,7 @@ namespace osu.Game.Online.Multiplayer builder.AddMessagePackProtocol(); else { - // eventuall we will precompile resolvers for messagepack, but this isn't working currently + // eventually we will precompile resolvers for messagepack, but this isn't working currently // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308. builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); } diff --git a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs index 7a28c179a8..b95e3f1297 100644 --- a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs +++ b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs @@ -124,7 +124,7 @@ namespace osu.Game.Online.Spectator builder.AddMessagePackProtocol(); else { - // eventuall we will precompile resolvers for messagepack, but this isn't working currently + // eventually we will precompile resolvers for messagepack, but this isn't working currently // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308. builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); } From da4c207a73b4beb25a59237a2e43ce674ed9ec99 Mon Sep 17 00:00:00 2001 From: Corentin PALLARD Date: Fri, 29 Jan 2021 02:53:26 +0100 Subject: [PATCH 201/202] Fix the ctb auto mod speedup in some occasions --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 32e8ab5da7..ae6868aea5 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -45,6 +45,9 @@ namespace osu.Game.Rulesets.Catch.Replays float positionChange = Math.Abs(lastPosition - h.EffectiveX); double timeAvailable = h.StartTime - lastTime; + if (timeAvailable < 0) + return; + // So we can either make it there without a dash or not. // If positionChange is 0, we don't need to move, so speedRequired should also be 0 (could be NaN if timeAvailable is 0 too) // The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour. From d168de0ae32f0877d225efc13942b96a57a9bba2 Mon Sep 17 00:00:00 2001 From: Corentin PALLARD Date: Fri, 29 Jan 2021 03:03:23 +0100 Subject: [PATCH 202/202] Formatting --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index ae6868aea5..64ded8e94f 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -46,7 +46,9 @@ namespace osu.Game.Rulesets.Catch.Replays double timeAvailable = h.StartTime - lastTime; if (timeAvailable < 0) + { return; + } // So we can either make it there without a dash or not. // If positionChange is 0, we don't need to move, so speedRequired should also be 0 (could be NaN if timeAvailable is 0 too)