diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index c0f0e5fd5e..1f589edc88 100755 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -26,6 +26,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed "Create Actions..." on `PlayerInput` creating an asset with an incorrect binding for taps on Touchscreens. \ __NOTE: If you have already created an .inputactions asset with this mechanism, update "tap [Touchscreen]" to "Primary Touch/Tap" to fix the problem manually.__ - Fixed `Invoke CSharp Events` when selected in `PlayerInput` not triggering `PlayerInput.onActionTriggered`. +- Fixed duplicating multiple items at the same time in the action editor duplicating them repeatedly. ### Changed diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionTreeView.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionTreeView.cs index 4a7e0002a1..96368b4c81 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionTreeView.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionTreeView.cs @@ -550,9 +550,7 @@ public void HandleCopyPasteCommandEvent(Event uiEvent) DeleteDataOfSelectedItems(); break; case k_DuplicateCommand: - var buffer = new StringBuilder(); - CopySelectedItemsTo(buffer); - PasteDataFrom(buffer.ToString()); + DuplicateSelection(); break; case k_DeleteCommand: DeleteDataOfSelectedItems(); @@ -564,6 +562,38 @@ public void HandleCopyPasteCommandEvent(Event uiEvent) } } + private void DuplicateSelection() + { + var buffer = new StringBuilder(); + + // If we have a multi-selection, we want to perform the duplication as if each item + // was duplicated individually. Meaning we paste each duplicate right after the item + // it was duplicated from. So if, say, an action is selected at the beginning of the + // tree and one is selected from the end of it, we still paste the copies into the + // two separate locations correctly. + // + // Technically, if both parents and children are selected, we're order dependent here + // but not sure we really need to care. + + var selection = GetSelection(); + ClearSelection(); + + // Copy-paste each selected item in turn. + var newItemIds = new List(); + foreach (var id in selection) + { + SetSelection(new[] { id }); + + buffer.Length = 0; + CopySelectedItemsTo(buffer); + PasteDataFrom(buffer.ToString()); + + newItemIds.AddRange(GetSelection()); + } + + SetSelection(newItemIds); + } + internal const string k_CopyPasteMarker = "INPUTASSET "; private const string k_StartOfText = "\u0002"; private const string k_StartOfHeading = "\u0001"; @@ -865,11 +895,7 @@ public void BuildContextMenuFor(Type itemType, GenericMenu menu, bool multiSelec { menu.AddDisabledItem(s_RenameLabel); } - menu.AddItem(s_DuplicateLabel, false, () => - { - CopySelectedItemsToClipboard(); - PasteDataFromClipboard(); - }); + menu.AddItem(s_DuplicateLabel, false, DuplicateSelection); menu.AddItem(s_DeleteLabel, false, DeleteDataOfSelectedItems); }