Skip to content

Commit 59d5736

Browse files
authored
FIX: TreeView tracking of collapse/expanded states (ISX-1626) (#1775)
* enabled TreeView tracking of collapse/expanded states * added changelog
1 parent 7e7d40e commit 59d5736

File tree

5 files changed

+33
-9
lines changed

5 files changed

+33
-9
lines changed

Assets/Tests/InputSystem.Editor/SelectorsTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// UITK TreeView is not supported in earlier versions
22
// Therefore the UITK version of the InputActionAsset Editor is not available on earlier Editor versions either.
33
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
4+
using System;
5+
using System.Collections.Generic;
46
using System.Linq;
57
using NUnit.Framework;
68
using UnityEngine;
@@ -22,7 +24,7 @@ public void GetActionsAsTreeViewData_ReturnsActionsAndBindingsAsTreeViewData()
2224
var actionTwo = actionMap.AddAction("Action2", binding: "<Keyboard>/d");
2325

2426

25-
var treeViewData = Selectors.GetActionsAsTreeViewData(TestData.EditorStateWithAsset(asset).Generate());
27+
var treeViewData = Selectors.GetActionsAsTreeViewData(TestData.EditorStateWithAsset(asset).Generate(), new Dictionary<Guid, int>());
2628

2729

2830
Assert.That(treeViewData.Count, Is.EqualTo(2));

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ however, it has to be formatted properly to pass verification tests.
3333
- Fixed case [ISXB-580](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-580) (UI Submit / Cancel not working with Switch Pro controller) by adding "Submit" & "Cancel" usages to the Switch Pro controller input controls.
3434
- Fixed an issue where undoing deletion of Action Maps did not restore Actions correctly.
3535
- Fixed case [ISXB-628](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-628) (OnIMECompositionChange does not return an empty string on accept when using Microsoft IME) by clarifying expectations and intended usage for the IME composition change event.
36+
- Fixed case [ISX-1626](https://jira.unity3d.com/browse/ISX-1626) where the expanded/collapsed state of items in the input action editor was not properly saved between rebuilds of the UI.
3637
- Fixed case [ISX-1668] (The Profiler shows incorrect data and spams the console with "Missing Profiler.EndSample" errors when there is an Input System Component in Scene).
3738
- Fixed [ISX-1661](https://jira.unity3d.com/browse/ISX-1661) where undoing duplications of action maps caused console errors
3839
- Fix for BindingSyntax `WithInteraction()` which was incorrectly using processors.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public SerializedInputAction(SerializedProperty serializedProperty)
1212
// serialized fields and make sure they're present?
1313
wrappedProperty = serializedProperty ?? throw new ArgumentNullException(nameof(serializedProperty));
1414

15+
id = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Id)).stringValue;
1516
name = serializedProperty.FindPropertyRelative(nameof(InputAction.m_Name)).stringValue;
1617
expectedControlType = ReadExpectedControlType(serializedProperty);
1718
type = (InputActionType)serializedProperty.FindPropertyRelative(nameof(InputAction.m_Type)).intValue;
@@ -22,6 +23,7 @@ public SerializedInputAction(SerializedProperty serializedProperty)
2223
expectedControlTypeTooltip = serializedProperty.FindPropertyRelative(nameof(InputAction.m_ExpectedControlType)).GetTooltip();
2324
}
2425

26+
public string id { get; }
2527
public string name { get; }
2628
public string expectedControlType { get; }
2729
public InputActionType type { get; }

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public SerializedInputBinding(SerializedProperty serializedProperty)
1818
{
1919
wrappedProperty = serializedProperty ?? throw new ArgumentNullException(nameof(serializedProperty));
2020

21+
id = serializedProperty.FindPropertyRelative("m_Id").stringValue;
2122
name = serializedProperty.FindPropertyRelative("m_Name").stringValue;
2223
path = serializedProperty.FindPropertyRelative("m_Path").stringValue;
2324
interactions = serializedProperty.FindPropertyRelative("m_Interactions").stringValue;
@@ -38,6 +39,7 @@ public SerializedInputBinding(SerializedProperty serializedProperty)
3839
}
3940

4041
public string name { get; }
42+
public string id { get; }
4143
public string path { get; }
4244
public string interactions { get; }
4345
public string processors { get; }

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

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,18 @@ internal class ActionsTreeView : ViewBase<ActionsTreeView.ViewState>
2222
private bool m_RenameOnActionAdded;
2323
private readonly CollectionViewSelectionChangeFilter m_ActionsTreeViewSelectionChangeFilter;
2424

