mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 11:42:56 +08:00
Merge branch 'ppy:master' into colour-encoding-2
This commit is contained in:
commit
55e5b41c03
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -126,6 +126,12 @@ jobs:
|
||||
with:
|
||||
dotnet-version: "6.0.x"
|
||||
|
||||
# macOS agents recently have empty NuGet config files, resulting in restore failures,
|
||||
# see https://github.com/actions/virtual-environments/issues/5768
|
||||
# Add the global nuget package source manually for now.
|
||||
- name: Setup NuGet.Config
|
||||
run: echo '<configuration><packageSources><add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /></packageSources></configuration>' > ~/.config/NuGet/NuGet.Config
|
||||
|
||||
# Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
|
||||
# cannot accept .sln(f) files as arguments.
|
||||
# Build just the main game for now.
|
||||
|
@ -16,3 +16,6 @@ M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Linq.IQueryable
|
||||
M:Realms.CollectionExtensions.SubscribeForNotifications`1(System.Collections.Generic.IList{``0},Realms.NotificationCallbackDelegate{``0});Use osu.Game.Database.RealmObjectExtensions.QueryAsyncWithNotifications(IList<T>,NotificationCallbackDelegate<T>) instead.
|
||||
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
|
||||
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.GetResultSafely() to ensure we avoid deadlocks.
|
||||
M:System.Threading.ManualResetEventSlim.Wait();Specify a timeout to avoid waiting forever.
|
||||
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!-- Contains required properties for osu!framework projects. -->
|
||||
<Project>
|
||||
<PropertyGroup Label="C#">
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
@ -51,8 +51,8 @@
|
||||
<Reference Include="Java.Interop" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.616.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.615.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.623.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.624.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Transitive Dependencies">
|
||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||
|
97
osu.Android/AndroidMouseSettings.cs
Normal file
97
osu.Android/AndroidMouseSettings.cs
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using Android.OS;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Overlays.Settings.Sections.Input;
|
||||
|
||||
namespace osu.Android
|
||||
{
|
||||
public class AndroidMouseSettings : SettingsSubsection
|
||||
{
|
||||
private readonly AndroidMouseHandler mouseHandler;
|
||||
|
||||
protected override LocalisableString Header => MouseSettingsStrings.Mouse;
|
||||
|
||||
private Bindable<double> handlerSensitivity = null!;
|
||||
|
||||
private Bindable<double> localSensitivity = null!;
|
||||
|
||||
private Bindable<bool> relativeMode = null!;
|
||||
|
||||
public AndroidMouseSettings(AndroidMouseHandler mouseHandler)
|
||||
{
|
||||
this.mouseHandler = mouseHandler;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager osuConfig)
|
||||
{
|
||||
// use local bindable to avoid changing enabled state of game host's bindable.
|
||||
handlerSensitivity = mouseHandler.Sensitivity.GetBoundCopy();
|
||||
localSensitivity = handlerSensitivity.GetUnboundCopy();
|
||||
|
||||
relativeMode = mouseHandler.UseRelativeMode.GetBoundCopy();
|
||||
|
||||
// High precision/pointer capture is only available on Android 8.0 and up
|
||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
|
||||
{
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = MouseSettingsStrings.HighPrecisionMouse,
|
||||
TooltipText = MouseSettingsStrings.HighPrecisionMouseTooltip,
|
||||
Current = relativeMode,
|
||||
Keywords = new[] { @"raw", @"input", @"relative", @"cursor", @"captured", @"pointer" },
|
||||
},
|
||||
new MouseSettings.SensitivitySetting
|
||||
{
|
||||
LabelText = MouseSettingsStrings.CursorSensitivity,
|
||||
Current = localSensitivity,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust,
|
||||
TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip,
|
||||
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableWheel),
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = MouseSettingsStrings.DisableMouseButtons,
|
||||
Current = osuConfig.GetBindable<bool>(OsuSetting.MouseDisableButtons),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
relativeMode.BindValueChanged(relative => localSensitivity.Disabled = !relative.NewValue, true);
|
||||
|
||||
handlerSensitivity.BindValueChanged(val =>
|
||||
{
|
||||
bool disabled = localSensitivity.Disabled;
|
||||
|
||||
localSensitivity.Disabled = false;
|
||||
localSensitivity.Value = val.NewValue;
|
||||
localSensitivity.Disabled = disabled;
|
||||
}, true);
|
||||
|
||||
localSensitivity.BindValueChanged(val => handlerSensitivity.Value = val.NewValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,11 @@ using System;
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Android.Input;
|
||||
using osu.Framework.Input.Handlers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Updater;
|
||||
using osu.Game.Utils;
|
||||
using Xamarin.Essentials;
|
||||
@ -75,10 +79,28 @@ namespace osu.Android
|
||||
LoadComponentAsync(new GameplayScreenRotationLocker(), Add);
|
||||
}
|
||||
|
||||
public override void SetHost(GameHost host)
|
||||
{
|
||||
base.SetHost(host);
|
||||
host.Window.CursorState |= CursorState.Hidden;
|
||||
}
|
||||
|
||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||
|
||||
protected override BatteryInfo CreateBatteryInfo() => new AndroidBatteryInfo();
|
||||
|
||||
public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler)
|
||||
{
|
||||
switch (handler)
|
||||
{
|
||||
case AndroidMouseHandler mh:
|
||||
return new AndroidMouseSettings(mh);
|
||||
|
||||
default:
|
||||
return base.CreateSettingsSubsectionFor(handler);
|
||||
}
|
||||
}
|
||||
|
||||
private class AndroidBatteryInfo : BatteryInfo
|
||||
{
|
||||
public override double ChargeLevel => Battery.ChargeLevel;
|
||||
|
@ -26,6 +26,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AndroidMouseSettings.cs" />
|
||||
<Compile Include="GameplayScreenRotationLocker.cs" />
|
||||
<Compile Include="OsuGameActivity.cs" />
|
||||
<Compile Include="OsuGameAndroid.cs" />
|
||||
|
@ -57,7 +57,7 @@ namespace osu.Desktop
|
||||
client.OnReady += onReady;
|
||||
|
||||
// safety measure for now, until we performance test / improve backoff for failed connections.
|
||||
client.OnConnectionFailed += (_, __) => client.Deinitialize();
|
||||
client.OnConnectionFailed += (_, _) => client.Deinitialize();
|
||||
|
||||
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network);
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@ -20,25 +18,34 @@ using osu.Framework;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Updater;
|
||||
using osu.Desktop.Windows;
|
||||
using osu.Framework.Input.Handlers;
|
||||
using osu.Framework.Input.Handlers.Joystick;
|
||||
using osu.Framework.Input.Handlers.Mouse;
|
||||
using osu.Framework.Input.Handlers.Tablet;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Overlays.Settings.Sections.Input;
|
||||
|
||||
namespace osu.Desktop
|
||||
{
|
||||
internal class OsuGameDesktop : OsuGame
|
||||
{
|
||||
public OsuGameDesktop(string[] args = null)
|
||||
private OsuSchemeLinkIPCChannel? osuSchemeLinkIPCChannel;
|
||||
|
||||
public OsuGameDesktop(string[]? args = null)
|
||||
: base(args)
|
||||
{
|
||||
}
|
||||
|
||||
public override StableStorage GetStorageForStableInstall()
|
||||
public override StableStorage? GetStorageForStableInstall()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Host is DesktopGameHost desktopHost)
|
||||
{
|
||||
string stablePath = getStableInstallPath();
|
||||
string? stablePath = getStableInstallPath();
|
||||
if (!string.IsNullOrEmpty(stablePath))
|
||||
return new StableStorage(stablePath, desktopHost);
|
||||
}
|
||||
@ -51,11 +58,11 @@ namespace osu.Desktop
|
||||
return null;
|
||||
}
|
||||
|
||||
private string getStableInstallPath()
|
||||
private string? getStableInstallPath()
|
||||
{
|
||||
static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg"));
|
||||
|
||||
string stableInstallPath;
|
||||
string? stableInstallPath;
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
@ -83,15 +90,15 @@ namespace osu.Desktop
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private string getStableInstallPathFromRegistry()
|
||||
private string? getStableInstallPathFromRegistry()
|
||||
{
|
||||
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||
using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||
return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
||||
}
|
||||
|
||||
protected override UpdateManager CreateUpdateManager()
|
||||
{
|
||||
string packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER");
|
||||
string? packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER");
|
||||
|
||||
if (!string.IsNullOrEmpty(packageManaged))
|
||||
return new NoActionUpdateManager();
|
||||
@ -118,6 +125,8 @@ namespace osu.Desktop
|
||||
LoadComponentAsync(new GameplayWinKeyBlocker(), Add);
|
||||
|
||||
LoadComponentAsync(new ElevatedPrivilegesChecker(), Add);
|
||||
|
||||
osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this);
|
||||
}
|
||||
|
||||
public override void SetHost(GameHost host)
|
||||
@ -134,8 +143,26 @@ namespace osu.Desktop
|
||||
desktopWindow.DragDrop += f => fileDrop(new[] { f });
|
||||
}
|
||||
|
||||
public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler)
|
||||
{
|
||||
switch (handler)
|
||||
{
|
||||
case ITabletHandler th:
|
||||
return new TabletSettings(th);
|
||||
|
||||
case MouseHandler mh:
|
||||
return new MouseSettings(mh);
|
||||
|
||||
case JoystickHandler jh:
|
||||
return new JoystickSettings(jh);
|
||||
|
||||
default:
|
||||
return base.CreateSettingsSubsectionFor(handler);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<string> importableFiles = new List<string>();
|
||||
private ScheduledDelegate importSchedule;
|
||||
private ScheduledDelegate? importSchedule;
|
||||
|
||||
private void fileDrop(string[] filePaths)
|
||||
{
|
||||
@ -168,5 +195,11 @@ namespace osu.Desktop
|
||||
Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
osuSchemeLinkIPCChannel?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ using osu.Framework;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Tournament;
|
||||
using Squirrel;
|
||||
@ -65,19 +66,8 @@ namespace osu.Desktop
|
||||
{
|
||||
if (!host.IsPrimaryInstance)
|
||||
{
|
||||
if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args
|
||||
{
|
||||
var importer = new ArchiveImportIPCChannel(host);
|
||||
|
||||
foreach (string file in args)
|
||||
{
|
||||
Console.WriteLine(@"Importing {0}", file);
|
||||
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))
|
||||
throw new TimeoutException(@"IPC took too long to send");
|
||||
}
|
||||
|
||||
if (trySendIPCMessage(host, cwd, args))
|
||||
return;
|
||||
}
|
||||
|
||||
// we want to allow multiple instances to be started when in debug.
|
||||
if (!DebugUtils.IsDebugBuild)
|
||||
@ -108,21 +98,49 @@ namespace osu.Desktop
|
||||
}
|
||||
}
|
||||
|
||||
private static bool trySendIPCMessage(IIpcHost host, string cwd, string[] args)
|
||||
{
|
||||
if (args.Length == 1 && args[0].StartsWith(OsuGameBase.OSU_PROTOCOL, StringComparison.Ordinal))
|
||||
{
|
||||
var osuSchemeLinkHandler = new OsuSchemeLinkIPCChannel(host);
|
||||
if (!osuSchemeLinkHandler.HandleLinkAsync(args[0]).Wait(3000))
|
||||
throw new IPCTimeoutException(osuSchemeLinkHandler.GetType());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args
|
||||
{
|
||||
var importer = new ArchiveImportIPCChannel(host);
|
||||
|
||||
foreach (string file in args)
|
||||
{
|
||||
Console.WriteLine(@"Importing {0}", file);
|
||||
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))
|
||||
throw new IPCTimeoutException(importer.GetType());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void setupSquirrel()
|
||||
{
|
||||
SquirrelAwareApp.HandleEvents(onInitialInstall: (version, tools) =>
|
||||
SquirrelAwareApp.HandleEvents(onInitialInstall: (_, tools) =>
|
||||
{
|
||||
tools.CreateShortcutForThisExe();
|
||||
tools.CreateUninstallerRegistryEntry();
|
||||
}, onAppUpdate: (version, tools) =>
|
||||
}, onAppUpdate: (_, tools) =>
|
||||
{
|
||||
tools.CreateUninstallerRegistryEntry();
|
||||
}, onAppUninstall: (version, tools) =>
|
||||
}, onAppUninstall: (_, tools) =>
|
||||
{
|
||||
tools.RemoveShortcutForThisExe();
|
||||
tools.RemoveUninstallerRegistryEntry();
|
||||
}, onEveryRun: (version, tools, firstRun) =>
|
||||
}, onEveryRun: (_, _, _) =>
|
||||
{
|
||||
// While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently
|
||||
// causes the right-click context menu to function incorrectly.
|
||||
|
@ -154,7 +154,7 @@ namespace osu.Desktop.Updater
|
||||
Activated = () =>
|
||||
{
|
||||
updateManager.PrepareUpdateAsync()
|
||||
.ContinueWith(_ => updateManager.Schedule(() => game?.GracefullyExit()));
|
||||
.ContinueWith(_ => updateManager.Schedule(() => game?.AttemptExit()));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Benchmarks
|
||||
|
||||
realm = new RealmAccess(storage, OsuGameBase.CLIENT_DATABASE_FILENAME);
|
||||
|
||||
realm.Run(r =>
|
||||
realm.Run(_ =>
|
||||
{
|
||||
realm.Write(c => c.Add(TestResources.CreateTestBeatmapSetInfo(rulesets: new[] { new OsuRuleset().RulesetInfo })));
|
||||
});
|
||||
@ -76,7 +76,7 @@ namespace osu.Game.Benchmarks
|
||||
}
|
||||
});
|
||||
|
||||
done.Wait();
|
||||
done.Wait(60000);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
@ -115,7 +115,7 @@ namespace osu.Game.Benchmarks
|
||||
}
|
||||
});
|
||||
|
||||
done.Wait();
|
||||
done.Wait(60000);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
|
@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
new JuiceStreamPathVertex(20, -5)
|
||||
}));
|
||||
|
||||
removeCount = path.RemoveVertices((_, i) => true);
|
||||
removeCount = path.RemoveVertices((_, _) => true);
|
||||
Assert.That(removeCount, Is.EqualTo(1));
|
||||
Assert.That(path.Vertices, Is.EqualTo(new[]
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
hyperDashCount = 0;
|
||||
|
||||
// this needs to be done within the frame stable context due to how quickly hyperdash state changes occur.
|
||||
Player.DrawableRuleset.FrameStableComponents.OnUpdate += d =>
|
||||
Player.DrawableRuleset.FrameStableComponents.OnUpdate += _ =>
|
||||
{
|
||||
var catcher = Player.ChildrenOfType<Catcher>().FirstOrDefault();
|
||||
|
||||
|
@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
protected override string RulesetPrefix => "catch"; // todo: use CatchRuleset.SHORT_NAME;
|
||||
|
||||
protected override string ComponentName => Component.ToString().ToLower();
|
||||
protected override string ComponentName => Component.ToString().ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
|
@ -135,15 +135,15 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
{
|
||||
switch (BlueprintContainer.CurrentTool)
|
||||
{
|
||||
case SelectTool _:
|
||||
case SelectTool:
|
||||
if (EditorBeatmap.SelectedHitObjects.Count == 0)
|
||||
return null;
|
||||
|
||||
double minTime = EditorBeatmap.SelectedHitObjects.Min(hitObject => hitObject.StartTime);
|
||||
return getLastSnappableHitObject(minTime);
|
||||
|
||||
case FruitCompositionTool _:
|
||||
case JuiceStreamCompositionTool _:
|
||||
case FruitCompositionTool:
|
||||
case JuiceStreamCompositionTool:
|
||||
if (!CursorInPlacementArea)
|
||||
return null;
|
||||
|
||||
|
@ -42,10 +42,10 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
case Droplet droplet:
|
||||
return droplet is TinyDroplet ? PositionRange.EMPTY : new PositionRange(droplet.OriginalX);
|
||||
|
||||
case JuiceStream _:
|
||||
case JuiceStream:
|
||||
return GetPositionRange(hitObject.NestedHitObjects);
|
||||
|
||||
case BananaShower _:
|
||||
case BananaShower:
|
||||
// A banana shower occupies the whole screen width.
|
||||
return new PositionRange(0, CatchPlayfield.WIDTH);
|
||||
|
||||
|
@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case BananaShower _:
|
||||
case BananaShower:
|
||||
return false;
|
||||
|
||||
case JuiceStream juiceStream:
|
||||
|
@ -389,13 +389,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case Fruit _:
|
||||
case Fruit:
|
||||
return caughtFruitPool.Get();
|
||||
|
||||
case Banana _:
|
||||
case Banana:
|
||||
return caughtBananaPool.Get();
|
||||
|
||||
case Droplet _:
|
||||
case Droplet:
|
||||
return caughtDropletPool.Get();
|
||||
|
||||
default:
|
||||
|
@ -173,7 +173,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
|
||||
switch (original)
|
||||
{
|
||||
case IHasDistance _:
|
||||
case IHasDistance:
|
||||
{
|
||||
var generator = new DistanceObjectPatternGenerator(Random, original, beatmap, lastPattern, originalBeatmap);
|
||||
conversion = generator;
|
||||
|
@ -156,9 +156,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case ManiaModNoFail _:
|
||||
case ManiaModEasy _:
|
||||
case ManiaModHalfTime _:
|
||||
case ManiaModNoFail:
|
||||
case ManiaModEasy:
|
||||
case ManiaModHalfTime:
|
||||
scoreMultiplier *= 0.5;
|
||||
break;
|
||||
}
|
||||
|
@ -146,56 +146,56 @@ namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
case ManiaModKey1 _:
|
||||
case ManiaModKey1:
|
||||
value |= LegacyMods.Key1;
|
||||
break;
|
||||
|
||||
case ManiaModKey2 _:
|
||||
case ManiaModKey2:
|
||||
value |= LegacyMods.Key2;
|
||||
break;
|
||||
|
||||
case ManiaModKey3 _:
|
||||
case ManiaModKey3:
|
||||
value |= LegacyMods.Key3;
|
||||
break;
|
||||
|
||||
case ManiaModKey4 _:
|
||||
case ManiaModKey4:
|
||||
value |= LegacyMods.Key4;
|
||||
break;
|
||||
|
||||
case ManiaModKey5 _:
|
||||
case ManiaModKey5:
|
||||
value |= LegacyMods.Key5;
|
||||
break;
|
||||
|
||||
case ManiaModKey6 _:
|
||||
case ManiaModKey6:
|
||||
value |= LegacyMods.Key6;
|
||||
break;
|
||||
|
||||
case ManiaModKey7 _:
|
||||
case ManiaModKey7:
|
||||
value |= LegacyMods.Key7;
|
||||
break;
|
||||
|
||||
case ManiaModKey8 _:
|
||||
case ManiaModKey8:
|
||||
value |= LegacyMods.Key8;
|
||||
break;
|
||||
|
||||
case ManiaModKey9 _:
|
||||
case ManiaModKey9:
|
||||
value |= LegacyMods.Key9;
|
||||
break;
|
||||
|
||||
case ManiaModDualStages _:
|
||||
case ManiaModDualStages:
|
||||
value |= LegacyMods.KeyCoop;
|
||||
break;
|
||||
|
||||
case ManiaModFadeIn _:
|
||||
case ManiaModFadeIn:
|
||||
value |= LegacyMods.FadeIn;
|
||||
value &= ~LegacyMods.Hidden; // this is toggled on in the base call due to inheritance, but we don't want that.
|
||||
break;
|
||||
|
||||
case ManiaModMirror _:
|
||||
case ManiaModMirror:
|
||||
value |= LegacyMods.Mirror;
|
||||
break;
|
||||
|
||||
case ManiaModRandom _:
|
||||
case ManiaModRandom:
|
||||
value |= LegacyMods.Random;
|
||||
break;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
|
||||
|
||||
protected override string ComponentName => Component.ToString().ToLower();
|
||||
protected override string ComponentName => Component.ToString().ToLowerInvariant();
|
||||
}
|
||||
|
||||
public enum ManiaSkinComponents
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
var rng = new Random((int)Seed.Value);
|
||||
|
||||
int availableColumns = ((ManiaBeatmap)beatmap).TotalColumns;
|
||||
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => rng.Next()).ToList();
|
||||
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(_ => rng.Next()).ToList();
|
||||
|
||||
beatmap.HitObjects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]);
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ namespace osu.Game.Rulesets.Mania.Replays
|
||||
{
|
||||
switch (point)
|
||||
{
|
||||
case HitPoint _:
|
||||
case HitPoint:
|
||||
actions.Add(columnActions[point.Column]);
|
||||
break;
|
||||
|
||||
case ReleasePoint _:
|
||||
case ReleasePoint:
|
||||
actions.Remove(columnActions[point.Column]);
|
||||
break;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
skin.Setup(s => s.GetTexture(It.IsAny<string>())).CallBase();
|
||||
|
||||
skin.Setup(s => s.GetTexture(It.IsIn(textureFilenames), It.IsAny<WrapMode>(), It.IsAny<WrapMode>()))
|
||||
.Returns((string componentName, WrapMode _, WrapMode __) => new Texture(1, 1) { AssetName = componentName });
|
||||
.Returns((string componentName, WrapMode _, WrapMode _) => new Texture(1, 1) { AssetName = componentName });
|
||||
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
lastResult = null;
|
||||
|
||||
spinner = nextSpinner;
|
||||
spinner.OnNewResult += (o, result) => lastResult = result;
|
||||
spinner.OnNewResult += (_, result) => lastResult = result;
|
||||
}
|
||||
|
||||
return lastResult?.Type == HitResult.Great;
|
||||
@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
return false;
|
||||
|
||||
spinner = nextSpinner;
|
||||
spinner.OnNewResult += (o, result) => results.Add(result);
|
||||
spinner.OnNewResult += (_, result) => results.Add(result);
|
||||
|
||||
results.Clear();
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
=> addCheckPositionChangeSteps(timeAtRepeat(startTime, repeatIndex), positionAtRepeat(repeatIndex), positionRemainsSame);
|
||||
|
||||
private Func<double> timeAtRepeat(Func<double> startTime, int repeatIndex) => () => startTime() + 100 + duration_of_span * repeatIndex;
|
||||
private Func<Vector2> positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? (Func<Vector2>)getSliderStart : getSliderEnd;
|
||||
private Func<Vector2> positionAtRepeat(int repeatIndex) => repeatIndex % 2 == 0 ? getSliderStart : getSliderEnd;
|
||||
|
||||
private List<Vector2> getSliderCurve() => ((PlaySliderBody)drawableSlider.Body.Drawable).CurrentCurve;
|
||||
private Vector2 getSliderStart() => getSliderCurve().First();
|
||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
});
|
||||
|
||||
selectedHitObjects = EditorBeatmap.SelectedHitObjects.GetBoundCopy();
|
||||
selectedHitObjects.CollectionChanged += (_, __) => updateDistanceSnapGrid();
|
||||
selectedHitObjects.CollectionChanged += (_, _) => updateDistanceSnapGrid();
|
||||
|
||||
placementObject = EditorBeatmap.PlacementObject.GetBoundCopy();
|
||||
placementObject.ValueChanged += _ => updateDistanceSnapGrid();
|
||||
@ -204,7 +204,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
|
||||
switch (BlueprintContainer.CurrentTool)
|
||||
{
|
||||
case SelectTool _:
|
||||
case SelectTool:
|
||||
if (!EditorBeatmap.SelectedHitObjects.Any())
|
||||
return;
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public void ApplyToDrawableHitObject(DrawableHitObject drawable)
|
||||
{
|
||||
drawable.ApplyCustomUpdateState += (drawableObject, state) =>
|
||||
drawable.ApplyCustomUpdateState += (drawableObject, _) =>
|
||||
{
|
||||
if (!(drawableObject is DrawableHitCircle drawableHitCircle)) return;
|
||||
|
||||
|
@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
switch (drawableObject)
|
||||
{
|
||||
case DrawableSliderTail _:
|
||||
case DrawableSliderTail:
|
||||
using (drawableObject.BeginAbsoluteSequence(fadeStartTime))
|
||||
drawableObject.FadeOut(fadeDuration);
|
||||
|
||||
@ -165,14 +165,14 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
switch (hitObject)
|
||||
{
|
||||
case Slider _:
|
||||
case Slider:
|
||||
return (fadeOutStartTime, longFadeDuration);
|
||||
|
||||
case SliderTick _:
|
||||
case SliderTick:
|
||||
double tickFadeOutDuration = Math.Min(hitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000);
|
||||
return (hitObject.StartTime - tickFadeOutDuration, tickFadeOutDuration);
|
||||
|
||||
case Spinner _:
|
||||
case Spinner:
|
||||
return (fadeOutStartTime + longFadeDuration, fadeOutDuration);
|
||||
|
||||
default:
|
||||
|
@ -44,13 +44,13 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
// apply grow effect
|
||||
switch (drawable)
|
||||
{
|
||||
case DrawableSliderHead _:
|
||||
case DrawableSliderTail _:
|
||||
case DrawableSliderHead:
|
||||
case DrawableSliderTail:
|
||||
// special cases we should *not* be scaling.
|
||||
break;
|
||||
|
||||
case DrawableSlider _:
|
||||
case DrawableHitCircle _:
|
||||
case DrawableSlider:
|
||||
case DrawableHitCircle:
|
||||
{
|
||||
using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
|
||||
drawable.ScaleTo(StartScale.Value).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine);
|
||||
|
@ -374,7 +374,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
int i = 0;
|
||||
double currentTime = timingPoint.Time;
|
||||
|
||||
while (!definitelyBigger(currentTime, mapEndTime) && controlPointInfo.TimingPointAt(currentTime) == timingPoint)
|
||||
while (!definitelyBigger(currentTime, mapEndTime) && ReferenceEquals(controlPointInfo.TimingPointAt(currentTime), timingPoint))
|
||||
{
|
||||
beats.Add(Math.Floor(currentTime));
|
||||
i++;
|
||||
|
@ -34,10 +34,10 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
switch (drawable)
|
||||
{
|
||||
case DrawableSliderHead _:
|
||||
case DrawableSliderTail _:
|
||||
case DrawableSliderTick _:
|
||||
case DrawableSliderRepeat _:
|
||||
case DrawableSliderHead:
|
||||
case DrawableSliderTail:
|
||||
case DrawableSliderTick:
|
||||
case DrawableSliderRepeat:
|
||||
return;
|
||||
|
||||
default:
|
||||
|
@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
public Slider()
|
||||
{
|
||||
SamplesBindable.CollectionChanged += (_, __) => UpdateNestedSamples();
|
||||
SamplesBindable.CollectionChanged += (_, _) => UpdateNestedSamples();
|
||||
Path.Version.ValueChanged += _ => updateNestedPositions();
|
||||
}
|
||||
|
||||
|
@ -120,19 +120,19 @@ namespace osu.Game.Rulesets.Osu
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
case OsuModAutopilot _:
|
||||
case OsuModAutopilot:
|
||||
value |= LegacyMods.Autopilot;
|
||||
break;
|
||||
|
||||
case OsuModSpunOut _:
|
||||
case OsuModSpunOut:
|
||||
value |= LegacyMods.SpunOut;
|
||||
break;
|
||||
|
||||
case OsuModTarget _:
|
||||
case OsuModTarget:
|
||||
value |= LegacyMods.Target;
|
||||
break;
|
||||
|
||||
case OsuModTouchDevice _:
|
||||
case OsuModTouchDevice:
|
||||
value |= LegacyMods.TouchDevice;
|
||||
break;
|
||||
}
|
||||
|
@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
protected override string RulesetPrefix => OsuRuleset.SHORT_NAME;
|
||||
|
||||
protected override string ComponentName => Component.ToString().ToLower();
|
||||
protected override string ComponentName => Component.ToString().ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
hitWindows = slider.TailCircle.HitWindows;
|
||||
break;
|
||||
|
||||
case Spinner _:
|
||||
case Spinner:
|
||||
hitWindows = defaultHitWindows;
|
||||
break;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case HitCircle _:
|
||||
case HitCircle:
|
||||
return new OsuHitCircleJudgementResult(hitObject, judgement);
|
||||
|
||||
default:
|
||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
|
||||
break;
|
||||
|
||||
case DrawableSpinnerBonusTick _:
|
||||
case DrawableSpinnerBonusTick:
|
||||
if (state == ArmedState.Hit)
|
||||
glow.FlashColour(Color4.White, 200);
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
switch (obj)
|
||||
{
|
||||
case DrawableSpinner _:
|
||||
case DrawableSpinner:
|
||||
continue;
|
||||
|
||||
case DrawableSlider slider:
|
||||
|
@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
// note: `Slider`'s `ProxiedLayer` is added when its nested `DrawableHitCircle` is loaded.
|
||||
switch (drawable)
|
||||
{
|
||||
case DrawableSpinner _:
|
||||
case DrawableSpinner:
|
||||
spinnerProxies.Add(drawable.CreateProxy());
|
||||
break;
|
||||
|
||||
|
@ -88,11 +88,11 @@ namespace osu.Game.Rulesets.Osu.Utils
|
||||
|
||||
switch (hitObject)
|
||||
{
|
||||
case HitCircle _:
|
||||
case HitCircle:
|
||||
shift = clampHitCircleToPlayfield(current);
|
||||
break;
|
||||
|
||||
case Slider _:
|
||||
case Slider:
|
||||
shift = clampSliderToPlayfield(current);
|
||||
break;
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
||||
createDrawableRuleset();
|
||||
|
||||
assertStateAfterResult(new JudgementResult(new Swell(), new TaikoSwellJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Clear);
|
||||
AddUntilStep($"state reverts to {expectedStateAfterClear.ToString().ToLower()}", () => allMascotsIn(expectedStateAfterClear));
|
||||
AddUntilStep($"state reverts to {expectedStateAfterClear.ToString().ToLowerInvariant()}", () => allMascotsIn(expectedStateAfterClear));
|
||||
}
|
||||
|
||||
private void setBeatmap(bool kiai = false)
|
||||
@ -195,7 +195,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
||||
{
|
||||
TaikoMascotAnimationState[] mascotStates = null;
|
||||
|
||||
AddStep($"{judgementResult.Type.ToString().ToLower()} result for {judgementResult.Judgement.GetType().Name.Humanize(LetterCasing.LowerCase)}",
|
||||
AddStep($"{judgementResult.Type.ToString().ToLowerInvariant()} result for {judgementResult.Judgement.GetType().Name.Humanize(LetterCasing.LowerCase)}",
|
||||
() =>
|
||||
{
|
||||
applyNewResult(judgementResult);
|
||||
@ -204,7 +204,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
||||
Schedule(() => mascotStates = animatedMascots.Select(mascot => mascot.State.Value).ToArray());
|
||||
});
|
||||
|
||||
AddAssert($"state is {expectedState.ToString().ToLower()}", () => mascotStates.All(state => state == expectedState));
|
||||
AddAssert($"state is {expectedState.ToString().ToLowerInvariant()}", () => mascotStates.All(state => state == expectedState));
|
||||
}
|
||||
|
||||
private void applyNewResult(JudgementResult judgementResult)
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
AddStep("Setup judgements", () =>
|
||||
{
|
||||
judged = false;
|
||||
Player.ScoreProcessor.NewJudgement += b => judged = true;
|
||||
Player.ScoreProcessor.NewJudgement += _ => judged = true;
|
||||
});
|
||||
AddUntilStep("swell judged", () => judged);
|
||||
AddAssert("failed", () => Player.GameplayState.HasFailed);
|
||||
|
@ -48,8 +48,8 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case DrawableDrumRollTick _:
|
||||
case DrawableHit _:
|
||||
case DrawableDrumRollTick:
|
||||
case DrawableHit:
|
||||
double preempt = drawableRuleset.TimeRange.Value / drawableRuleset.ControlPointAt(hitObject.HitObject.StartTime).Multiplier;
|
||||
double start = hitObject.HitObject.StartTime - preempt * fade_out_start_time;
|
||||
double duration = preempt * fade_out_duration;
|
||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
DisplayColour.Value = Type == HitType.Centre ? COLOUR_CENTRE : COLOUR_RIM;
|
||||
});
|
||||
|
||||
SamplesBindable.BindCollectionChanged((_, __) => updateTypeFromSamples());
|
||||
SamplesBindable.BindCollectionChanged((_, _) => updateTypeFromSamples());
|
||||
}
|
||||
|
||||
private void updateTypeFromSamples()
|
||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
protected TaikoStrongableHitObject()
|
||||
{
|
||||
IsStrongBindable.BindValueChanged(_ => updateSamplesFromType());
|
||||
SamplesBindable.BindCollectionChanged((_, __) => updateTypeFromSamples());
|
||||
SamplesBindable.BindCollectionChanged((_, _) => updateTypeFromSamples());
|
||||
}
|
||||
|
||||
private void updateTypeFromSamples()
|
||||
|
@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
protected override string RulesetPrefix => TaikoRuleset.SHORT_NAME;
|
||||
|
||||
protected override string ComponentName => Component.ToString().ToLower();
|
||||
protected override string ComponentName => Component.ToString().ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
|
@ -139,10 +139,10 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
private static Texture getAnimationFrame(ISkin skin, TaikoMascotAnimationState state, int frameIndex)
|
||||
{
|
||||
var texture = skin.GetTexture($"pippidon{state.ToString().ToLower()}{frameIndex}");
|
||||
var texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}{frameIndex}");
|
||||
|
||||
if (frameIndex == 0 && texture == null)
|
||||
texture = skin.GetTexture($"pippidon{state.ToString().ToLower()}");
|
||||
texture = skin.GetTexture($"pippidon{state.ToString().ToLowerInvariant()}");
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
barLinePlayfield.Add(barLine);
|
||||
break;
|
||||
|
||||
case DrawableTaikoHitObject _:
|
||||
case DrawableTaikoHitObject:
|
||||
base.Add(h);
|
||||
break;
|
||||
|
||||
@ -261,7 +261,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
case DrawableBarLine barLine:
|
||||
return barLinePlayfield.Remove(barLine);
|
||||
|
||||
case DrawableTaikoHitObject _:
|
||||
case DrawableTaikoHitObject:
|
||||
return base.Remove(h);
|
||||
|
||||
default:
|
||||
@ -280,12 +280,12 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
switch (result.Judgement)
|
||||
{
|
||||
case TaikoStrongJudgement _:
|
||||
case TaikoStrongJudgement:
|
||||
if (result.IsHit)
|
||||
hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).ParentHitObject)?.VisualiseSecondHit(result);
|
||||
break;
|
||||
|
||||
case TaikoDrumRollTickJudgement _:
|
||||
case TaikoDrumRollTickJudgement:
|
||||
if (!result.IsHit)
|
||||
break;
|
||||
|
||||
|
@ -157,7 +157,7 @@ namespace osu.Game.Tests.Beatmaps
|
||||
[TestCase(8.3, DifficultyRating.ExpertPlus)]
|
||||
public void TestDifficultyRatingMapping(double starRating, DifficultyRating expectedBracket)
|
||||
{
|
||||
var actualBracket = BeatmapDifficultyCache.GetDifficultyRating(starRating);
|
||||
var actualBracket = StarDifficulty.GetDifficultyRating(starRating);
|
||||
|
||||
Assert.AreEqual(expectedBracket, actualBracket);
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Tests.Collections.IO
|
||||
public async Task TestImportMalformedDatabase()
|
||||
{
|
||||
bool exceptionThrown = false;
|
||||
UnhandledExceptionEventHandler setException = (_, __) => exceptionThrown = true;
|
||||
UnhandledExceptionEventHandler setException = (_, _) => exceptionThrown = true;
|
||||
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost())
|
||||
{
|
||||
|
@ -15,7 +15,6 @@ using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Models;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets;
|
||||
@ -39,10 +38,7 @@ namespace osu.Game.Tests.Database
|
||||
using (var importer = new BeatmapImporter(storage, realm))
|
||||
using (new RealmRulesetStore(realm, storage))
|
||||
{
|
||||
Live<BeatmapSetInfo>? beatmapSet;
|
||||
|
||||
using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream()))
|
||||
beatmapSet = await importer.Import(reader);
|
||||
var beatmapSet = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz"));
|
||||
|
||||
Assert.NotNull(beatmapSet);
|
||||
Debug.Assert(beatmapSet != null);
|
||||
@ -83,10 +79,7 @@ namespace osu.Game.Tests.Database
|
||||
using (var importer = new BeatmapImporter(storage, realm))
|
||||
using (new RealmRulesetStore(realm, storage))
|
||||
{
|
||||
Live<BeatmapSetInfo>? beatmapSet;
|
||||
|
||||
using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream()))
|
||||
beatmapSet = await importer.Import(reader);
|
||||
var beatmapSet = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz"));
|
||||
|
||||
Assert.NotNull(beatmapSet);
|
||||
Debug.Assert(beatmapSet != null);
|
||||
@ -146,11 +139,8 @@ namespace osu.Game.Tests.Database
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Live<BeatmapSetInfo>? beatmapSet;
|
||||
|
||||
using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream()))
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
beatmapSet = await importer.Import(reader);
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
var beatmapSet = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz"));
|
||||
|
||||
Assert.NotNull(beatmapSet);
|
||||
Debug.Assert(beatmapSet != null);
|
||||
@ -173,13 +163,8 @@ namespace osu.Game.Tests.Database
|
||||
using (var importer = new BeatmapImporter(storage, realm))
|
||||
using (new RealmRulesetStore(realm, storage))
|
||||
{
|
||||
Live<BeatmapSetInfo>? imported;
|
||||
|
||||
using (var reader = new ZipArchiveReader(TestResources.GetTestBeatmapStream()))
|
||||
{
|
||||
imported = await importer.Import(reader);
|
||||
EnsureLoaded(realm.Realm);
|
||||
}
|
||||
var imported = await importer.Import(new ImportTask(TestResources.GetTestBeatmapStream(), "renatus.osz"));
|
||||
EnsureLoaded(realm.Realm);
|
||||
|
||||
Assert.AreEqual(1, realm.Realm.All<BeatmapSetInfo>().Count());
|
||||
|
||||
@ -291,6 +276,42 @@ namespace osu.Game.Tests.Database
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportDirectoryWithEmptyOsuFiles()
|
||||
{
|
||||
RunTestWithRealmAsync(async (realm, storage) =>
|
||||
{
|
||||
using var importer = new BeatmapImporter(storage, realm);
|
||||
using var store = new RealmRulesetStore(realm, storage);
|
||||
|
||||
string? temp = TestResources.GetTestBeatmapForImport();
|
||||
|
||||
string extractedFolder = $"{temp}_extracted";
|
||||
Directory.CreateDirectory(extractedFolder);
|
||||
|
||||
try
|
||||
{
|
||||
using (var zip = ZipArchive.Open(temp))
|
||||
zip.WriteToDirectory(extractedFolder);
|
||||
|
||||
foreach (var file in new DirectoryInfo(extractedFolder).GetFiles("*.osu"))
|
||||
{
|
||||
using (file.Open(FileMode.Create))
|
||||
{
|
||||
// empty file.
|
||||
}
|
||||
}
|
||||
|
||||
var imported = await importer.Import(new ImportTask(extractedFolder));
|
||||
Assert.IsNull(imported);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(extractedFolder, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportThenImportWithReZip()
|
||||
{
|
||||
@ -760,7 +781,7 @@ namespace osu.Game.Tests.Database
|
||||
}
|
||||
};
|
||||
|
||||
var imported = importer.Import(toImport);
|
||||
var imported = importer.ImportModel(toImport);
|
||||
|
||||
realm.Run(r => r.Refresh());
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace osu.Game.Tests.Database
|
||||
|
||||
realm.RegisterCustomSubscription(r =>
|
||||
{
|
||||
var subscription = r.All<BeatmapInfo>().QueryAsyncWithNotifications((sender, changes, error) =>
|
||||
var subscription = r.All<BeatmapInfo>().QueryAsyncWithNotifications((_, _, _) =>
|
||||
{
|
||||
realm.Run(_ =>
|
||||
{
|
||||
@ -79,11 +79,11 @@ namespace osu.Game.Tests.Database
|
||||
{
|
||||
hasThreadedUsage.Set();
|
||||
|
||||
stopThreadedUsage.Wait();
|
||||
stopThreadedUsage.Wait(60000);
|
||||
});
|
||||
}, TaskCreationOptions.LongRunning | TaskCreationOptions.HideScheduler);
|
||||
|
||||
hasThreadedUsage.Wait();
|
||||
hasThreadedUsage.Wait(60000);
|
||||
|
||||
Assert.Throws<TimeoutException>(() =>
|
||||
{
|
||||
|
@ -189,7 +189,7 @@ namespace osu.Game.Tests.Database
|
||||
});
|
||||
|
||||
// Can't be used, even from within a valid context.
|
||||
realm.Run(threadContext =>
|
||||
realm.Run(_ =>
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
|
@ -192,7 +192,7 @@ namespace osu.Game.Tests.Gameplay
|
||||
AddStep("apply perfect hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = HitResult.Perfect }));
|
||||
AddAssert("not failed", () => !processor.HasFailed);
|
||||
|
||||
AddStep($"apply {resultApplied.ToString().ToLower()} hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = resultApplied }));
|
||||
AddStep($"apply {resultApplied.ToString().ToLowerInvariant()} hit result", () => processor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new Judgement()) { Type = resultApplied }));
|
||||
AddAssert("failed", () => processor.HasFailed);
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ namespace osu.Game.Tests.NonVisual
|
||||
Assert.That(File.Exists(Path.Combine(customPath, OsuGameBase.CLIENT_DATABASE_FILENAME)));
|
||||
|
||||
Directory.CreateDirectory(customPath2);
|
||||
File.Copy(Path.Combine(customPath, OsuGameBase.CLIENT_DATABASE_FILENAME), Path.Combine(customPath2, OsuGameBase.CLIENT_DATABASE_FILENAME));
|
||||
File.WriteAllText(Path.Combine(customPath2, OsuGameBase.CLIENT_DATABASE_FILENAME), "I am a text");
|
||||
|
||||
// Fails because file already exists.
|
||||
Assert.Throws<ArgumentException>(() => osu.Migrate(customPath2));
|
||||
|
@ -364,12 +364,12 @@ namespace osu.Game.Tests.NonVisual
|
||||
|
||||
private void confirmCurrentFrame(int? frame)
|
||||
{
|
||||
Assert.AreEqual(frame is int x ? replay.Frames[x].Time : (double?)null, handler.CurrentFrame?.Time, "Unexpected current frame");
|
||||
Assert.AreEqual(frame is int x ? replay.Frames[x].Time : null, handler.CurrentFrame?.Time, "Unexpected current frame");
|
||||
}
|
||||
|
||||
private void confirmNextFrame(int? frame)
|
||||
{
|
||||
Assert.AreEqual(frame is int x ? replay.Frames[x].Time : (double?)null, handler.NextFrame?.Time, "Unexpected next frame");
|
||||
Assert.AreEqual(frame is int x ? replay.Frames[x].Time : null, handler.NextFrame?.Time, "Unexpected next frame");
|
||||
}
|
||||
|
||||
private class TestReplayFrame : ReplayFrame
|
||||
|
@ -157,7 +157,7 @@ namespace osu.Game.Tests.NonVisual.Skinning
|
||||
{
|
||||
// use an incrementing width to allow assertion matching on correct textures as they turn from uploads into actual textures.
|
||||
int width = 1;
|
||||
Textures = fileNames.ToDictionary(fileName => fileName, fileName => new TextureUpload(new Image<Rgba32>(width, width++)));
|
||||
Textures = fileNames.ToDictionary(fileName => fileName, _ => new TextureUpload(new Image<Rgba32>(width, width++)));
|
||||
}
|
||||
|
||||
public TextureUpload Get(string name) => Textures.GetValueOrDefault(name);
|
||||
|
@ -227,10 +227,10 @@ namespace osu.Game.Tests.Online
|
||||
this.testBeatmapManager = testBeatmapManager;
|
||||
}
|
||||
|
||||
public override Live<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default)
|
||||
public override Live<BeatmapSetInfo> ImportModel(BeatmapSetInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
testBeatmapManager.AllowImport.Task.WaitSafely();
|
||||
return (testBeatmapManager.CurrentImport = base.Import(item, archive, batchImport, cancellationToken));
|
||||
return (testBeatmapManager.CurrentImport = base.ImportModel(item, archive, batchImport, cancellationToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Skinning;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
@ -28,7 +27,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSingleImportDifferentFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
|
||||
// When the import filename doesn't match, it should be appended (and update the skin.ini).
|
||||
assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu);
|
||||
@ -37,7 +36,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSingleImportWeirdIniFileCase() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner", iniFilename: "Skin.InI"), "skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner", iniFilename: "Skin.InI"), "skin.osk"));
|
||||
|
||||
// When the import filename doesn't match, it should be appended (and update the skin.ini).
|
||||
assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu);
|
||||
@ -46,7 +45,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSingleImportMissingSectionHeader() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner", includeSectionHeader: false), "skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner", includeSectionHeader: false), "skin.osk"));
|
||||
|
||||
// When the import filename doesn't match, it should be appended (and update the skin.ini).
|
||||
assertCorrectMetadata(import1, "test skin [skin]", "skinner", osu);
|
||||
@ -55,7 +54,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSingleImportMatchingFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "test skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "test skin.osk"));
|
||||
|
||||
// When the import filename matches it shouldn't be appended.
|
||||
assertCorrectMetadata(import1, "test skin", "skinner", osu);
|
||||
@ -64,7 +63,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSingleImportNoIniFile() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithNonIniFile(), "test skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithNonIniFile(), "test skin.osk"));
|
||||
|
||||
// When the import filename matches it shouldn't be appended.
|
||||
assertCorrectMetadata(import1, "test skin", "Unknown", osu);
|
||||
@ -73,7 +72,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestEmptyImportImportsWithFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createEmptyOsk(), "test skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createEmptyOsk(), "test skin.osk"));
|
||||
|
||||
// When the import filename matches it shouldn't be appended.
|
||||
assertCorrectMetadata(import1, "test skin", "Unknown", osu);
|
||||
@ -86,8 +85,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestImportTwiceWithSameMetadataAndFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
|
||||
assertImportedOnce(import1, import2);
|
||||
});
|
||||
@ -96,8 +95,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
public Task TestImportTwiceWithNoMetadataSameDownloadFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
// if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety.
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download.osk"));
|
||||
|
||||
assertImportedOnce(import1, import2);
|
||||
});
|
||||
@ -105,10 +104,10 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestImportUpperCasedOskArchive() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.OsK"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "name 1.OsK"));
|
||||
assertCorrectMetadata(import1, "name 1", "author 1", osu);
|
||||
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "name 1.oSK"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "name 1.oSK"));
|
||||
|
||||
assertImportedOnce(import1, import2);
|
||||
});
|
||||
@ -118,7 +117,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
{
|
||||
MemoryStream exportStream = new MemoryStream();
|
||||
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "custom.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "custom.osk"));
|
||||
assertCorrectMetadata(import1, "name 1 [custom]", "author 1", osu);
|
||||
|
||||
import1.PerformRead(s =>
|
||||
@ -128,7 +127,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
|
||||
string exportFilename = import1.GetDisplayString();
|
||||
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(exportStream, $"{exportFilename}.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(exportStream, $"{exportFilename}.osk"));
|
||||
assertCorrectMetadata(import2, "name 1 [custom]", "author 1", osu);
|
||||
|
||||
assertImportedOnce(import1, import2);
|
||||
@ -137,8 +136,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSameMetadataNameSameFolderName() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
|
||||
|
||||
assertImportedOnce(import1, import2);
|
||||
assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu);
|
||||
@ -151,8 +150,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestImportTwiceWithSameMetadataButDifferentFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin", "skinner"), "skin2.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin", "skinner"), "skin2.osk"));
|
||||
|
||||
assertImportedBoth(import1, import2);
|
||||
});
|
||||
@ -161,8 +160,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
public Task TestImportTwiceWithNoMetadataDifferentDownloadFilename() => runSkinTest(async osu =>
|
||||
{
|
||||
// if a user downloads two skins that do have skin.ini files but don't have any creator metadata in the skin.ini, they should both import separately just for safety.
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni(string.Empty, string.Empty), "download2.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni(string.Empty, string.Empty), "download2.osk"));
|
||||
|
||||
assertImportedBoth(import1, import2);
|
||||
});
|
||||
@ -170,8 +169,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestImportTwiceWithSameFilenameDifferentMetadata() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2", "skinner"), "skin.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("test skin v2.1", "skinner"), "skin.osk"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin v2", "skinner"), "skin.osk"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("test skin v2.1", "skinner"), "skin.osk"));
|
||||
|
||||
assertImportedBoth(import1, import2);
|
||||
assertCorrectMetadata(import1, "test skin v2 [skin]", "skinner", osu);
|
||||
@ -181,8 +180,8 @@ namespace osu.Game.Tests.Skins.IO
|
||||
[Test]
|
||||
public Task TestSameMetadataNameDifferentFolderName() => runSkinTest(async osu =>
|
||||
{
|
||||
var import1 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ZipArchiveReader(createOskWithIni("name 1", "author 1"), "my custom skin 2"));
|
||||
var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 1"));
|
||||
var import2 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "my custom skin 2"));
|
||||
|
||||
assertImportedBoth(import1, import2);
|
||||
assertCorrectMetadata(import1, "name 1 [my custom skin 1]", "author 1", osu);
|
||||
@ -358,10 +357,10 @@ namespace osu.Game.Tests.Skins.IO
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Live<SkinInfo>> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null)
|
||||
private async Task<Live<SkinInfo>> loadSkinIntoOsu(OsuGameBase osu, ImportTask import)
|
||||
{
|
||||
var skinManager = osu.Dependencies.Get<SkinManager>();
|
||||
return await skinManager.Import(archive);
|
||||
return await skinManager.Import(import);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Tests.Skins
|
||||
{
|
||||
AddStep($"Set beatmap skin enabled to {allowBeatmapLookups}", () => config.SetValue(OsuSetting.BeatmapSkins, allowBeatmapLookups));
|
||||
|
||||
ISkin expected() => allowBeatmapLookups ? (ISkin)beatmapSource : userSource;
|
||||
ISkin expected() => allowBeatmapLookups ? beatmapSource : userSource;
|
||||
|
||||
AddAssert("Check lookup is from correct source", () => requester.FindProvider(s => s.GetDrawableComponent(new TestSkinComponent()) != null) == expected());
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ using osu.Framework.Extensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
@ -27,7 +27,7 @@ namespace osu.Game.Tests.Skins
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).GetResultSafely();
|
||||
var imported = beatmaps.Import(new ImportTask(TestResources.OpenResource("Archives/ogg-beatmap.osz"), "ogg-beatmap.osz")).GetResultSafely();
|
||||
|
||||
imported?.PerformRead(s =>
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual;
|
||||
@ -26,7 +26,7 @@ namespace osu.Game.Tests.Skins
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var imported = skins.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-skin.osk"))).GetResultSafely();
|
||||
var imported = skins.Import(new ImportTask(TestResources.OpenResource("Archives/ogg-skin.osk"), "ogg-skin.osk")).GetResultSafely();
|
||||
skin = imported.PerformRead(skinInfo => skins.GetSkin(skinInfo));
|
||||
}
|
||||
|
||||
|
57
osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs
Normal file
57
osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||
using osu.Game.Screens.Edit.GameplayTest;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
public class TestSceneEditorNavigation : OsuGameTestScene
|
||||
{
|
||||
[Test]
|
||||
public void TestEditorGameplayTestAlwaysUsesOriginalRuleset()
|
||||
{
|
||||
BeatmapSetInfo beatmapSet = null!;
|
||||
|
||||
AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely());
|
||||
AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach());
|
||||
|
||||
AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet));
|
||||
AddUntilStep("wait for song select",
|
||||
() => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet)
|
||||
&& Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect
|
||||
&& songSelect.IsLoaded);
|
||||
AddStep("switch ruleset", () => Game.Ruleset.Value = new ManiaRuleset().RulesetInfo);
|
||||
|
||||
AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0)));
|
||||
AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.IsLoaded);
|
||||
AddStep("test gameplay", () =>
|
||||
{
|
||||
var testGameplayButton = this.ChildrenOfType<TestGameplayButton>().Single();
|
||||
InputManager.MoveMouseTo(testGameplayButton);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for player", () => Game.ScreenStack.CurrentScreen is EditorPlayer editorPlayer && editorPlayer.IsLoaded);
|
||||
AddAssert("current ruleset is osu!", () => Game.Ruleset.Value.Equals(new OsuRuleset().RulesetInfo));
|
||||
|
||||
AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(PlaySongSelect).Yield()));
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
|
||||
AddAssert("previous ruleset restored", () => Game.Ruleset.Value.Equals(new ManiaRuleset().RulesetInfo));
|
||||
}
|
||||
}
|
||||
}
|
@ -117,8 +117,8 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
// After placement these must be non-default as defaults are read-only.
|
||||
AddAssert("Placed object has non-default control points", () =>
|
||||
EditorBeatmap.HitObjects[0].SampleControlPoint != SampleControlPoint.DEFAULT &&
|
||||
EditorBeatmap.HitObjects[0].DifficultyControlPoint != DifficultyControlPoint.DEFAULT);
|
||||
!ReferenceEquals(EditorBeatmap.HitObjects[0].SampleControlPoint, SampleControlPoint.DEFAULT) &&
|
||||
!ReferenceEquals(EditorBeatmap.HitObjects[0].DifficultyControlPoint, DifficultyControlPoint.DEFAULT));
|
||||
|
||||
ReloadEditorToSameBeatmap();
|
||||
|
||||
@ -126,8 +126,8 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
// After placement these must be non-default as defaults are read-only.
|
||||
AddAssert("Placed object still has non-default control points", () =>
|
||||
EditorBeatmap.HitObjects[0].SampleControlPoint != SampleControlPoint.DEFAULT &&
|
||||
EditorBeatmap.HitObjects[0].DifficultyControlPoint != DifficultyControlPoint.DEFAULT);
|
||||
!ReferenceEquals(EditorBeatmap.HitObjects[0].SampleControlPoint, SampleControlPoint.DEFAULT) &&
|
||||
!ReferenceEquals(EditorBeatmap.HitObjects[0].DifficultyControlPoint, DifficultyControlPoint.DEFAULT));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -322,8 +322,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
switch (h)
|
||||
{
|
||||
case TestPooledHitObject _:
|
||||
case TestPooledParentHitObject _:
|
||||
case TestPooledHitObject:
|
||||
case TestPooledParentHitObject:
|
||||
return null;
|
||||
|
||||
case TestParentHitObject p:
|
||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
HealthProcessor.FailConditions += (_, __) => true;
|
||||
HealthProcessor.FailConditions += (_, _) => true;
|
||||
}
|
||||
|
||||
private double lastFrequency = double.MaxValue;
|
||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
HealthProcessor.FailConditions += (_, __) => true;
|
||||
HealthProcessor.FailConditions += (_, _) => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Test]
|
||||
public void TestToggleEditor()
|
||||
{
|
||||
AddToggleStep("toggle editor visibility", visible => skinEditor.ToggleVisibility());
|
||||
AddToggleStep("toggle editor visibility", _ => skinEditor.ToggleVisibility());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
Child = new SkinProvidingContainer(secondarySource)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"))
|
||||
Child = consumer = new SkinConsumer("test", _ => new NamedBox("Default Implementation"))
|
||||
}
|
||||
};
|
||||
});
|
||||
@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"))));
|
||||
AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", _ => new NamedBox("Default Implementation"))));
|
||||
AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox);
|
||||
AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1);
|
||||
}
|
||||
@ -155,7 +155,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"))));
|
||||
AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", _ => new NamedBox("Default Implementation"))));
|
||||
AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox);
|
||||
AddStep("disable", () => target.Disable());
|
||||
AddAssert("consumer using base source", () => consumer.Drawable is BaseSourceBox);
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
base.SetUpSteps();
|
||||
AddStep("enable storyboard", () => LocalConfig.SetValue(OsuSetting.ShowStoryboard, true));
|
||||
AddStep("set dim level to 0", () => LocalConfig.SetValue<double>(OsuSetting.DimLevel, 0));
|
||||
AddStep("reset fail conditions", () => currentFailConditions = (_, __) => false);
|
||||
AddStep("reset fail conditions", () => currentFailConditions = (_, _) => false);
|
||||
AddStep("set storyboard duration to 2s", () => currentStoryboardDuration = 2000);
|
||||
AddStep("set ShowResults = true", () => showResults = true);
|
||||
}
|
||||
@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
CreateTest(() =>
|
||||
{
|
||||
AddStep("fail on first judgement", () => currentFailConditions = (_, __) => true);
|
||||
AddStep("fail on first judgement", () => currentFailConditions = (_, _) => true);
|
||||
|
||||
// Fail occurs at 164ms with the provided beatmap.
|
||||
// Fail animation runs for 2.5s realtime but the gameplay time change is *variable* due to the frequency transform being applied, so we need a bit of lenience.
|
||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
// To emulate `MultiplayerClient.CurrentMatchPlayingUserIds` we need a bindable list of *only IDs*.
|
||||
// This tracks the list of users 1:1.
|
||||
MultiplayerUsers.BindCollectionChanged((c, e) =>
|
||||
MultiplayerUsers.BindCollectionChanged((_, e) =>
|
||||
{
|
||||
switch (e.Action)
|
||||
{
|
||||
|
@ -42,11 +42,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
var mockLounge = new Mock<LoungeSubScreen>();
|
||||
mockLounge
|
||||
.Setup(l => l.Join(It.IsAny<Room>(), It.IsAny<string>(), It.IsAny<Action<Room>>(), It.IsAny<Action<string>>()))
|
||||
.Callback<Room, string, Action<Room>, Action<string>>((a, b, c, d) =>
|
||||
.Callback<Room, string, Action<Room>, Action<string>>((_, _, _, d) =>
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
allowResponseCallback.Wait();
|
||||
allowResponseCallback.Wait(10000);
|
||||
allowResponseCallback.Reset();
|
||||
Schedule(() => d?.Invoke("Incorrect password"));
|
||||
});
|
||||
|
@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
setRoomCountdown(countdownStart.Duration);
|
||||
break;
|
||||
|
||||
case StopCountdownRequest _:
|
||||
case StopCountdownRequest:
|
||||
multiplayerRoom.Countdown = null;
|
||||
raiseRoomUpdated();
|
||||
break;
|
||||
|
@ -0,0 +1,86 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
[TestFixture]
|
||||
[Ignore("This test cannot be run headless, as it requires the game host running the nested game to have IPC bound.")]
|
||||
public class TestSceneInterProcessCommunication : OsuGameTestScene
|
||||
{
|
||||
private HeadlessGameHost ipcSenderHost = null!;
|
||||
|
||||
private OsuSchemeLinkIPCChannel osuSchemeLinkIPCReceiver = null!;
|
||||
private OsuSchemeLinkIPCChannel osuSchemeLinkIPCSender = null!;
|
||||
|
||||
private const int requested_beatmap_set_id = 1;
|
||||
|
||||
[Resolved]
|
||||
private GameHost gameHost { get; set; } = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
AddStep("set up request handling", () =>
|
||||
{
|
||||
((DummyAPIAccess)API).HandleRequest = request =>
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case GetBeatmapSetRequest gbr:
|
||||
|
||||
var apiBeatmapSet = CreateAPIBeatmapSet();
|
||||
apiBeatmapSet.OnlineID = requested_beatmap_set_id;
|
||||
apiBeatmapSet.Beatmaps = apiBeatmapSet.Beatmaps.Append(new APIBeatmap
|
||||
{
|
||||
DifficultyName = "Target difficulty",
|
||||
OnlineID = 75,
|
||||
}).ToArray();
|
||||
gbr.TriggerSuccess(apiBeatmapSet);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
});
|
||||
AddStep("create IPC receiver channel", () => osuSchemeLinkIPCReceiver = new OsuSchemeLinkIPCChannel(gameHost, Game));
|
||||
AddStep("create IPC sender channel", () =>
|
||||
{
|
||||
ipcSenderHost = new HeadlessGameHost(gameHost.Name, new HostOptions { BindIPC = true });
|
||||
osuSchemeLinkIPCSender = new OsuSchemeLinkIPCChannel(ipcSenderHost);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOsuSchemeLinkIPCChannel()
|
||||
{
|
||||
AddStep("open beatmap via IPC", () => osuSchemeLinkIPCSender.HandleLinkAsync($@"osu://s/{requested_beatmap_set_id}").WaitSafely());
|
||||
AddUntilStep("beatmap overlay displayed", () => Game.ChildrenOfType<BeatmapSetOverlay>().FirstOrDefault()?.State.Value == Visibility.Visible);
|
||||
AddUntilStep("beatmap overlay showing content", () => Game.ChildrenOfType<BeatmapSetOverlay>().FirstOrDefault()?.Header.BeatmapSet.Value.OnlineID == requested_beatmap_set_id);
|
||||
}
|
||||
|
||||
public override void TearDownSteps()
|
||||
{
|
||||
AddStep("dispose IPC receiver", () => osuSchemeLinkIPCReceiver.Dispose());
|
||||
AddStep("dispose IPC sender", () =>
|
||||
{
|
||||
osuSchemeLinkIPCSender.Dispose();
|
||||
ipcSenderHost.Dispose();
|
||||
});
|
||||
base.TearDownSteps();
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,9 @@ using NUnit.Framework;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
@ -16,6 +18,7 @@ using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
using osu.Game.Skinning.Editor;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation;
|
||||
|
||||
@ -26,29 +29,6 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
private TestPlaySongSelect songSelect;
|
||||
private SkinEditor skinEditor => Game.ChildrenOfType<SkinEditor>().FirstOrDefault();
|
||||
|
||||
private void advanceToSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
}
|
||||
|
||||
private void openSkinEditor()
|
||||
{
|
||||
AddStep("open skin editor", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ControlLeft);
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.S);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
AddUntilStep("skin editor loaded", () => skinEditor != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEditComponentDuringGameplay()
|
||||
{
|
||||
@ -88,6 +68,68 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("value is less than default", () => hitErrorMeter.JudgementLineThickness.Value < hitErrorMeter.JudgementLineThickness.Default);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestComponentsDeselectedOnSkinEditorHide()
|
||||
{
|
||||
advanceToSongSelect();
|
||||
openSkinEditor();
|
||||
switchToGameplayScene();
|
||||
|
||||
AddUntilStep("wait for components", () => skinEditor.ChildrenOfType<SkinBlueprint>().Any());
|
||||
|
||||
AddStep("select all components", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ControlLeft);
|
||||
InputManager.Key(Key.A);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
});
|
||||
|
||||
AddUntilStep("components selected", () => skinEditor.SelectedComponents.Count > 0);
|
||||
|
||||
toggleSkinEditor();
|
||||
|
||||
AddUntilStep("no components selected", () => skinEditor.SelectedComponents.Count == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchScreenWhileDraggingComponent()
|
||||
{
|
||||
Vector2 firstBlueprintCentre = Vector2.Zero;
|
||||
ScheduledDelegate movementDelegate = null;
|
||||
|
||||
advanceToSongSelect();
|
||||
|
||||
openSkinEditor();
|
||||
|
||||
AddStep("add skinnable component", () =>
|
||||
{
|
||||
skinEditor.ChildrenOfType<SkinComponentToolbox.ToolboxComponentButton>().First().TriggerClick();
|
||||
});
|
||||
|
||||
AddUntilStep("newly added component selected", () => skinEditor.SelectedComponents.Count == 1);
|
||||
|
||||
AddStep("start drag", () =>
|
||||
{
|
||||
firstBlueprintCentre = skinEditor.ChildrenOfType<SkinBlueprint>().First().ScreenSpaceDrawQuad.Centre;
|
||||
|
||||
InputManager.MoveMouseTo(firstBlueprintCentre);
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("start movement", () => movementDelegate = Scheduler.AddDelayed(() => { InputManager.MoveMouseTo(firstBlueprintCentre += new Vector2(1)); }, 10, true));
|
||||
|
||||
toggleSkinEditor();
|
||||
AddStep("exit song select", () => songSelect.Exit());
|
||||
|
||||
AddUntilStep("wait for blueprints removed", () => !skinEditor.ChildrenOfType<SkinBlueprint>().Any());
|
||||
|
||||
AddStep("stop drag", () =>
|
||||
{
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
movementDelegate?.Cancel();
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAutoplayCompatibleModsRetainedOnEnteringGameplay()
|
||||
{
|
||||
@ -146,8 +188,35 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddUntilStep("mod overlay closed", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
private void advanceToSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
}
|
||||
|
||||
private void openSkinEditor()
|
||||
{
|
||||
toggleSkinEditor();
|
||||
AddUntilStep("skin editor loaded", () => skinEditor != null);
|
||||
}
|
||||
|
||||
private void toggleSkinEditor()
|
||||
{
|
||||
AddStep("toggle skin editor", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ControlLeft);
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.S);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
}
|
||||
|
||||
private void switchToGameplayScene()
|
||||
{
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
AddStep("Click gameplay scene button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(skinEditor.ChildrenOfType<SkinEditorSceneLibrary.SceneButton>().First(b => b.Text == "Gameplay"));
|
||||
|
@ -219,7 +219,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Metadata.BindValueChanged(metadata =>
|
||||
Metadata.BindValueChanged(_ =>
|
||||
{
|
||||
foreach (var b in this.ChildrenOfType<YearButton>())
|
||||
b.Action = () => YearChanged?.Invoke(b.Year);
|
||||
|
@ -187,8 +187,8 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
// pre-check for requests we should be handling (as they are scheduled below).
|
||||
switch (request)
|
||||
{
|
||||
case ShowPlaylistUserScoreRequest _:
|
||||
case IndexPlaylistScoresRequest _:
|
||||
case ShowPlaylistUserScoreRequest:
|
||||
case IndexPlaylistScoresRequest:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Settings
|
||||
public void ToggleVisibility()
|
||||
{
|
||||
AddWaitStep("wait some", 5);
|
||||
AddToggleStep("toggle visibility", visible => settings.ToggleVisibility());
|
||||
AddToggleStep("toggle visibility", _ => settings.ToggleVisibility());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -91,19 +91,19 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
switch (instance)
|
||||
{
|
||||
case OsuRuleset _:
|
||||
case OsuRuleset:
|
||||
testInfoLabels(5);
|
||||
break;
|
||||
|
||||
case TaikoRuleset _:
|
||||
case TaikoRuleset:
|
||||
testInfoLabels(5);
|
||||
break;
|
||||
|
||||
case CatchRuleset _:
|
||||
case CatchRuleset:
|
||||
testInfoLabels(5);
|
||||
break;
|
||||
|
||||
case ManiaRuleset _:
|
||||
case ManiaRuleset:
|
||||
testInfoLabels(4);
|
||||
break;
|
||||
|
||||
|
@ -872,10 +872,10 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
return set != null;
|
||||
});
|
||||
|
||||
FilterableGroupedDifficultyIcon groupIcon = null;
|
||||
GroupedDifficultyIcon groupIcon = null;
|
||||
AddUntilStep("Find group icon for different ruleset", () =>
|
||||
{
|
||||
return (groupIcon = set.ChildrenOfType<FilterableGroupedDifficultyIcon>()
|
||||
return (groupIcon = set.ChildrenOfType<GroupedDifficultyIcon>()
|
||||
.FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.OnlineID == 3)) != null;
|
||||
});
|
||||
|
||||
|
@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddStep("Set time before zero", () =>
|
||||
{
|
||||
beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) =>
|
||||
beatContainer.NewBeat = (i, timingControlPoint, _, _) =>
|
||||
{
|
||||
lastActuationTime = gameplayClockContainer.CurrentTime;
|
||||
lastTimingPoint = timingControlPoint;
|
||||
@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddStep("Set time before zero", () =>
|
||||
{
|
||||
beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) =>
|
||||
beatContainer.NewBeat = (i, timingControlPoint, _, _) =>
|
||||
{
|
||||
lastBeatIndex = i;
|
||||
lastBpm = timingControlPoint.BPM;
|
||||
@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddStep("bind event", () =>
|
||||
{
|
||||
beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) => lastBpm = timingControlPoint.BPM;
|
||||
beatContainer.NewBeat = (_, timingControlPoint, _, _) => lastBpm = timingControlPoint.BPM;
|
||||
});
|
||||
|
||||
AddUntilStep("wait for trigger", () => lastBpm != null);
|
||||
@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
actualEffectPoint = null;
|
||||
beatContainer.AllowMistimedEventFiring = false;
|
||||
|
||||
beatContainer.NewBeat = (i, timingControlPoint, effectControlPoint, channelAmplitudes) =>
|
||||
beatContainer.NewBeat = (_, _, effectControlPoint, _) =>
|
||||
{
|
||||
if (Precision.AlmostEquals(gameplayClockContainer.CurrentTime + earlyActivationMilliseconds, expectedEffectPoint.Time, BeatSyncedContainer.MISTIMED_ALLOWANCE))
|
||||
actualEffectPoint = effectControlPoint;
|
||||
@ -269,7 +269,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private TimingControlPoint getNextTimingPoint(TimingControlPoint current)
|
||||
{
|
||||
if (timingPoints[^1] == current)
|
||||
if (ReferenceEquals(timingPoints[^1], current))
|
||||
return current;
|
||||
|
||||
int index = timingPoints.IndexOf(current); // -1 means that this is a "default beat"
|
||||
@ -281,7 +281,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
if (timingPoints.Count == 0) return 0;
|
||||
|
||||
if (timingPoints[^1] == current)
|
||||
if (ReferenceEquals(timingPoints[^1], current))
|
||||
{
|
||||
Debug.Assert(BeatSyncSource.Clock != null);
|
||||
|
||||
|
@ -77,13 +77,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
};
|
||||
|
||||
control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
|
||||
control.General.BindCollectionChanged((u, v) => general.Text = $"General: {(control.General.Any() ? string.Join('.', control.General.Select(i => i.ToString().Underscore())) : "")}", true);
|
||||
control.General.BindCollectionChanged((_, _) => general.Text = $"General: {(control.General.Any() ? string.Join('.', control.General.Select(i => i.ToString().Underscore())) : "")}", true);
|
||||
control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
|
||||
control.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true);
|
||||
control.Genre.BindValueChanged(g => genre.Text = $"Genre: {g.NewValue}", true);
|
||||
control.Language.BindValueChanged(l => language.Text = $"Language: {l.NewValue}", true);
|
||||
control.Extra.BindCollectionChanged((u, v) => extra.Text = $"Extra: {(control.Extra.Any() ? string.Join('.', control.Extra.Select(i => i.ToString().ToLowerInvariant())) : "")}", true);
|
||||
control.Ranks.BindCollectionChanged((u, v) => ranks.Text = $"Ranks: {(control.Ranks.Any() ? string.Join('.', control.Ranks.Select(i => i.ToString())) : "")}", true);
|
||||
control.Extra.BindCollectionChanged((_, _) => extra.Text = $"Extra: {(control.Extra.Any() ? string.Join('.', control.Extra.Select(i => i.ToString().ToLowerInvariant())) : "")}", true);
|
||||
control.Ranks.BindCollectionChanged((_, _) => ranks.Text = $"Ranks: {(control.Ranks.Any() ? string.Join('.', control.Ranks.Select(i => i.ToString())) : "")}", true);
|
||||
control.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true);
|
||||
control.ExplicitContent.BindValueChanged(e => explicitMap.Text = $"Explicit Maps: {e.NewValue}", true);
|
||||
});
|
||||
|
@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
notificationOverlay.Reset();
|
||||
|
||||
performer.Setup(g => g.PerformFromScreen(It.IsAny<Action<IScreen>>(), It.IsAny<IEnumerable<Type>>()))
|
||||
.Callback((Action<IScreen> action, IEnumerable<Type> types) => action(null));
|
||||
.Callback((Action<IScreen> action, IEnumerable<Type> _) => action(null));
|
||||
|
||||
notificationOverlay.Setup(n => n.Post(It.IsAny<Notification>()))
|
||||
.Callback((Notification n) => lastNotification = n);
|
||||
|
@ -78,7 +78,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
Origin = Anchor.Centre,
|
||||
Width = 500,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = component = padded ? (LabelledDrawable<Drawable>)new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(),
|
||||
Child = component = padded ? new PaddedLabelledDrawable() : new NonPaddedLabelledDrawable(),
|
||||
};
|
||||
|
||||
component.Label = "a sample component";
|
||||
|
@ -9,9 +9,11 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Overlays.Mods.Input;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Utils;
|
||||
@ -25,6 +27,9 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
|
||||
|
||||
[Resolved]
|
||||
private OsuConfigManager configManager { get; set; } = null!;
|
||||
|
||||
[TestCase(ModType.DifficultyReduction)]
|
||||
[TestCase(ModType.DifficultyIncrease)]
|
||||
[TestCase(ModType.Conversion)]
|
||||
@ -132,14 +137,16 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestKeyboardSelection()
|
||||
public void TestSequentialKeyboardSelection()
|
||||
{
|
||||
AddStep("set sequential hotkey mode", () => configManager.SetValue(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Sequential));
|
||||
|
||||
ModColumn column = null!;
|
||||
AddStep("create content", () => Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(30),
|
||||
Child = column = new ModColumn(ModType.DifficultyReduction, true, new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P })
|
||||
Child = column = new ModColumn(ModType.DifficultyReduction, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -158,9 +165,12 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("set filter to NF", () => setFilter(mod => mod.Acronym == "NF"));
|
||||
|
||||
AddStep("press W", () => InputManager.Key(Key.W));
|
||||
AddAssert("NF panel not selected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NF").Active.Value);
|
||||
|
||||
AddStep("press Q", () => InputManager.Key(Key.Q));
|
||||
AddAssert("NF panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NF").Active.Value);
|
||||
|
||||
AddStep("press W again", () => InputManager.Key(Key.W));
|
||||
AddStep("press Q again", () => InputManager.Key(Key.Q));
|
||||
AddAssert("NF panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NF").Active.Value);
|
||||
|
||||
AddStep("filter out everything", () => setFilter(_ => false));
|
||||
@ -171,6 +181,113 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("clear filter", () => setFilter(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClassicKeyboardExclusiveSelection()
|
||||
{
|
||||
AddStep("set classic hotkey mode", () => configManager.SetValue(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Classic));
|
||||
|
||||
ModColumn column = null!;
|
||||
AddStep("create content", () => Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(30),
|
||||
Child = column = new ModColumn(ModType.DifficultyIncrease, false)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AvailableMods = getExampleModsFor(ModType.DifficultyIncrease)
|
||||
}
|
||||
});
|
||||
|
||||
AddUntilStep("wait for panel load", () => column.IsLoaded && column.ItemsLoaded);
|
||||
|
||||
AddStep("press A", () => InputManager.Key(Key.A));
|
||||
AddAssert("HR panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "HR").Active.Value);
|
||||
|
||||
AddStep("press A again", () => InputManager.Key(Key.A));
|
||||
AddAssert("HR panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "HR").Active.Value);
|
||||
|
||||
AddStep("press D", () => InputManager.Key(Key.D));
|
||||
AddAssert("DT panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
|
||||
AddStep("press D again", () => InputManager.Key(Key.D));
|
||||
AddAssert("DT panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
AddAssert("NC panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NC").Active.Value);
|
||||
|
||||
AddStep("press D again", () => InputManager.Key(Key.D));
|
||||
AddAssert("DT panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
AddAssert("NC panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NC").Active.Value);
|
||||
|
||||
AddStep("press Shift-D", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.D);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
AddAssert("DT panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
AddAssert("NC panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NC").Active.Value);
|
||||
|
||||
AddStep("press J", () => InputManager.Key(Key.J));
|
||||
AddAssert("no change", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Active.Value).Mod.Acronym == "NC");
|
||||
|
||||
AddStep("filter everything but NC", () => setFilter(mod => mod.Acronym == "NC"));
|
||||
|
||||
AddStep("press A", () => InputManager.Key(Key.A));
|
||||
AddAssert("no change", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Active.Value).Mod.Acronym == "NC");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClassicKeyboardIncompatibleSelection()
|
||||
{
|
||||
AddStep("set classic hotkey mode", () => configManager.SetValue(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Classic));
|
||||
|
||||
ModColumn column = null!;
|
||||
AddStep("create content", () => Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(30),
|
||||
Child = column = new ModColumn(ModType.DifficultyIncrease, true)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AvailableMods = getExampleModsFor(ModType.DifficultyIncrease)
|
||||
}
|
||||
});
|
||||
|
||||
AddUntilStep("wait for panel load", () => column.IsLoaded && column.ItemsLoaded);
|
||||
|
||||
AddStep("press A", () => InputManager.Key(Key.A));
|
||||
AddAssert("HR panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "HR").Active.Value);
|
||||
|
||||
AddStep("press A again", () => InputManager.Key(Key.A));
|
||||
AddAssert("HR panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "HR").Active.Value);
|
||||
|
||||
AddStep("press D", () => InputManager.Key(Key.D));
|
||||
AddAssert("DT panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
AddAssert("NC panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NC").Active.Value);
|
||||
|
||||
AddStep("press D again", () => InputManager.Key(Key.D));
|
||||
AddAssert("DT panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
AddAssert("NC panel deselected", () => !this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NC").Active.Value);
|
||||
|
||||
AddStep("press Shift-D", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.D);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
AddAssert("DT panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "DT").Active.Value);
|
||||
AddAssert("NC panel selected", () => this.ChildrenOfType<ModPanel>().Single(panel => panel.Mod.Acronym == "NC").Active.Value);
|
||||
|
||||
AddStep("press J", () => InputManager.Key(Key.J));
|
||||
AddAssert("no change", () => this.ChildrenOfType<ModPanel>().Count(panel => panel.Active.Value) == 2);
|
||||
|
||||
AddStep("filter everything but NC", () => setFilter(mod => mod.Acronym == "NC"));
|
||||
|
||||
AddStep("press A", () => InputManager.Key(Key.A));
|
||||
AddAssert("no change", () => this.ChildrenOfType<ModPanel>().Count(panel => panel.Active.Value) == 2);
|
||||
}
|
||||
|
||||
private void setFilter(Func<Mod, bool>? filter)
|
||||
{
|
||||
foreach (var modState in this.ChildrenOfType<ModColumn>().Single().AvailableMods)
|
||||
@ -181,8 +298,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public new bool SelectionAnimationRunning => base.SelectionAnimationRunning;
|
||||
|
||||
public TestModColumn(ModType modType, bool allowBulkSelection)
|
||||
: base(modType, allowBulkSelection)
|
||||
public TestModColumn(ModType modType, bool allowIncompatibleSelection)
|
||||
: base(modType, allowIncompatibleSelection)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType<ModPanel>().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => panel.Filtered.Value));
|
||||
AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType<ModPanel>().Where(panel => panel.Mod is OsuModNightcore).Any(panel => !panel.Filtered.Value));
|
||||
|
||||
AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = m => true);
|
||||
AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = _ => true);
|
||||
AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType<ModPanel>().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => !panel.Filtered.Value));
|
||||
AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType<ModPanel>().Where(b => b.Mod is OsuModNightcore).Any(panel => !panel.Filtered.Value));
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
@ -89,7 +88,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddToggleStep("toggle enabled", toggle =>
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
button.Action = toggle ? () => { } : (Action)null;
|
||||
button.Action = toggle ? () => { } : null;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -29,7 +28,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddToggleStep("toggle enabled", toggle =>
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
button.Action = toggle ? () => { } : (Action)null;
|
||||
button.Action = toggle ? () => { } : null;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
base.Current = new Bindable<string>(string.Empty);
|
||||
|
||||
((OsuTextBox)Control).OnCommit += (sender, newText) =>
|
||||
((OsuTextBox)Control).OnCommit += (sender, _) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ namespace osu.Game.Tournament.Components
|
||||
FillMode = FillMode.Fill
|
||||
};
|
||||
|
||||
(flag = team.FlagName.GetBoundCopy()).BindValueChanged(acronym => flagSprite.Texture = textures.Get($@"Flags/{team.FlagName}"), true);
|
||||
(flag = team.FlagName.GetBoundCopy()).BindValueChanged(_ => flagSprite.Texture = textures.Get($@"Flags/{team.FlagName}"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
if (team == null) return;
|
||||
|
||||
(acronym = team.Acronym.GetBoundCopy()).BindValueChanged(acronym => Text.Text = team?.FullName.Value ?? string.Empty, true);
|
||||
(acronym = team.Acronym.GetBoundCopy()).BindValueChanged(_ => Text.Text = team?.FullName.Value ?? string.Empty, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
if (Team == null) return;
|
||||
|
||||
(acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true);
|
||||
(acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(_ => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,14 +66,14 @@ namespace osu.Game.Tournament.Models
|
||||
{
|
||||
// use a sane default flag name based on acronym.
|
||||
if (val.OldValue.StartsWith(FlagName.Value, StringComparison.InvariantCultureIgnoreCase))
|
||||
FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpper() : string.Empty;
|
||||
FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpperInvariant() : string.Empty;
|
||||
};
|
||||
|
||||
FullName.ValueChanged += val =>
|
||||
{
|
||||
// use a sane acronym based on full name.
|
||||
if (val.OldValue.StartsWith(Acronym.Value, StringComparison.InvariantCultureIgnoreCase))
|
||||
Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpper() : string.Empty;
|
||||
Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpperInvariant() : string.Empty;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ namespace osu.Game.Tournament.Screens.Drawings
|
||||
}
|
||||
}
|
||||
|
||||
writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run(writeAction);
|
||||
writeOp = writeOp?.ContinueWith(_ => { writeAction(); }) ?? Task.Run(writeAction);
|
||||
}
|
||||
|
||||
private void reloadTeams()
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
|
||||
AddInternal(rightClickMessage = new WarningBox("Right click to place and link matches"));
|
||||
|
||||
LadderInfo.Matches.CollectionChanged += (_, __) => updateMessage();
|
||||
LadderInfo.Matches.CollectionChanged += (_, _) => updateMessage();
|
||||
updateMessage();
|
||||
}
|
||||
|
||||
|
@ -49,10 +49,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
};
|
||||
|
||||
name = round.Name.GetBoundCopy();
|
||||
name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpper(), true);
|
||||
name.BindValueChanged(_ => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpperInvariant(), true);
|
||||
|
||||
description = round.Description.GetBoundCopy();
|
||||
description.BindValueChanged(n => textDescription.Text = round.Description.Value?.ToUpper(), true);
|
||||
description.BindValueChanged(_ => textDescription.Text = round.Description.Value?.ToUpperInvariant(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ namespace osu.Game.Tournament.Screens.Ladder
|
||||
foreach (var match in LadderInfo.Matches)
|
||||
addMatch(match);
|
||||
|
||||
LadderInfo.Rounds.CollectionChanged += (_, __) => layout.Invalidate();
|
||||
LadderInfo.Rounds.CollectionChanged += (_, _) => layout.Invalidate();
|
||||
LadderInfo.Matches.CollectionChanged += (_, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user