Skip to content

Commit 5b346ad

Browse files
authored
NEW: add maps, actions and bindings via '+' button (ISX-1040) (#1675)
* ADDED: add functions via '+' button for maps, actions and bindings * Fixed editor index out of bounds error if no binding added * Change: select actions and actionMaps by serialized property- not string * Change: refactor naming for ActionsTreeView method
1 parent d4dd758 commit 5b346ad

7 files changed

Lines changed: 134 additions & 15 deletions

File tree

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Commands/Commands.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,43 @@ public static Command SelectActionMap(string actionMapName)
2121
return (in InputActionsEditorState state) => state.SelectActionMap(actionMapName);
2222
}
2323

24+
public static Command AddActionMap()
25+
{
26+
return (in InputActionsEditorState state) =>
27+
{
28+
var newMap = InputActionSerializationHelpers.AddActionMap(state.serializedObject);
29+
var actionProperty = InputActionSerializationHelpers.AddAction(newMap);
30+
InputActionSerializationHelpers.AddBinding(actionProperty, newMap);
31+
state.serializedObject.ApplyModifiedProperties();
32+
return state.SelectActionMap(newMap);
33+
};
34+
}
35+
36+
public static Command AddAction()
37+
{
38+
return (in InputActionsEditorState state) =>
39+
{
40+
var actionMap = Selectors.GetSelectedActionMap(state).wrappedProperty;
41+
var newAction = InputActionSerializationHelpers.AddAction(actionMap);
42+
InputActionSerializationHelpers.AddBinding(newAction, actionMap);
43+
state.serializedObject.ApplyModifiedProperties();
44+
return state.SelectAction(newAction);
45+
};
46+
}
47+
48+
public static Command AddBinding()
49+
{
50+
return (in InputActionsEditorState state) =>
51+
{
52+
var action = Selectors.GetSelectedAction(state).wrappedProperty;
53+
var map = Selectors.GetSelectedActionMap(state).wrappedProperty;
54+
var binding = InputActionSerializationHelpers.AddBinding(action, map);
55+
var bindingIndex = new SerializedInputBinding(binding).indexOfBinding;
56+
state.serializedObject.ApplyModifiedProperties();
57+
return state.With(selectedBindingIndex: bindingIndex, selectionType: SelectionType.Binding);
58+
};
59+
}
60+
2461
public static Command ExpandCompositeBinding(SerializedInputBinding binding)
2562
{
2663
return (in InputActionsEditorState state) => state.ExpandCompositeBinding(binding);

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorState.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ public InputActionsEditorState SelectAction(string actionName)
152152
throw new InvalidOperationException($"Couldn't find an action map with name '{actionName}'.");
153153
}
154154

155+
public InputActionsEditorState SelectAction(SerializedProperty state)
156+
{
157+
var index = state.GetIndexOfArrayElement();
158+
return With(selectedActionIndex: index, selectionType: SelectionType.Action);
159+
}
160+
161+
public InputActionsEditorState SelectActionMap(SerializedProperty state)
162+
{
163+
var index = state.GetIndexOfArrayElement();
164+
return With(selectedBindingIndex: 0, selectedActionMapIndex: index, selectedActionIndex: 0);
165+
}
166+
155167
public InputActionsEditorState SelectActionMap(string actionMapName)
156168
{
157169
var actionMap = GetActionMapByName(actionMapName);
@@ -160,6 +172,11 @@ public InputActionsEditorState SelectActionMap(string actionMapName)
160172
selectedActionIndex: 0);
161173
}
162174

175+
public InputActionsEditorState SelectBinding(int index)
176+
{
177+
return With(selectedBindingIndex: index);
178+
}
179+
163180
public ReadOnlyCollection<int> GetOrCreateExpandedState()
164181
{
165182
return new ReadOnlyCollection<int>(GetOrCreateExpandedStateInternal().ToList());

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Resources/InputActionsEditor.uxml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
</ui:VisualElement>
3333
<ui:TwoPaneSplitView name="actions-and-properties-split-view" fixed-pane-index="1" fixed-pane-initial-dimension="400" style="height: auto;">
3434
<ui:VisualElement name="actions-container" class="body-panel-container">
35-
<ui:VisualElement name="header" class="body-panel-header">
35+
<ui:VisualElement name="header" class="body-panel-header" style="justify-content: space-between;">
3636
<ui:Label text="Actions" display-tooltip-when-elided="true" name="actions-label" />
37+
<ui:Button text="+" display-tooltip-when-elided="true" name="add-new-action-button" style="align-items: auto;" />
3738
</ui:VisualElement>
3839
<ui:VisualElement name="body">
3940
<ui:TreeView view-data-key="unity-tree-view" focusable="true" name="actions-tree-view" show-border="false" reorderable="true" show-alternating-row-backgrounds="None" fixed-item-height="20" />

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Resources/InputActionsEditorStyles.uss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
border-width: 0;
3030
}
3131

