Skip to content
Merged
2 changes: 1 addition & 1 deletion Assets/Tests/InputSystem.Editor/SelectorsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void GetActionsAsTreeViewData_ReturnsActionsAndBindingsAsTreeViewData()
var actionTwo = actionMap.AddAction("Action2", binding: "<Keyboard>/d");


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


Assert.That(treeViewData.Count, Is.EqualTo(2));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#if UNITY_EDITOR && UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using UnityEditor;

Expand Down Expand Up @@ -92,7 +91,6 @@ public InputActionsEditorState(
int selectedActionIndex = 0,
int selectedBindingIndex = 0,
SelectionType selectionType = SelectionType.Action,
Dictionary<(string, string), HashSet<int>> expandedBindingIndices = null,
InputControlScheme selectedControlScheme = default,
int selectedControlSchemeIndex = -1,
int selectedDeviceRequirementIndex = -1,
Expand All @@ -112,9 +110,6 @@ public InputActionsEditorState(
m_selectedControlSchemeIndex = selectedControlSchemeIndex;
m_selectedDeviceRequirementIndex = selectedDeviceRequirementIndex;

m_ExpandedCompositeBindings = expandedBindingIndices == null ?
new Dictionary<(string, string), HashSet<int>>() :
new Dictionary<(string, string), HashSet<int>>(expandedBindingIndices);
m_CutElements = cutElements;
}

Expand Down Expand Up @@ -201,12 +196,6 @@ public InputActionsEditorState(InputActionsEditorState other, SerializedObject a
m_ControlScheme = new InputControlScheme();
}

// Editor may leave these as null after domain reloads, so recreate them in that case.
// If they exist, we attempt to just preserve the same expanded items based on name for now for simplicity.
m_ExpandedCompositeBindings = other.m_ExpandedCompositeBindings == null ?
new Dictionary<(string, string), HashSet<int>>() :
new Dictionary<(string, string), HashSet<int>>(other.m_ExpandedCompositeBindings);

m_CutElements = other.cutElements;
}

