1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-15 17:47:18 +08:00

Add migration to remove duplicate bindings

This commit is contained in:
Bartłomiej Dach 2023-10-16 21:26:46 +02:00
parent 639c96e60c
commit 9c6166ec3d
No known key found for this signature in database
4 changed files with 40 additions and 12 deletions

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Input.Bindings;
using osu.Game.Input;
@ -25,11 +24,11 @@ namespace osu.Game.Tests.Input
new RealmKeyBinding(GlobalAction.MusicNext, KeyCombination.FromKey(Key.F5))
};
bool anyCleared = RealmKeyBindingStore.ClearDuplicateBindings(bindings.AsQueryable());
int countCleared = RealmKeyBindingStore.ClearDuplicateBindings(bindings);
Assert.Multiple(() =>
{
Assert.That(anyCleared, Is.False);
Assert.That(countCleared, Is.Zero);
Assert.That(bindings[0].Action, Is.EqualTo((int)GlobalAction.Back));
Assert.That(bindings[0].KeyCombination, Is.EqualTo(new KeyCombination(InputKey.Escape)));
@ -59,11 +58,11 @@ namespace osu.Game.Tests.Input
new RealmKeyBinding(GlobalAction.TakeScreenshot, KeyCombination.FromKey(Key.PrintScreen)),
};
bool anyCleared = RealmKeyBindingStore.ClearDuplicateBindings(bindings.AsQueryable());
int countCleared = RealmKeyBindingStore.ClearDuplicateBindings(bindings);
Assert.Multiple(() =>
{
Assert.That(anyCleared, Is.True);
Assert.That(countCleared, Is.EqualTo(4));
Assert.That(bindings[0].Action, Is.EqualTo((int)GlobalAction.Back));
Assert.That(bindings[0].KeyCombination, Is.EqualTo(new KeyCombination(InputKey.None)));

View File

@ -25,6 +25,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Input;
using osu.Game.Input.Bindings;
using osu.Game.Models;
using osu.Game.Online.API;
@ -84,8 +85,9 @@ namespace osu.Game.Database
/// 32 2023-07-09 Populate legacy scores with the ScoreV2 mod (and restore TotalScore to the legacy total for such scores) using replay files.
/// 33 2023-08-16 Reset default chat toggle key binding to avoid conflict with newly added leaderboard toggle key binding.
/// 34 2023-08-21 Add BackgroundReprocessingFailed flag to ScoreInfo to track upgrade failures.
/// 35 2023-10-16 Clear key combinations of keybindings that are assigned to more than one action in a given settings section.
/// </summary>
private const int schema_version = 34;
private const int schema_version = 35;
/// <summary>
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods.
@ -1031,6 +1033,33 @@ namespace osu.Game.Database
break;
}
case 35:
{
int countCleared = 0;
var globalBindings = migration.NewRealm.All<RealmKeyBinding>().Where(kb => kb.RulesetName == null).ToList();
foreach (var category in Enum.GetValues<GlobalActionCategory>())
{
var categoryActions = GlobalActionContainer.GetGlobalActionsFor(category).Cast<int>().ToHashSet();
var categoryBindings = globalBindings.Where(kb => categoryActions.Contains(kb.ActionInt));
countCleared += RealmKeyBindingStore.ClearDuplicateBindings(categoryBindings);
}
var rulesetBindings = migration.NewRealm.All<RealmKeyBinding>().Where(kb => kb.RulesetName != null).ToList();
foreach (var variantGroup in rulesetBindings.GroupBy(kb => (kb.RulesetName, kb.Variant)))
countCleared += RealmKeyBindingStore.ClearDuplicateBindings(variantGroup);
if (countCleared > 0)
{
Logger.Log($"{countCleared} of your keybinding(s) have been cleared due to being bound to multiple actions. "
+ "Please choose new unique ones in the settings panel.", level: LogLevel.Important);
}
break;
}
}
Logger.Log($"Migration completed in {stopwatch.ElapsedMilliseconds}ms");

View File

@ -136,10 +136,10 @@ namespace osu.Game.Input
/// which are assigned to more than one binding.
/// </summary>
/// <param name="keyBindings">The <see cref="RealmKeyBinding"/>s to de-duplicate.</param>
/// <returns>Whether any bindings have been cleared.</returns>
public static bool ClearDuplicateBindings(IQueryable<IKeyBinding> keyBindings)
/// <returns>Number of bindings cleared.</returns>
public static int ClearDuplicateBindings(IEnumerable<IKeyBinding> keyBindings)
{
bool anyRemoved = false;
int countRemoved = 0;
var lookup = keyBindings.ToLookup(kb => kb.KeyCombination);
@ -151,10 +151,10 @@ namespace osu.Game.Input
foreach (var binding in group)
binding.KeyCombination = new KeyCombination(InputKey.None);
anyRemoved = true;
countRemoved += group.Count();
}
return anyRemoved;
return countRemoved;
}
}
}

View File

@ -218,7 +218,7 @@ namespace osu.Game.Rulesets.UI
base.ReloadMappings(realmKeyBindings);
KeyBindings = KeyBindings.Where(b => RealmKeyBindingStore.CheckValidForGameplay(b.KeyCombination)).ToList();
RealmKeyBindingStore.ClearDuplicateBindings(KeyBindings.AsQueryable());
RealmKeyBindingStore.ClearDuplicateBindings(KeyBindings);
}
}
}