From a1bcdd8c8adfefb6a5dfb17823fda58fde5537b6 Mon Sep 17 00:00:00 2001 From: Falko Galperin Date: Sat, 16 Nov 2024 16:44:24 +0100 Subject: [PATCH] Ask user for confirmation before rebinding key mapping (fix #683) --- Assets/SEE/Controls/KeyActions/KeyMap.cs | 14 ++++- Assets/SEE/UI/SettingsMenu.cs | 76 ++++++++++++++---------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/Assets/SEE/Controls/KeyActions/KeyMap.cs b/Assets/SEE/Controls/KeyActions/KeyMap.cs index 16a47c4fc0..338487db9e 100644 --- a/Assets/SEE/Controls/KeyActions/KeyMap.cs +++ b/Assets/SEE/Controls/KeyActions/KeyMap.cs @@ -134,8 +134,8 @@ internal void ResetKeyCode(KeyActionDescriptor descriptor, KeyCode keyCode) { if (TryGetKeyAction(keyCode, out KeyAction action)) { - throw new($"Cannot register key {keyCode} for {descriptor.Name}." - + $" Key {keyCode} is already bound to {action}.\n"); + throw new KeyBindingsExistsException($"Cannot register key {keyCode} for {descriptor.Name}." + + $" Key {keyCode} is already bound to {action}.\n"); } else { @@ -351,5 +351,13 @@ IEnumerator IEnumerable.GetEnumerator() } } #endregion + + /// + /// An exception indicating that the attempted rebind would result in a duplicate key binding. + /// + public class KeyBindingsExistsException : Exception + { + public KeyBindingsExistsException(string message) : base(message) { } + }; } -} \ No newline at end of file +} diff --git a/Assets/SEE/UI/SettingsMenu.cs b/Assets/SEE/UI/SettingsMenu.cs index 8ce5e9c412..784c1a68a4 100644 --- a/Assets/SEE/UI/SettingsMenu.cs +++ b/Assets/SEE/UI/SettingsMenu.cs @@ -1,13 +1,17 @@ -using UnityEngine.UI; -using UnityEngine; -using TMPro; -using SEE.Controls; -using SEE.Utils; -using SEE.GO; using System; using System.Collections.Generic; -using SEE.UI.Notification; +using System.Linq; +using Cysharp.Threading.Tasks; +using SEE.Controls; using SEE.Controls.KeyActions; +using SEE.GO; +using SEE.UI.Menu; +using SEE.UI.Notification; +using SEE.Utils; +using TMPro; +using UnityEditor; +using UnityEngine; +using UnityEngine.UI; namespace SEE.UI { @@ -19,17 +23,17 @@ public class SettingsMenu : PlatformDependentComponent /// /// Prefab for the . /// - private string SettingsPrefab => UIPrefabFolder + "SettingsMenu"; + private static string SettingsPrefab => UIPrefabFolder + "SettingsMenu"; /// /// Prefab for the KeyBindingContent. /// - private string KeyBindingContent => UIPrefabFolder + "KeyBindingContent"; + private static string KeyBindingContent => UIPrefabFolder + "KeyBindingContent"; /// /// Prefab for the ScrollView. /// - private string ScrollPrefab => UIPrefabFolder + "ScrollPrefab"; + private static string ScrollPrefab => UIPrefabFolder + "ScrollPrefab"; /// /// The game object instantiated for the . @@ -99,26 +103,11 @@ protected override void UpdateDesktop() // the next button that gets pressed will be the new keyBind. if (Input.anyKeyDown) { - foreach (KeyCode key in Enum.GetValues(typeof(KeyCode))) + KeyCode newKey = Enum.GetValues(typeof(KeyCode)).Cast() + .FirstOrDefault(key => Input.GetKeyDown(key) && KeyBindings.AssignableKeyCode(key)); + if (newKey != KeyCode.None) { - if (Input.GetKeyDown(key) && KeyBindings.AssignableKeyCode(key)) - { - try - { - KeyBindings.SetBindingForKey(bindingToRebind, key); - // TODO (#683): We need to open a modal dialog and ask the user - // whether he/she really wants to change the binding. - shortNameOfBindingToLabel[bindingToRebind.Name].text = key.ToString(); - } - catch (Exception ex) - { - ShowNotification.Error("Key code already bound", ex.Message); - } - - bindingToRebind = null; - SEEInput.KeyboardShortcutsEnabled = true; - break; - } + ReassignKeyAsync(bindingToRebind, newKey).Forget(); } } } @@ -139,6 +128,33 @@ protected override void UpdateDesktop() } } + /// + /// Reassigns the binding of the given to the new key + /// after confirming the action with the user. + /// + /// The key binding to reassign. + /// The new key code to assign to the key binding. + private async UniTaskVoid ReassignKeyAsync(KeyActionDescriptor descriptor, KeyCode newKey) + { + string question = $"Do you really want to reassign action \"{descriptor.Name}\" to key {newKey}?"; + if (!await ConfirmDialog.ConfirmAsync(new(question, title: "Change Key?"))) + { + return; + } + try + { + KeyBindings.SetBindingForKey(descriptor, newKey); + shortNameOfBindingToLabel[descriptor.Name].text = newKey.ToString(); + } + catch (KeyMap.KeyBindingsExistsException ex) + { + ShowNotification.Error("Key code already bound", ex.Message, log: false); + } + + bindingToRebind = null; + SEEInput.KeyboardShortcutsEnabled = true; + } + /// /// The keyBinding which gets updated. /// @@ -159,7 +175,7 @@ private void StartRebindFor(KeyActionDescriptor binding) private static void ExitGame() { #if UNITY_EDITOR - UnityEditor.EditorApplication.isPlaying = false; + EditorApplication.isPlaying = false; #else Application.Quit(); #endif