Expand All @@ -218,7 +207,6 @@ public InputActionsEditorState With(
InputControlScheme? selectedControlScheme = null,
int? selectedControlSchemeIndex = null,
int? selectedDeviceRequirementIndex = null,
Dictionary<(string, string), HashSet<int>> expandedBindingIndices = null,
List<CutElement> cutElements = null)
{
return new InputActionsEditorState(
Expand All @@ -228,7 +216,6 @@ public InputActionsEditorState With(
selectedActionIndex ?? this.selectedActionIndex,
selectedBindingIndex ?? this.selectedBindingIndex,
selectionType ?? this.selectionType,
expandedBindingIndices ?? m_ExpandedCompositeBindings,

// Control schemes
selectedControlScheme ?? this.selectedControlScheme,
Expand All @@ -248,7 +235,6 @@ public InputActionsEditorState ClearCutElements()
selectedActionIndex,
selectedBindingIndex,
selectionType,
m_ExpandedCompositeBindings,
selectedControlScheme,
selectedControlSchemeIndex,
selectedDeviceRequirementIndex,
Expand All @@ -262,39 +248,6 @@ public SerializedProperty GetActionMapByName(string actionMapName)
.FirstOrDefault(p => p.FindPropertyRelative(nameof(InputActionMap.m_Name)).stringValue == actionMapName);
}

public InputActionsEditorState ExpandCompositeBinding(SerializedInputBinding binding)
{
var key = GetSelectedActionMapAndActionKey();

var expandedCompositeBindings = new Dictionary<(string, string), HashSet<int>>(m_ExpandedCompositeBindings);
if (!expandedCompositeBindings.TryGetValue(key, out var expandedStates))
{
expandedStates = new HashSet<int>();
expandedCompositeBindings.Add(key, expandedStates);
}

expandedStates.Add(binding.indexOfBinding);

return With(expandedBindingIndices: expandedCompositeBindings);
}

public InputActionsEditorState CollapseCompositeBinding(SerializedInputBinding binding)
{
var key = GetSelectedActionMapAndActionKey();

if (m_ExpandedCompositeBindings.ContainsKey(key) == false)
throw new InvalidOperationException("Trying to collapse a composite binding tree that was never expanded.");

// do the dance of C# immutability
var oldExpandedCompositeBindings = m_ExpandedCompositeBindings;
var expandedCompositeBindings = oldExpandedCompositeBindings.Keys.Where(dictKey => dictKey != key)
.ToDictionary(dictKey => dictKey, dictKey => oldExpandedCompositeBindings[dictKey]);
var newHashset = new HashSet<int>(m_ExpandedCompositeBindings[key].Where(index => index != binding.indexOfBinding));
expandedCompositeBindings.Add(key, newHashset);

return With(expandedBindingIndices: expandedCompositeBindings);
}

public InputActionsEditorState SelectAction(string actionName)
{
var actionMap = GetSelectedActionMap();
Expand Down Expand Up @@ -419,47 +372,11 @@ public readonly List<CutElement> GetCutElements()
return m_CutElements;
}

public ReadOnlyCollection<int> GetOrCreateExpandedState()
{
return new ReadOnlyCollection<int>(GetOrCreateExpandedStateInternal().ToList());
}

private HashSet<int> GetOrCreateExpandedStateInternal()
{
var key = GetSelectedActionMapAndActionKey();

if (m_ExpandedCompositeBindings.TryGetValue(key, out var expandedStates))
return expandedStates;

expandedStates = new HashSet<int>();
m_ExpandedCompositeBindings.Add(key, expandedStates);
return expandedStates;
}

internal (string, string) GetSelectedActionMapAndActionKey()
{
var selectedActionMap = GetSelectedActionMap();

var selectedAction = selectedActionMap
.FindPropertyRelative(nameof(InputActionMap.m_Actions))
.GetArrayElementAtIndex(selectedActionIndex);

var key = (
selectedActionMap.FindPropertyRelative(nameof(InputActionMap.m_Name)).stringValue,
selectedAction.FindPropertyRelative(nameof(InputAction.m_Name)).stringValue
);
return key;
}

private SerializedProperty GetSelectedActionMap()
{
return Selectors.GetActionMapAtIndex(serializedObject, selectedActionMapIndex)?.wrappedProperty;
}

/// <summary>
/// Expanded states for the actions tree view. These are stored per InputActionMap
/// </summary>
private readonly Dictionary<(string, string), HashSet<int>> m_ExpandedCompositeBindings;


private readonly InputControlScheme m_ControlScheme;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ internal class ActionsTreeView : ViewBase<ActionsTreeView.ViewState>
private bool m_RenameOnActionAdded;
private readonly CollectionViewSelectionChangeFilter m_ActionsTreeViewSelectionChangeFilter;

//save TreeView element id's of individual input actions and bindings to ensure saving of expanded state
private Dictionary<Guid, int> m_GuidToTreeViewId;

public ActionsTreeView(VisualElement root, StateContainer stateContainer)
: base(root, stateContainer)
{
Expand All @@ -38,7 +35,6 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
m_ActionsTreeView = root.Q<TreeView>("actions-tree-view");
//assign unique viewDataKey to store treeView states like expanded/collapsed items - make it unique to avoid conflicts with other TreeViews
m_ActionsTreeView.viewDataKey = $"InputActionTreeView_{stateContainer.assetGUID}";
m_GuidToTreeViewId = new Dictionary<Guid, int>();
m_ActionsTreeView.selectionType = UIElements.SelectionType.Single;
m_ActionsTreeView.makeItem = () => new InputActionsTreeViewItem();
m_ActionsTreeView.reorderable = true;
Expand Down Expand Up @@ -147,7 +143,7 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
CreateSelector(Selectors.GetActionsForSelectedActionMap, Selectors.GetActionMapCount,
(_, count, state) =>
{
var treeData = Selectors.GetActionsAsTreeViewData(state, m_GuidToTreeViewId);
var treeData = Selectors.GetActionsAsTreeViewData(state);
return new ViewState
{
treeViewData = treeData,
Expand Down Expand Up @@ -572,7 +568,7 @@ public ActionOrBindingData(bool isAction, string name, int actionMapIndex, bool

internal static partial class Selectors
{
public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewData(InputActionsEditorState state, Dictionary<Guid, int> idDictionary)
public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewData(InputActionsEditorState state)
{
var actionMapIndex = state.selectedActionMapIndex;
var controlSchemes = state.serializedObject.FindProperty(nameof(InputActionAsset.m_ControlSchemes));
Expand All @@ -591,12 +587,13 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
.ToList();

var actionItems = new List<TreeViewItemData<ActionOrBindingData>>();
var treeviewItemIDCounter = 0;
foreach (var action in actions)
{
var actionBindings = bindings.Where(spb => spb.action == action.name).ToList();
var bindingItems = new List<TreeViewItemData<ActionOrBindingData>>();
var actionId = new Guid(action.id);

for (var i = 0; i < actionBindings.Count; i++)
{
var serializedInputBinding = actionBindings[i];
Expand All @@ -619,7 +616,7 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
if (isVisible)
{
var name = GetHumanReadableCompositeName(nextBinding, state.selectedControlScheme, controlSchemes);
compositeItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(new Guid(nextBinding.id), idDictionary),
compositeItems.Add(new TreeViewItemData<ActionOrBindingData>(treeviewItemIDCounter++,
new ActionOrBindingData(isAction: false, name, actionMapIndex, isComposite: false,
isPartOfComposite: true, GetControlLayout(nextBinding.path), bindingIndex: nextBinding.indexOfBinding, isCut: state.IsBindingCut(actionMapIndex, nextBinding.indexOfBinding))));
}
Expand All @@ -637,36 +634,26 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa

var shouldCompositeBeVisible = !(compositeItems.Count == 0 && hasHiddenCompositeParts); //hide composite if all parts are hidden
if (shouldCompositeBeVisible)
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(inputBindingId, idDictionary),
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(treeviewItemIDCounter++,
new ActionOrBindingData(isAction: false, serializedInputBinding.name, actionMapIndex, isComposite: true, isPartOfComposite: false, action.expectedControlType, bindingIndex: serializedInputBinding.indexOfBinding, isCut: state.IsBindingCut(actionMapIndex, serializedInputBinding.indexOfBinding)),
compositeItems.Count > 0 ? compositeItems : null));
}
else
{
var isVisible = ShouldBindingBeVisible(serializedInputBinding, state.selectedControlScheme, state.selectedDeviceRequirementIndex);
if (isVisible)
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(inputBindingId, idDictionary),
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(treeviewItemIDCounter++,
new ActionOrBindingData(isAction: false, GetHumanReadableBindingName(serializedInputBinding, state.selectedControlScheme, controlSchemes), actionMapIndex,
isComposite: false, isPartOfComposite: false, GetControlLayout(serializedInputBinding.path), bindingIndex: serializedInputBinding.indexOfBinding, isCut: state.IsBindingCut(actionMapIndex, serializedInputBinding.indexOfBinding))));
}
}
var actionIndex = action.wrappedProperty.GetIndexOfArrayElement();
actionItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(actionId, idDictionary),
actionItems.Add(new TreeViewItemData<ActionOrBindingData>(treeviewItemIDCounter++,
new ActionOrBindingData(isAction: true, action.name, actionMapIndex, isComposite: false, isPartOfComposite: false, action.expectedControlType, actionIndex: actionIndex, isCut: state.IsActionCut(actionMapIndex, actionIndex)), bindingItems.Count > 0 ? bindingItems : null));
}
return actionItems;
}

private static int GetIdForGuid(Guid guid, Dictionary<Guid, int> idDictionary)
{
if (!idDictionary.TryGetValue(guid, out var id))
{
id = idDictionary.Values.Count > 0 ? idDictionary.Values.Max() + 1 : 0;
idDictionary.Add(guid, id);
}
return id;
}

private static string GetHumanReadableBindingName(SerializedInputBinding serializedInputBinding, InputControlScheme? currentControlScheme, SerializedProperty allControlSchemes)
{
var name = InputControlPath.ToHumanReadableString(serializedInputBinding.path);
Expand Down
Loading