Skip to content

Commit 91be281

Browse files
authored
FIX: Avoid nullrefs from right-clicking when there's no Action Maps (ISXB-833). (#1898)
Also stop "Add Action" / pasting an action being options when there are no Action Maps.
1 parent 2c4e532 commit 91be281

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ however, it has to be formatted properly to pass verification tests.
1010

1111
## [Unreleased] - YYYY-MM-DD
1212

13+
### Fixed
14+
- NullReferenceException thrown when right-clicking an empty Action Map list in Input Actions Editor windows [ISXB-833](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-833).
15+
1316
## [1.8.1] - 2024-03-14
1417

1518
### Fixed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public ActionMapsView(VisualElement root, StateContainer stateContainer)
6767
m_AddActionMapButton.clicked += AddActionMap;
6868

6969
ContextMenu.GetContextMenuForActionMapsEmptySpace(this, root.Q<VisualElement>("rclick-area-to-add-new-action-map"));
70+
// Only bring up this context menu for the List when it's empty, so we can treat it like right-clicking the empty space:
71+
ContextMenu.GetContextMenuForActionMapsEmptySpace(this, m_ListView, onlyShowIfListIsEmpty: true);
7072
}
7173

7274
void OnDroppedHandler(int mapIndex)
@@ -154,6 +156,11 @@ internal void AddActionMap()
154156
m_EnterRenamingMode = true;
155157
}
156158