32+
#add-new-action-button {
33+
background-color: transparent;
34+
border-width: 0;
35+
}
36+
3237
#bindings-container {
3338
min-width: 225px;
3439
border-left-width: 0;
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
22
<Style src="project://database/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Resources/InputActionsEditorStyles.uss?fileID=7433441132597879392&amp;guid=7dac9c49a90bca4499371d0adc9b617b&amp;type=3#InputActionsEditorStyles" />
3-
<ui:VisualElement name="item-row" class="unity-list-view__item" style="flex-direction: row; flex-grow: 1; justify-content: flex-start; margin-left: 4px; flex-shrink: 0;">
3+
<ui:VisualElement name="item-row" class="unity-list-view__item" style="flex-direction: row; flex-grow: 1; justify-content: space-between; margin-left: 4px; flex-shrink: 0;">
44
<ui:VisualElement name="row" style="flex-direction: row; border-left-width: 0; border-left-color: rgb(89, 89, 89); justify-content: flex-start; align-items: center;">
55
<ui:VisualElement name="icon" style="justify-content: center; background-image: url(&apos;project://database/Packages/com.unity.inputsystem/InputSystem/Editor/Icons/d_InputControl.png?fileID=2800000&amp;guid=399cd90f4e31041e692a7d3a8b1aa4d0&amp;type=3#d_InputControl&apos;); width: 16px; height: 16px;" />
66
<ui:TextField picking-mode="Ignore" name="rename-text-field" is-delayed="true" focusable="true" class="unity-input-actions-editor-hidden" style="visibility: visible; flex-shrink: 1;" />
77
<ui:Label text="binding-name" display-tooltip-when-elided="true" name="name" style="flex-grow: 1; justify-content: center; align-items: stretch; margin-left: 4px; -unity-font-style: normal;" />
88
</ui:VisualElement>
9+
<ui:Button text="+" display-tooltip-when-elided="true" enable-rich-text="false" name="add-new-binding-button" style="opacity: 1; background-color: rgba(255, 255, 255, 0); border-left-color: rgba(255, 255, 255, 0); border-right-color: rgba(255, 255, 255, 0); border-top-color: rgba(255, 255, 255, 0); border-bottom-color: rgba(255, 255, 255, 0); display: none; align-items: flex-end; align-self: auto; flex-direction: row-reverse;" />
910
</ui:VisualElement>
1011
</ui:UXML>

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ActionMapsView.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#if UNITY_EDITOR && UNITY_2022_1_OR_NEWER
22
using System.Collections.Generic;
33
using System.Linq;
4+
using UnityEngine.InputSystem.Utilities;
45
using UnityEngine.UIElements;
56

67
namespace UnityEngine.InputSystem.Editor
@@ -33,25 +34,23 @@ public ActionMapsView(VisualElement root, StateContainer stateContainer)
3334

3435
CreateSelector(s => new ViewStateCollection<string>(Selectors.GetActionMapNames(s)),
3536
(actionMapNames, state) => new ViewState(Selectors.GetSelectedActionMap(state), actionMapNames));
37+
38+
addActionMapButton.clicked += AddActionMap;
3639
}
3740

3841
private Button addActionMapButton => m_Root?.Q<Button>("add-new-action-map-button");
3942

4043
public override void RedrawUI(ViewState viewState)
4144
{
42-
m_ListView.bindItem = (element, i) =>
43-
{
44-
var treeViewItem = (InputActionsTreeViewItem)element;
45-
treeViewItem.label.text = (string)m_ListView.itemsSource[i];
46-
};
47-
m_ListView.makeItem = () => new InputActionsTreeViewItem();
4845
m_ListView.itemsSource = viewState.actionMapNames?.ToList() ?? new List<string>();
49-
addActionMapButton.clicked += ShowAddActionMapWindow;
46+
var indexOf = viewState.actionMapNames.IndexOf(viewState.selectedActionMap.name);
47+
m_ListView.SetSelection(indexOf);
48+
m_ListView.Rebuild();
5049
}
5150

5251
public override void DestroyView()
5352
{
54-
addActionMapButton.clicked -= ShowAddActionMapWindow;
53+
addActionMapButton.clicked -= AddActionMap;
5554
}
5655

5756
private void ChangeActionMapName(string newName)
@@ -64,8 +63,9 @@ private void SelectActionMap()
6463
Dispatch(Commands.SelectActionMap((string)m_ListView.selectedItem));
6564
}
6665

