From e972f167bb0c7007670aa840b81db8b9604f5e0e Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Tue, 16 Sep 2025 13:15:31 +0200 Subject: [PATCH 1/7] Add fix for multiple null refs caused by a control scheme being deleted by Undoing the creation of it via ctrl+z. --- .../Commands/ControlSchemeCommands.cs | 14 +++++-- .../Views/ControlSchemesView.cs | 3 +- .../Views/InputActionsEditorView.cs | 40 ++++++++++++++----- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs index 33d186f8a3..7ed574d501 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs @@ -145,10 +145,16 @@ public static Command ResetSelectedControlScheme() { return (in InputActionsEditorState state) => { - var controlSchemeSerializedProperty = state.selectedControlSchemeIndex == -1 ? null : - state.serializedObject - .FindProperty(nameof(InputActionAsset.m_ControlSchemes)) - .GetArrayElementAtIndex(state.selectedControlSchemeIndex); + SerializedProperty controlSchemeSerializedProperty = null; + var serializedProperty = state.serializedObject + .FindProperty(nameof(InputActionAsset.m_ControlSchemes)); + + if (state.selectedControlSchemeIndex < serializedProperty.arraySize) + { + controlSchemeSerializedProperty = state.selectedControlSchemeIndex == -1 ? null : + serializedProperty + .GetArrayElementAtIndex(state.selectedControlSchemeIndex); + } if (controlSchemeSerializedProperty == null) { diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ControlSchemesView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ControlSchemesView.cs index e6e7e58e5f..43fecb0c80 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ControlSchemesView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ControlSchemesView.cs @@ -108,7 +108,6 @@ private void RemoveDeviceRequirement() public override void RedrawUI(InputControlScheme viewState) { rootElement.Q(kControlSchemeNameTextField).value = string.IsNullOrEmpty(m_NewName) ? viewState.name : m_NewName; - m_ListView.itemsSource?.Clear(); m_ListView.itemsSource = viewState.deviceRequirements.Count > 0 ? viewState.deviceRequirements.Select(r => (r.controlPath, r.isOptional)).ToList() : @@ -128,7 +127,7 @@ private void SaveAndClose() CloseView(); } - private void Cancel() + internal void Cancel() { // Reload the selected ControlScheme values from the SerilaizedProperty and throw away any changes Dispatch(ControlSchemeCommands.ResetSelectedControlScheme()); diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs index cd9573e1f3..0ca344afa7 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs @@ -23,6 +23,8 @@ internal class InputActionsEditorView : ViewBase s.selectedControlSchemeIndex, @@ -106,6 +108,22 @@ public InputActionsEditorView(VisualElement root, StateContainer stateContainer, s_OnPasteCutElements.Add(this); } + private Action StateChanged(StateContainer stateContainer) + { + return (inputActionsEditorState, uiRebuildMode) => + { + var state = stateContainer.GetState(); + var viewState = ViewStateSelector.GetViewState(state); + var elementAtOrDefault = viewState.controlSchemes?.ElementAtOrDefault(viewState.selectedControlSchemeIndex); + if (viewState.selectedControlSchemeIndex != -1 && elementAtOrDefault == default(InputControlScheme)) + { + m_ControlSchemesView?.Cancel(); + } + + OnStateChanged(inputActionsEditorState, uiRebuildMode); + }; + } + private void OnReset() { Dispatch(Commands.ReplaceActionMaps(ProjectWideActionsAsset.GetDefaultAssetJson())); @@ -156,9 +174,8 @@ private void SetUpControlSchemesMenu(ViewState viewState) if (viewState.controlSchemes.Any()) { - m_ControlSchemesToolbar.text = viewState.selectedControlSchemeIndex == -1 - ? "All Control Schemes" - : viewState.controlSchemes.ElementAt(viewState.selectedControlSchemeIndex).name; + var elementAtOrDefault = viewState.controlSchemes.ElementAtOrDefault(viewState.selectedControlSchemeIndex); + m_ControlSchemesToolbar.text = elementAtOrDefault == default ? "All Control Schemes" : elementAtOrDefault.name; m_ControlSchemesToolbar.menu.AppendAction("All Control Schemes", _ => SelectControlScheme(-1), viewState.selectedControlSchemeIndex == -1 ? DropdownMenuAction.Status.Checked : DropdownMenuAction.Status.Normal); @@ -186,7 +203,7 @@ private void SetUpDevicesMenu(ViewState viewState) return; } m_DevicesToolbar.SetEnabled(true); - var currentControlScheme = viewState.controlSchemes.ElementAt(viewState.selectedControlSchemeIndex); + var currentControlScheme = viewState.controlSchemes.ElementAtOrDefault(viewState.selectedControlSchemeIndex); if (viewState.selectedDeviceIndex == -1) m_DevicesToolbar.text = "All Devices"; @@ -228,12 +245,15 @@ private void DeleteControlScheme(DropdownMenuAction obj) private void ShowControlSchemeEditor(VisualElement parent, bool updateExisting = false) { - var controlSchemesView = CreateChildView(new ControlSchemesView(parent, stateContainer, updateExisting)); - controlSchemesView.UpdateView(stateContainer.GetState()); - - controlSchemesView.OnClosing += _ => DestroyChildView(controlSchemesView); + m_ControlSchemesView = CreateChildView(new ControlSchemesView(parent, stateContainer, updateExisting)); + m_ControlSchemesView.UpdateView(stateContainer.GetState()); + m_ControlSchemesView.OnClosing += _ => + { + DestroyChildView(m_ControlSchemesView); + m_ControlSchemesView = null; + }; } - + private void SelectControlScheme(int controlSchemeIndex) { Dispatch(ControlSchemeCommands.SelectControlScheme(controlSchemeIndex)); From ce32d45fb9c70315f14702025bf2b873fc1b77f4 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Tue, 16 Sep 2025 17:14:22 +0200 Subject: [PATCH 2/7] Add better fix for undo bug in control scheme editor. --- .../Views/InputActionsEditorView.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs index 0ca344afa7..529e59dfee 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using UnityEditor; using UnityEditor.UIElements; using UnityEngine.UIElements; @@ -93,7 +94,7 @@ public InputActionsEditorView(VisualElement root, StateContainer stateContainer, // only register the state changed event here in the parent. Changes will be cascaded // into child views. - stateContainer.StateChanged += StateChanged(stateContainer); + stateContainer.StateChanged += OnStateChanged; CreateSelector( s => s.selectedControlSchemeIndex, @@ -106,12 +107,15 @@ public InputActionsEditorView(VisualElement root, StateContainer stateContainer, }); s_OnPasteCutElements.Add(this); + + Undo.undoRedoPerformed += CheckForInvalidControlSchemeInOneFrame; } - private Action StateChanged(StateContainer stateContainer) + private async void CheckForInvalidControlSchemeInOneFrame() { - return (inputActionsEditorState, uiRebuildMode) => + try { + await Task.Delay(1); var state = stateContainer.GetState(); var viewState = ViewStateSelector.GetViewState(state); var elementAtOrDefault = viewState.controlSchemes?.ElementAtOrDefault(viewState.selectedControlSchemeIndex); @@ -119,9 +123,11 @@ private Action StateChanged(StateContain { m_ControlSchemesView?.Cancel(); } - - OnStateChanged(inputActionsEditorState, uiRebuildMode); - }; + } + catch (Exception e) + { + Debug.LogException(e); + } } private void OnReset() @@ -278,6 +284,7 @@ public override void DestroyView() { base.DestroyView(); s_OnPasteCutElements.Remove(this); + Undo.undoRedoPerformed -= CheckForInvalidControlSchemeInOneFrame; } public void OnPaste(InputActionsEditorState state) From 1b6175e4cd3baa4dbaf500dbc9e83a334b1a9ea1 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 22 Sep 2025 14:46:43 +0200 Subject: [PATCH 3/7] Add formatting. --- .../Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs | 2 +- .../Editor/UITKAssetEditor/Views/InputActionsEditorView.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs index 7ed574d501..f03291bfbd 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/ControlSchemeCommands.cs @@ -148,7 +148,7 @@ public static Command ResetSelectedControlScheme() SerializedProperty controlSchemeSerializedProperty = null; var serializedProperty = state.serializedObject .FindProperty(nameof(InputActionAsset.m_ControlSchemes)); - + if (state.selectedControlSchemeIndex < serializedProperty.arraySize) { controlSchemeSerializedProperty = state.selectedControlSchemeIndex == -1 ? null : diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs index 529e59dfee..cb02e1fcca 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs @@ -24,7 +24,7 @@ internal class InputActionsEditorView : ViewBase Date: Fri, 26 Sep 2025 11:46:37 +0200 Subject: [PATCH 4/7] Update the changelog to reflect the bugfix ISXB-1607. --- Packages/com.unity.inputsystem/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 9b80e149bc..06818f4020 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -27,6 +27,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed the compilation warnings when used with Unity 6.4 (ISX-2349). - Fixed an issue where `InputSystemUIInputModule.localMultiPlayerRoot` could not be set to `null` when using `MultiplayerEventSystem`. [ISXB-1610](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1610) - Fixed an issue in `Keyboard` where the sub-script operator would return a `null` key control for the deprecated key `Key.IMESelected`. Now, an aliased `KeyControl`mapping to the IMESelected bit is returned for compability reasons. It is still strongly advised to not rely on this key since `IMESelected` bit isn't strictly a key and will be removed from the `Key` enumeration type in a future major revision. [ISXB-1541](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1541). +- Fixed an ArgumentOutOfRangeException that was thrown when pressing the undo shortcut while changing a control scheme name. ## [1.14.2] - 2025-08-05 From f53e9a42f96c2fca1f6e841a631c61acf5bf4fd5 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Fri, 26 Sep 2025 11:50:16 +0200 Subject: [PATCH 5/7] Update the changelog to include the public issue tracker link for ISXB-1607. --- Packages/com.unity.inputsystem/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 06818f4020..899b856544 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -27,7 +27,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed the compilation warnings when used with Unity 6.4 (ISX-2349). - Fixed an issue where `InputSystemUIInputModule.localMultiPlayerRoot` could not be set to `null` when using `MultiplayerEventSystem`. [ISXB-1610](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1610) - Fixed an issue in `Keyboard` where the sub-script operator would return a `null` key control for the deprecated key `Key.IMESelected`. Now, an aliased `KeyControl`mapping to the IMESelected bit is returned for compability reasons. It is still strongly advised to not rely on this key since `IMESelected` bit isn't strictly a key and will be removed from the `Key` enumeration type in a future major revision. [ISXB-1541](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1541). -- Fixed an ArgumentOutOfRangeException that was thrown when pressing the undo shortcut while changing a control scheme name. +- Fixed an ArgumentOutOfRangeException that was thrown when pressing the undo shortcut while changing a control scheme name. [ISXB-1607](https://issuetracker.unity3d.com/issues/argumentoutofrangeexception-error-is-thrown-when-pressing-the-undo-shortcut-while-changing-the-control-scheme-name) ## [1.14.2] - 2025-08-05 From 31800beeb902206ee464ce55600ff4e898dd76de Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Tue, 7 Oct 2025 15:00:45 +0200 Subject: [PATCH 6/7] Remove hacky wait for seconds to check if the control scheme was deleted or not. --- .../Views/InputActionsEditorView.cs | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs index cb02e1fcca..3694b82b43 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs @@ -108,26 +108,12 @@ public InputActionsEditorView(VisualElement root, StateContainer stateContainer, s_OnPasteCutElements.Add(this); - Undo.undoRedoPerformed += CheckForInvalidControlSchemeInOneFrame; + Undo.undoRedoPerformed += CloseControlSchemeView; } - private async void CheckForInvalidControlSchemeInOneFrame() + private void CloseControlSchemeView() { - try - { - await Task.Delay(1); - var state = stateContainer.GetState(); - var viewState = ViewStateSelector.GetViewState(state); - var elementAtOrDefault = viewState.controlSchemes?.ElementAtOrDefault(viewState.selectedControlSchemeIndex); - if (viewState.selectedControlSchemeIndex != -1 && elementAtOrDefault == default(InputControlScheme)) - { - m_ControlSchemesView?.Cancel(); - } - } - catch (Exception e) - { - Debug.LogException(e); - } + m_ControlSchemesView?.Cancel(); } private void OnReset() @@ -284,7 +270,7 @@ public override void DestroyView() { base.DestroyView(); s_OnPasteCutElements.Remove(this); - Undo.undoRedoPerformed -= CheckForInvalidControlSchemeInOneFrame; + Undo.undoRedoPerformed -= CloseControlSchemeView; } public void OnPaste(InputActionsEditorState state) From cf3f6a554a85ed1b53b2ebc393689340386be042 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Tue, 7 Oct 2025 15:05:05 +0200 Subject: [PATCH 7/7] Remove threading using as it's not needed anymore. --- .../Editor/UITKAssetEditor/Views/InputActionsEditorView.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs index 3694b82b43..8bedceee99 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using UnityEditor; using UnityEditor.UIElements; using UnityEngine.UIElements;