@@ -26,6 +26,9 @@ internal class ActionsTreeView : ViewBase<ActionsTreeView.ViewState>
2626 private bool m_RenameOnActionAdded ;
2727 private readonly CollectionViewSelectionChangeFilter m_ActionsTreeViewSelectionChangeFilter ;
2828
29+ //save TreeView element id's of individual input actions and bindings to ensure saving of expanded state
30+ private Dictionary < Guid , int > m_GuidToTreeViewId ;
31+
2932 public ActionsTreeView ( VisualElement root , StateContainer stateContainer )
3033 : base ( root , stateContainer )
3134 {
@@ -35,6 +38,7 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
3538 m_ActionsTreeView = root . Q < TreeView > ( "actions-tree-view" ) ;
3639 //assign unique viewDataKey to store treeView states like expanded/collapsed items - make it unique to avoid conflicts with other TreeViews
3740 m_ActionsTreeView . viewDataKey = $ "InputActionTreeView_{ stateContainer . assetGUID } ";
41+ m_GuidToTreeViewId = new Dictionary < Guid , int > ( ) ;
3842 m_ActionsTreeView . selectionType = UIElements . SelectionType . Single ;
3943 m_ActionsTreeView . makeItem = ( ) => new InputActionsTreeViewItem ( ) ;
4044 m_ActionsTreeView . reorderable = true ;
@@ -143,7 +147,7 @@ public ActionsTreeView(VisualElement root, StateContainer stateContainer)
143147 CreateSelector ( Selectors . GetActionsForSelectedActionMap , Selectors . GetActionMapCount ,
144148 ( _ , count , state ) =>
145149 {
146- var treeData = Selectors . GetActionsAsTreeViewData ( state ) ;
150+ var treeData = Selectors . GetActionsAsTreeViewData ( state , m_GuidToTreeViewId ) ;
147151 return new ViewState
148152 {
149153 treeViewData = treeData ,
@@ -568,7 +572,7 @@ public ActionOrBindingData(bool isAction, string name, int actionMapIndex, bool
568572
569573 internal static partial class Selectors
570574 {
571- public static List < TreeViewItemData < ActionOrBindingData > > GetActionsAsTreeViewData ( InputActionsEditorState state )
575+ public static List < TreeViewItemData < ActionOrBindingData > > GetActionsAsTreeViewData ( InputActionsEditorState state , Dictionary < Guid , int > idDictionary )
572576 {
573577 var actionMapIndex = state . selectedActionMapIndex ;
574578 var controlSchemes = state . serializedObject . FindProperty ( nameof ( InputActionAsset . m_ControlSchemes ) ) ;
@@ -587,13 +591,12 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
587591 . ToList ( ) ;
588592
589593 var actionItems = new List < TreeViewItemData < ActionOrBindingData > > ( ) ;
590- var treeviewItemIDCounter = 0 ;
591594 foreach ( var action in actions )
592595 {
593596 var actionBindings = bindings . Where ( spb => spb . action == action . name ) . ToList ( ) ;
594597 var bindingItems = new List < TreeViewItemData < ActionOrBindingData > > ( ) ;
595598 var actionId = new Guid ( action . id ) ;
596-
599+
597600 for ( var i = 0 ; i < actionBindings . Count ; i ++ )
598601 {
599602 var serializedInputBinding = actionBindings [ i ] ;
@@ -616,7 +619,7 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
616619 if ( isVisible )
617620 {
618621 var name = GetHumanReadableCompositeName ( nextBinding , state . selectedControlScheme , controlSchemes ) ;
619- compositeItems . Add ( new TreeViewItemData < ActionOrBindingData > ( treeviewItemIDCounter ++ ,
622+ compositeItems . Add ( new TreeViewItemData < ActionOrBindingData > ( GetIdForGuid ( new Guid ( nextBinding . id ) , idDictionary ) ,
620623 new ActionOrBindingData ( isAction : false , name , actionMapIndex , isComposite : false ,
621624 isPartOfComposite : true , GetControlLayout ( nextBinding . path ) , bindingIndex : nextBinding . indexOfBinding , isCut : state . IsBindingCut ( actionMapIndex , nextBinding . indexOfBinding ) ) ) ) ;
622625 }
@@ -634,26 +637,39 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa
634637
635638 var shouldCompositeBeVisible = ! ( compositeItems . Count == 0 && hasHiddenCompositeParts ) ; //hide composite if all parts are hidden
636639 if ( shouldCompositeBeVisible )
637- bindingItems . Add ( new TreeViewItemData < ActionOrBindingData > ( treeviewItemIDCounter ++ ,
640+ bindingItems . Add ( new TreeViewItemData < ActionOrBindingData > ( GetIdForGuid ( inputBindingId , idDictionary ) ,
638641 new ActionOrBindingData ( isAction : false , serializedInputBinding . name , actionMapIndex , isComposite : true , isPartOfComposite : false , action . expectedControlType , bindingIndex : serializedInputBinding . indexOfBinding , isCut : state . IsBindingCut ( actionMapIndex , serializedInputBinding . indexOfBinding ) ) ,
639642 compositeItems . Count > 0 ? compositeItems : null ) ) ;
640643 }
641644 else
642645 {
643646 var isVisible = ShouldBindingBeVisible ( serializedInputBinding , state . selectedControlScheme , state . selectedDeviceRequirementIndex ) ;
644647 if ( isVisible )
645- bindingItems . Add ( new TreeViewItemData < ActionOrBindingData > ( treeviewItemIDCounter ++ ,
648+ bindingItems . Add ( new TreeViewItemData < ActionOrBindingData > ( GetIdForGuid ( inputBindingId , idDictionary ) ,
646649 new ActionOrBindingData ( isAction : false , GetHumanReadableBindingName ( serializedInputBinding , state . selectedControlScheme , controlSchemes ) , actionMapIndex ,
647650 isComposite : false , isPartOfComposite : false , GetControlLayout ( serializedInputBinding . path ) , bindingIndex : serializedInputBinding . indexOfBinding , isCut : state . IsBindingCut ( actionMapIndex , serializedInputBinding . indexOfBinding ) ) ) ) ;
648651 }
649652 }
650653 var actionIndex = action . wrappedProperty . GetIndexOfArrayElement ( ) ;
651- actionItems . Add ( new TreeViewItemData < ActionOrBindingData > ( treeviewItemIDCounter ++ ,
654+ actionItems . Add ( new TreeViewItemData < ActionOrBindingData > ( GetIdForGuid ( actionId , idDictionary ) ,
652655 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 ) ) ;
653656 }
654657 return actionItems ;
655658 }
656659
660+ private static int GetIdForGuid ( Guid guid , Dictionary < Guid , int > idDictionary )
661+ {
662+ //This method is used to ensure that the same Guid always gets the same id
663+ //We use getHashCode instead of a counter, as we cannot guarantee that the same Guid will always be added in the same order
664+ //There is a tiny chance of a collision, but it is it does happen it will only affect the expanded state of the tree view
665+ if ( ! idDictionary . TryGetValue ( guid , out var id ) )
666+ {
667+ id = guid . GetHashCode ( ) ; //idDictionary.Values.Count > 0 ? idDictionary.Values.Max() + 1 : 0;
668+ idDictionary . Add ( guid , id ) ;
669+ }
670+ return id ;
671+ }
672+
657673 private static string GetHumanReadableBindingName ( SerializedInputBinding serializedInputBinding , InputControlScheme ? currentControlScheme , SerializedProperty allControlSchemes )
658674 {
659675 var name = InputControlPath . ToHumanReadableString ( serializedInputBinding . path ) ;
0 commit comments