From 8944d39fb5fb183eefb9d2d0f441c4a8a4e36d63 Mon Sep 17 00:00:00 2001 From: Graham Huws Date: Thu, 15 Feb 2024 00:36:17 +0000 Subject: [PATCH] FIX: Allow Copy/Paste between windows by intercepting the commands higher up the hierarchy. (ISX-1823) --- Packages/com.unity.inputsystem/CHANGELOG.md | 1 + .../UITKAssetEditor/Views/CopyPasteHelper.cs | 9 +++- .../Views/InputActionsEditorView.cs | 53 +++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 1437473c32..24ff187e71 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -43,6 +43,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed InputManager.asset file growing in size on each Reset call. - Fixed Opening InputDebugger throws 'Action map must have state at this point' error - Fixed Cut/Paste behaviour to match Editor - Cut items will now be cleared from clipboard after pasting. +- Fixed Pasting items between windows not working until an item in the Action Map/Action lists was selected. ## [1.8.0-pre.2] - 2023-11-09 diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs index badbbd8e70..a5f54566f9 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs @@ -204,6 +204,10 @@ private static void PasteActionsFromClipboard(InputActionsEditorState state, boo var index = state.selectedActionIndex; if (addLast) index = actionArray.arraySize - 1; + + if (index < 0) + index = 0; + PasteData(EditorGUIUtility.systemCopyBuffer, new[] {index}, actionArray); } @@ -288,13 +292,14 @@ private static void PasteAction(SerializedProperty arrayProperty, string jsonToI private static int PasteBindingOrComposite(SerializedProperty arrayProperty, string json, int index, string actionName, bool createCompositeParts = true) { var pastePartOfComposite = IsPartOfComposite(json); - if (index > 0) + if (index > 0 && arrayProperty.arraySize > 0 && index - 1 < arrayProperty.arraySize) { var currentProperty = arrayProperty.GetArrayElementAtIndex(index - 1); var currentIsComposite = IsComposite(currentProperty) || IsPartOfComposite(currentProperty); if (pastePartOfComposite && !currentIsComposite) //prevent pasting part of composite into non-composite return index; } + index = pastePartOfComposite || s_State.selectionType == SelectionType.Action ? index : Selectors.GetSelectedBindingIndexAfterCompositeBindings(s_State) + 1; if (json.Contains(k_BindingData)) //copied data is composite with bindings - only true for directly copied composites, not for composites from copied actions return PasteCompositeFromJson(arrayProperty, json, index, actionName); @@ -351,7 +356,7 @@ private static bool IsPartOfComposite(string json) private static SerializedProperty AddElement(SerializedProperty arrayProperty, string name, int index = -1) { var uniqueName = InputActionSerializationHelpers.FindUniqueName(arrayProperty, name); - if (index < 0) + if (index < 0 || index > arrayProperty.arraySize) index = arrayProperty.arraySize; arrayProperty.InsertArrayElementAtIndex(index); 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 c8d91fa9e6..bd41c775af 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/InputActionsEditorView.cs @@ -1,4 +1,5 @@ #if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS +using CmdEvents = UnityEngine.InputSystem.Editor.InputActionsEditorConstants.CommandEvents; using System; using System.Collections.Generic; using System.Linq; @@ -14,6 +15,8 @@ internal class InputActionsEditorView : ViewBase("actions-tree-view"); + m_ActionMapsListView = root.Q("action-maps-list-view"); + + root.RegisterCallback(OnValidateCommand); + root.RegisterCallback(OnExecuteCommand); + root.focusable = true; // Required for CommandEvents to work } private void OnReset() @@ -159,6 +169,49 @@ public class ViewState public IEnumerable controlSchemes; public int selectedControlSchemeIndex; } + + void OnExecuteCommand(ExecuteCommandEvent evt) + { + if (evt.commandName != CmdEvents.Paste) + return; + + var copiedType = CopyPasteHelper.GetCopiedClipboardType(); + + if (copiedType == typeof(InputActionMap)) + { + Dispatch(Commands.PasteActionMaps()); + } + else if (copiedType == typeof(InputAction)) + { + // Can't paste an Action without any Action Maps for it to go to + if (m_ActionMapsListView.itemsSource.Count > 0) + Dispatch(Commands.PasteActionsOrBindings()); + } + else if (copiedType == typeof(InputBinding)) + { + // Can't paste a Binding without any Actions for it to go to + if (m_ActionsTreeView.itemsSource.Count > 0) + { + var oldSelectedBinding = stateContainer.GetState().selectedBindingIndex; + Dispatch(Commands.PasteActionsOrBindings()); + + // If paste succeeded, expand the relevant Action to show the new binding. + if (stateContainer.GetState().selectedBindingIndex != oldSelectedBinding) + m_ActionsTreeView.ExpandItem(m_ActionsTreeView.GetIdForIndex(stateContainer.GetState().selectedActionIndex)); + } + } + } + + void OnValidateCommand(ValidateCommandEvent evt) + { + // Mark commands as supported for Execute by stopping propagation of the event + switch (evt.commandName) + { + case CmdEvents.Paste: + evt.StopPropagation(); + break; + } + } } internal static partial class Selectors