159+
internal int GetMapCount()
160+
{
161+
return m_ListView.itemsSource.Count;
162+
}
163+
157164
private void OnExecuteCommand(ExecuteCommandEvent evt)
158165
{
159166
var selectedItem = m_ListView.GetRootElementForIndex(m_ListView.selectedIndex);
@@ -218,7 +225,8 @@ private void OnPointerDown(PointerDownEvent evt)
218225
if (evt.button == (int)MouseButton.RightMouse && evt.clickCount == 1)
219226
{
220227
var actionMap = (evt.target as VisualElement).GetFirstAncestorOfType<InputActionMapsTreeViewItem>();
221-
m_ListView.SetSelection(actionMap.parent.IndexOf(actionMap));
228+
if (actionMap != null)
229+
m_ListView.SetSelection(actionMap.parent.IndexOf(actionMap));
222230
}
223231
}
224232

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace UnityEngine.InputSystem.Editor
1818
/// </summary>
1919
internal class ActionsTreeView : ViewBase<ActionsTreeView.ViewState>
2020
{
21+
private readonly ListView m_ActionMapsListView;
2122
private readonly TreeView m_ActionsTreeView;
2223
private readonly Button m_AddActionButton;
2324
private readonly ScrollView m_PropertiesScrollview;
@@ -31,6 +32,7 @@ internal class ActionsTreeView : ViewBase<ActionsTreeView.ViewState>
3132
public ActionsTreeView(VisualElement root, StateContainer stateContainer)
3233
: base(root, stateContainer)
3334
{
35+
m_ActionMapsListView = root.Q<ListView>("action-maps-list-view");
3436
m_AddActionButton = root.Q<Button>("add-new-action-button");
3537
m_PropertiesScrollview = root.Q<ScrollView>("properties-scrollview");
3638
m_ActionsTreeView = root.Q<TreeView>("actions-tree-view");
@@ -122,6 +124,8 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
122124

123125
ContextMenu.GetContextMenuForActionListView(this, m_ActionsTreeView, m_ActionsTreeView.parent);
124126
ContextMenu.GetContextMenuForActionsEmptySpace(this, m_ActionsTreeView, root.Q<VisualElement>("rclick-area-to-add-new-action"));
127+
// Only bring up this context menu for the Tree when it's empty, so we can treat it like right-clicking the empty space:
128+
ContextMenu.GetContextMenuForActionsEmptySpace(this, m_ActionsTreeView, m_ActionsTreeView, onlyShowIfTreeIsEmpty: true);
125129

126130
m_ActionsTreeViewSelectionChangeFilter = new CollectionViewSelectionChangeFilter(m_ActionsTreeView);
127131
m_ActionsTreeViewSelectionChangeFilter.selectedIndicesChanged += (_) =>
@@ -374,6 +378,11 @@ private void ChangeActionOrCompositName(ActionOrBindingData data, string newName
374378
Dispatch(Commands.ChangeCompositeName(data.actionMapIndex, data.bindingIndex, newName));
375379
}
376380

381+
internal int GetMapCount()
382+
{
383+
return m_ActionMapsListView.itemsSource.Count;
384+
}
385+
377386
private void OnExecuteCommand(ExecuteCommandEvent evt)
378387
{
379388
if (m_ActionsTreeView.selectedItem == null)

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

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,20 @@ public static void GetContextMenuForActionMapItem(ActionMapsView mapView, InputA
4747

4848
// Add "Add Action Map" option to empty space under the ListView. Matches with old IMGUI style (ISX-1519).
4949
// Include Paste here as well, since it makes sense for adding ActionMaps.
50-
public static void GetContextMenuForActionMapsEmptySpace(ActionMapsView mapView, VisualElement listView)
50+
public static void GetContextMenuForActionMapsEmptySpace(ActionMapsView mapView, VisualElement element, bool onlyShowIfListIsEmpty = false)
5151
{
5252
_ = new ContextualMenuManipulator(menuEvent =>
5353
{
54-
var copiedAction = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction);
55-
if (CopyPasteHelper.HasPastableClipboardData(typeof(InputActionMap)))
56-
menuEvent.menu.AppendAction(paste_String, _ => mapView.PasteItems(copiedAction));
54+
if (!onlyShowIfListIsEmpty || mapView.GetMapCount() == 0)
55+
{
56+
var copiedAction = CopyPasteHelper.GetCopiedClipboardType() == typeof(InputAction);
57+
if (CopyPasteHelper.HasPastableClipboardData(typeof(InputActionMap)))
58+
menuEvent.menu.AppendAction(paste_String, _ => mapView.PasteItems(copiedAction));
5759

58-
menuEvent.menu.AppendSeparator();
59-
menuEvent.menu.AppendAction(add_Action_Map_String, _ => mapView.AddActionMap());
60-
}) { target = listView };
60+
menuEvent.menu.AppendSeparator();
61+
menuEvent.menu.AppendAction(add_Action_Map_String, _ => mapView.AddActionMap());
62+
}
63+
}) { target = element };
6164
}
6265

6366
#endregion
@@ -77,17 +80,19 @@ public static void GetContextMenuForActionListView(ActionsTreeView actionsTreeVi
7780

7881
// Add "Add Action" option to empty space under the TreeView. Matches with old IMGUI style (ISX-1519).
7982
// Include Paste here as well, since it makes sense for Actions; thus users would expect it for Bindings too.
80-
public static void GetContextMenuForActionsEmptySpace(ActionsTreeView actionsTreeView, TreeView treeView, VisualElement target)
83+
public static void GetContextMenuForActionsEmptySpace(ActionsTreeView actionsTreeView, TreeView treeView, VisualElement target, bool onlyShowIfTreeIsEmpty = false)
8184
{
8285
_ = new ContextualMenuManipulator(menuEvent =>
8386
{
84-
var item = treeView.GetItemDataForIndex<ActionOrBindingData>(treeView.selectedIndex);
85-
var hasPastableData = CopyPasteHelper.HasPastableClipboardData(item.isAction ? typeof(InputAction) : typeof(InputBinding));
86-
if (hasPastableData)
87-
menuEvent.menu.AppendAction(paste_String, _ => actionsTreeView.PasteItems());
87+
if (actionsTreeView.GetMapCount() > 0 && (!onlyShowIfTreeIsEmpty || treeView.GetTreeCount() == 0))
88+
{
89+
var item = treeView.GetItemDataForIndex<ActionOrBindingData>(treeView.selectedIndex);
90+
if (CopyPasteHelper.HasPastableClipboardData(item.isAction ? typeof(InputAction) : typeof(InputBinding)))
91+
menuEvent.menu.AppendAction(paste_String, _ => actionsTreeView.PasteItems());
8892

89-
menuEvent.menu.AppendSeparator();
90-
menuEvent.menu.AppendAction(add_Action_String, _ => actionsTreeView.AddAction());
93+
menuEvent.menu.AppendSeparator();
94+
menuEvent.menu.AppendAction(add_Action_String, _ => actionsTreeView.AddAction());
95+
}
9196
}) { target = target };
9297
}
9398

0 commit comments

Comments
 (0)