67-
private void ShowAddActionMapWindow()
66+
private void AddActionMap()
6867
{
68+
Dispatch(Commands.AddActionMap());
6969
}
7070

7171
private readonly VisualElement m_Root;

Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/Views/ActionsTreeView.cs

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ internal class ActionsTreeView : ViewBase<ActionsTreeView.ViewState>
1717
{
1818
private readonly VisualElement m_Root;
1919
private readonly TreeView m_ActionsTreeView;
20+
private Button addActionButton => m_Root?.Q<Button>("add-new-action-button");
2021

2122
public ActionsTreeView(VisualElement root, StateContainer stateContainer)
2223
: base(stateContainer)
@@ -31,6 +32,14 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
3132
var item = m_ActionsTreeView.GetItemDataForIndex<ActionOrBindingData>(i);
3233

3334
e.Q<Label>("name").text = item.name;
35+
var addBindingButton = e.Q<Button>("add-new-binding-button");
36+
if (item.isAction)
37+
{
38+
addBindingButton.style.display = DisplayStyle.Flex;
39+
addBindingButton.clicked += () => AddBinding(item.name);
40+
}
41+
else
42+
addBindingButton.style.display = DisplayStyle.None;
3443

3544
if (!string.IsNullOrEmpty(item.controlLayout))
3645
e.Q<VisualElement>("icon").style.backgroundImage =
@@ -49,19 +58,69 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
4958
};
5059

5160
CreateSelector(Selectors.GetActionsForSelectedActionMap,
52-
(_, state) => new ViewState {treeViewData = Selectors.GetActionsAsTreeViewData(state)});
61+
(_, state) =>
62+
{
63+
var treeData = Selectors.GetActionsAsTreeViewData(state);
64+
return new ViewState
65+
{
66+
treeViewData = treeData,
67+
newElementID = state.selectionType == SelectionType.Action ? treeData[state.selectedActionIndex].id : GetComponentOrBindingID(treeData, state.selectedBindingIndex)
68+
};
69+
});
70+
71+
addActionButton.clicked += AddAction;
72+
}
73+
74+
private int GetComponentOrBindingID(List<TreeViewItemData<ActionOrBindingData>> treeList, int selectedBindingIndex)
75+
{
76+
var currentBindingIndex = -1;
77+
foreach (var action in treeList)
78+
{
79+
foreach (var bindingOrComponent in action.children)
80+
{
81+
currentBindingIndex++;
82+
if (currentBindingIndex == selectedBindingIndex) return bindingOrComponent.id;
83+
if (bindingOrComponent.hasChildren)
84+
{
85+
foreach (var binding in bindingOrComponent.children)
86+
{
87+
currentBindingIndex++;
88+
if (currentBindingIndex == selectedBindingIndex) return binding.id;
89+
}
90+
}
91+
}
92+
}
93+
return -1;
94+
}
95+
96+
public override void DestroyView()
97+
{
98+
addActionButton.clicked -= AddAction;
5399
}
54100

55101
public override void RedrawUI(ViewState viewState)
56102
{
57103
m_ActionsTreeView.Clear();
58104
m_ActionsTreeView.SetRootItems(viewState.treeViewData);
105+
m_ActionsTreeView.SetSelectionById(viewState.newElementID);
59106
m_ActionsTreeView.Rebuild();
60107
}
61108

109+
private void AddAction()
110+
{
111+
Dispatch(Commands.AddAction());
112+
}
113+
114+
private void AddBinding(string actionName)
115+
{
116+
Dispatch(Commands.SelectAction(actionName));
117+
Dispatch(Commands.AddBinding());
118+
}
119+
62120
internal class ViewState
63121
{
64122
public List<TreeViewItemData<ActionOrBindingData>> treeViewData;
123+
public int newElementID;
65124
}
66125
}
67126

@@ -134,7 +193,7 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
134193
i--;
135194
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(id++,
136195
new ActionOrBindingData(false, serializedInputBinding.name, action.expectedControlType, serializedInputBinding.indexOfBinding),
137-
compositeItems));
196+
compositeItems.Count > 0 ? compositeItems : null));
138197
}
139198
else
140199
{
@@ -143,9 +202,8 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
143202
GetControlLayout(serializedInputBinding.path), serializedInputBinding.indexOfBinding)));
144203
}
145204
}
146-
147205
actionItems.Add(new TreeViewItemData<ActionOrBindingData>(id++,
148-
new ActionOrBindingData(true, action.name, action.expectedControlType), bindingItems));
206+
new ActionOrBindingData(true, action.name, action.expectedControlType), bindingItems.Count > 0 ? bindingItems : null));
149207
}
150208
return actionItems;
151209
}

0 commit comments

Comments
 (0)