From b7f93d88b32f6982c4c761ed84052a8ea1beaa1e Mon Sep 17 00:00:00 2001 From: Alex Tyrer Date: Mon, 18 Nov 2024 17:54:08 +0000 Subject: [PATCH 1/3] [Input System] Fixed pasting bindings into empty Input Action asset (case ISXB-1180) - take #2 FIX: Fixed pasting bindings into empty Input Action asset (case ISXB-1180) Ensure PasteBlocks() deals with invalid selection - when copied type is binding we need to have a valid Action selected to paste into. --- .../Editor/UITKAssetEditor/Views/CopyPasteHelper.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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 3d2fad8100..0e965f91f0 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs @@ -265,9 +265,18 @@ private static void PasteBlocks(string transmission, int indexToInsert, Serializ else { var actionName = Selectors.GetSelectedBinding(s_State)?.wrappedProperty.FindPropertyRelative("m_Action") - .stringValue; + .stringValue; + if (s_State.selectionType == SelectionType.Action) - actionName = PropertyName(Selectors.GetSelectedAction(s_State)?.wrappedProperty); + { + SerializedProperty property = Selectors.GetSelectedAction(s_State)?.wrappedProperty; + if (property == null) + return; + actionName = PropertyName(property); + } + if (actionName == null) + return; + PasteBindingOrComposite(arrayToInsertInto, block, indexToInsert, actionName); } } From 96a5dbefd42fb0e8a4ca7be2af9571da820f09ea Mon Sep 17 00:00:00 2001 From: Alex Tyrer Date: Mon, 18 Nov 2024 20:09:07 +0000 Subject: [PATCH 2/3] [Input System] Format source file (CopyPasteHelper.cs) --- .../InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0e965f91f0..9dfea2c1d6 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/CopyPasteHelper.cs @@ -265,7 +265,7 @@ private static void PasteBlocks(string transmission, int indexToInsert, Serializ else { var actionName = Selectors.GetSelectedBinding(s_State)?.wrappedProperty.FindPropertyRelative("m_Action") - .stringValue; + .stringValue; if (s_State.selectionType == SelectionType.Action) { From 8de537212492812d0d7d77970ddb24e36bc8eba9 Mon Sep 17 00:00:00 2001 From: Alex Tyrer Date: Thu, 21 Nov 2024 12:00:43 +0000 Subject: [PATCH 3/3] [Input System] Clean up context menu behaviour in InputActionsEditor window (Action Maps and Action views) (case ISXB-1180) (case ISXB-1182) o Ensure Paste option is only present in context menu when appropriate. o Fix menu separator presence (or absense). o Action Maps view: can Paste ActionMap or Action (if a map is present). o Actions view: can paste Actions or Bindings depending on selected item context. --- .../UITKAssetEditor/Views/ContextMenu.cs | 90 +++++++++++++++---- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ContextMenu.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ContextMenu.cs index ef70992280..51b3a5d331 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ContextMenu.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ContextMenu.cs @@ -25,6 +25,21 @@ internal static class ContextMenu private static readonly string add_Binding_String = "Add Binding"; #region ActionMaps + // Determine whether current clipboard contents can can pasted into the ActionMaps view + // + // can always paste an ActionMap + // need an existing map to be able to paste an Action + // + private static bool CanPasteIntoActionMaps(ActionMapsView mapView) + { + bool haveMap = mapView.GetMapCount() > 0; + var copiedType = CopyPasteHelper.GetCopiedClipboardType(); + bool copyIsMap = copiedType == typeof(InputActionMap); + bool copyIsAction = copiedType == typeof(InputAction); + bool hasPastableData = (copyIsMap || (copyIsAction && haveMap)); + return hasPastableData; + } + public static void GetContextMenuForActionMapItem(ActionMapsView mapView, InputActionMapsTreeViewItem treeViewItem, int index) { treeViewItem.OnContextualMenuPopulateEvent = (menuEvent => @@ -39,9 +54,15 @@ public static void GetContextMenuForActionMapItem(ActionMapsView mapView, InputA menuEvent.menu.AppendAction(copy_String, _ => mapView.CopyItems()); menuEvent.menu.AppendAction(cut_String, _ => mapView.CutItems()); - var copiedAction = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction); - if (CopyPasteHelper.HasPastableClipboardData(typeof(InputActionMap))) - menuEvent.menu.AppendAction(paste_String, _ => mapView.PasteItems(copiedAction)); + if (CanPasteIntoActionMaps(mapView)) + { + bool copyIsAction = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction); + if (CopyPasteHelper.HasPastableClipboardData(typeof(InputActionMap))) + menuEvent.menu.AppendAction(paste_String, _ => mapView.PasteItems(copyIsAction)); + } + + menuEvent.menu.AppendSeparator(); + menuEvent.menu.AppendAction(add_Action_Map_String, _ => mapView.AddActionMap()); }); } @@ -51,11 +72,12 @@ public static void GetContextMenuForActionMapsEmptySpace(ActionMapsView mapView, { _ = new ContextualMenuManipulator(menuEvent => { - var copiedAction = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction); - if (CopyPasteHelper.HasPastableClipboardData(typeof(InputActionMap))) - menuEvent.menu.AppendAction(paste_String, _ => mapView.PasteItems(copiedAction)); - - menuEvent.menu.AppendSeparator(); + if (CanPasteIntoActionMaps(mapView)) + { + bool copyIsAction = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction); + menuEvent.menu.AppendAction(paste_String, _ => mapView.PasteItems(copyIsAction)); + menuEvent.menu.AppendSeparator(); + } menuEvent.menu.AppendAction(add_Action_Map_String, _ => mapView.AddActionMap()); }) { target = element }; } @@ -63,15 +85,47 @@ public static void GetContextMenuForActionMapsEmptySpace(ActionMapsView mapView, #endregion #region Actions + // Determine whether current clipboard contents can pasted into the Actions TreeView + // + // item selected => can paste either Action or Binding (depends on selected item context) + // empty view => can only paste Action + // no selection => can only paste Action + // + private static bool CanPasteIntoActions(TreeView treeView) + { + bool hasPastableData = false; + bool selected = treeView.selectedIndex != -1; + if (selected) + { + var item = treeView.GetItemDataForIndex(treeView.selectedIndex); + var itemType = item.isAction ? typeof(InputAction) : typeof(InputBinding); + hasPastableData = CopyPasteHelper.HasPastableClipboardData(itemType); + } + else + { + // Cannot paste Binding when no Action is selected or into an empty view + bool copyIsBinding = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputBinding); + hasPastableData = !copyIsBinding && CopyPasteHelper.HasPastableClipboardData(typeof(InputAction)); + } + return hasPastableData; + } + // Add the "Paste" option to all elements in the Action area. public static void GetContextMenuForActionListView(ActionsTreeView actionsTreeView, TreeView treeView, VisualElement target) { _ = new ContextualMenuManipulator(menuEvent => { - var item = treeView.GetItemDataForIndex(treeView.selectedIndex); - var hasPastableData = CopyPasteHelper.HasPastableClipboardData(item.isAction ? typeof(InputAction) : typeof(InputBinding)); - if (hasPastableData) - menuEvent.menu.AppendAction(paste_String, _ => actionsTreeView.PasteItems()); + bool haveMap = actionsTreeView.GetMapCount() > 0; + if (haveMap) + { + bool hasPastableData = CanPasteIntoActions(treeView); + if (hasPastableData) + { + menuEvent.menu.AppendAction(paste_String, _ => actionsTreeView.PasteItems()); + } + menuEvent.menu.AppendSeparator(); + menuEvent.menu.AppendAction(add_Action_String, _ => actionsTreeView.AddAction()); + } }) { target = target }; } @@ -81,13 +135,15 @@ public static void GetContextMenuForActionsEmptySpace(ActionsTreeView actionsTre { _ = new ContextualMenuManipulator(menuEvent => { - if (actionsTreeView.GetMapCount() > 0 && (!onlyShowIfTreeIsEmpty || treeView.GetTreeCount() == 0)) + bool haveMap = actionsTreeView.GetMapCount() > 0; + if (haveMap && (!onlyShowIfTreeIsEmpty || treeView.GetTreeCount() == 0)) { - var item = treeView.GetItemDataForIndex(treeView.selectedIndex); - if (CopyPasteHelper.HasPastableClipboardData(item.isAction ? typeof(InputAction) : typeof(InputBinding))) + bool hasPastableData = CanPasteIntoActions(treeView); + if (hasPastableData) + { menuEvent.menu.AppendAction(paste_String, _ => actionsTreeView.PasteItems()); - - menuEvent.menu.AppendSeparator(); + menuEvent.menu.AppendSeparator(); + } menuEvent.menu.AppendAction(add_Action_String, _ => actionsTreeView.AddAction()); } }) { target = target };