25+
//save TreeView element id's of individual input actions and bindings to ensure saving of expanded state
26+
private Dictionary<Guid, int> m_GuidToTreeViewId;
27+
2528
public ActionsTreeView(VisualElement root, StateContainer stateContainer)
2629
: base(stateContainer)
2730
{
2831
m_Root = root;
2932

3033
m_ActionsTreeView = m_Root.Q<TreeView>("actions-tree-view");
34+
//assign unique viewDataKey to store treeView states like expanded/collapsed items - make it unique to avoid conflicts with other TreeViews
35+
m_ActionsTreeView.viewDataKey = "InputActionTreeView " + stateContainer.GetState().serializedObject.targetObject.GetInstanceID();
36+
m_GuidToTreeViewId = new Dictionary<Guid, int>();
3137
m_ActionsTreeView.selectionType = UIElements.SelectionType.Single;
3238
m_ActionsTreeView.makeItem = () => new InputActionsTreeViewItem();
3339
m_ActionsTreeView.bindItem = (e, i) =>
@@ -127,7 +133,7 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
127133
CreateSelector(Selectors.GetActionsForSelectedActionMap, Selectors.GetActionMapCount,
128134
(_, count, state) =>
129135
{
130-
var treeData = Selectors.GetActionsAsTreeViewData(state);
136+
var treeData = Selectors.GetActionsAsTreeViewData(state, m_GuidToTreeViewId);
131137
return new ViewState
132138
{
133139
treeViewData = treeData,
@@ -305,7 +311,7 @@ public ActionOrBindingData(bool isAction, string name, int actionMapIndex, bool
305311

306312
internal static partial class Selectors
307313
{
308-
public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewData(InputActionsEditorState state)
314+
public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewData(InputActionsEditorState state, Dictionary<Guid, int> idDictionary)
309315
{
310316
var actionMapIndex = state.selectedActionMapIndex;
311317
var controlSchemes = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes));
@@ -323,16 +329,17 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
323329
.Select(sp => new SerializedInputBinding(sp))
324330
.ToList();
325331

326-
var id = 0;
327332
var actionItems = new List<TreeViewItemData<ActionOrBindingData>>();
328333
foreach (var action in actions)
329334
{
330335
var actionBindings = bindings.Where(spb => spb.action == action.name).ToList();
331336
var bindingItems = new List<TreeViewItemData<ActionOrBindingData>>();
337+
var actionId = new Guid(action.id);
332338

333339
for (var i = 0; i < actionBindings.Count; i++)
334340
{
335341
var serializedInputBinding = actionBindings[i];
342+
var inputBindingId = new Guid(serializedInputBinding.id);
336343

337344
if (serializedInputBinding.isComposite)
338345
{
@@ -343,8 +350,8 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
343350
var isVisible = ShouldBindingBeVisible(nextBinding, state.selectedControlScheme);
344351
if (isVisible)
345352
{
346-
var name = GetHumanReadableCompositeName(nextBinding, state.selectedControlScheme, controlSchemes);
347-
compositeItems.Add(new TreeViewItemData<ActionOrBindingData>(id++,
353+
var name = GetHumanReadableCompositeName(nextBinding, state.selectedControlScheme, controlSchemes); var compositeBindingId = new Guid(nextBinding.id);
354+
compositeItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(new Guid(nextBinding.id), idDictionary),
348355
new ActionOrBindingData(false, name, actionMapIndex, false,
349356
GetControlLayout(nextBinding.path), nextBinding.indexOfBinding)));
350357
}
@@ -355,25 +362,35 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
355362
nextBinding = actionBindings[i];
356363
}
357364
i--;
358-
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(id++,
365+
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(inputBindingId, idDictionary),
359366
new ActionOrBindingData(false, serializedInputBinding.name, actionMapIndex, true, action.expectedControlType, serializedInputBinding.indexOfBinding),
360367
compositeItems.Count > 0 ? compositeItems : null));
361368
}
362369
else
363370
{
364371
var isVisible = ShouldBindingBeVisible(serializedInputBinding, state.selectedControlScheme);
365372
if (isVisible)
366-
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(id++,
373+
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(inputBindingId, idDictionary),
367374
new ActionOrBindingData(false, GetHumanReadableBindingName(serializedInputBinding, state.selectedControlScheme, controlSchemes), actionMapIndex,
368375
false, GetControlLayout(serializedInputBinding.path), serializedInputBinding.indexOfBinding)));
369376
}
370377
}
371-
actionItems.Add(new TreeViewItemData<ActionOrBindingData>(id++,
378+
actionItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(actionId, idDictionary),
372379
new ActionOrBindingData(true, action.name, actionMapIndex, false, action.expectedControlType), bindingItems.Count > 0 ? bindingItems : null));
373380
}
374381
return actionItems;
375382
}
376383

384+
private static int GetIdForGuid(Guid guid, Dictionary<Guid, int> idDictionary)
385+
{
386+
if (!idDictionary.TryGetValue(guid, out var id))
387+
{
388+
id = idDictionary.Values.Count > 0 ? idDictionary.Values.Max() + 1 : 0;
389+
idDictionary.Add(guid, id);
390+
}
391+
return id;
392+
}
393+
377394
private static string GetHumanReadableBindingName(SerializedInputBinding serializedInputBinding, InputControlScheme? currentControlScheme, SerializedProperty allControlSchemes)
378395
{
379396
var name = InputControlPath.ToHumanReadableString(serializedInputBinding.path);

0 commit comments

Comments
 (0)