Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

ReorderableList and focused Element

Discussion in 'Editor & General Support' started by tribaleur, Apr 8, 2020.

  1. tribaleur

    tribaleur

    Joined:
    Jan 19, 2017
    Posts:
    34
    Hello,

    I'm using a reorderableList for a custom Editor and when i edit a element of the list, the selected item doesn't change. It's a problem because this can cause possible mistake when trying to delete an element.

    Here what is the problem :
    upload_2020-4-8_22-58-42.png

    My Custom editor script :
    Code (CSharp):
    1. [CustomEditor(typeof(MyCustomClass), true)]
    2.     public class testeditor : Editor{
    3.  
    4.         public ReorderableList _listDrawer;
    5.         private MyCustomClass _myClass;
    6.  
    7.         public void OnEnable () {
    8.             this._myClass = (MyCustomClass) target;
    9.  
    10.             this._listDrawer = new ReorderableList(_myClass.list, typeof(FeatureType));
    11.             this._listDrawer.drawHeaderCallback += this.DrawHeader;
    12.             this._listDrawer.drawElementCallback += this.DrawElement;
    13.         }
    14.                
    15.         public void OnDisable () {
    16.             this._listDrawer.drawHeaderCallback -= this.DrawHeader;
    17.             this._listDrawer.drawElementCallback -= this.DrawElement;
    18.         }
    19.  
    20.         public override void OnInspectorGUI () {
    21.             this._listDrawer.DoLayoutList();
    22.         }
    23.  
    24.         #region METHODES ____________________________________________________________
    25.  
    26.         /// <summary>
    27.         /// Draw the header of the list
    28.         /// </summary>
    29.         /// <param name="rect">the actual position</param>
    30.         protected virtual void DrawHeader(Rect rect){
    31.             GUI.Label(rect, "Liste Test");
    32.         }
    33.  
    34.    
    35.         /// <summary>
    36.         /// Draws one element of the list
    37.         /// </summary>
    38.         /// <param name="rect">The actual position in the editor</param>
    39.         /// <param name="index">The index element of the list</param>
    40.         /// <param name="active">Is the element active ?</param>
    41.         /// <param name="focused">Is the element focused ?</param>
    42.         protected void DrawElement (Rect rect, int index, bool active, bool focused) {
    43.             FeatureType currentItem = (FeatureType) _myClass.list[index];
    44.            
    45.             if (currentItem != null) {
    46.                 EditorGUI.BeginChangeCheck();
    47.  
    48.                 currentItem.Num = EditorGUI.LongField(new Rect(rect.x, rect.y, 45, rect.height), currentItem.Num);
    49.                 currentItem.Name = EditorGUI.TextField(new Rect (rect.x + 60, rect.y, 150,rect.height), currentItem.Name);
    50.  
    51.                 EditorGUI.EndChangeCheck();
    52.             }
    53.         }
    54.         #endregion
    55.     }
    MyCustomClass.cs :
    Code (CSharp):
    1. [Serializable]
    2.     public class MyCustomClass : MonoBehaviour{
    3.         [SerializeField]
    4.         public List<FeatureType> list = new List<FeatureType>();
    5.     }
    FeatureType.cs :
    Code (CSharp):
    1. [Serializable]
    2.     public class FeatureType{
    3.         public long Num;
    4.         public string Name;
    5.        
    6.     }
    Do you have an idea where the problem is ?
     
  2. tribaleur

    tribaleur

    Joined:
    Jan 19, 2017
    Posts:
    34
    Hello again,

    I found a solution by using element focus name.
    I change my editor to set a name to every elements of my list. Then after draw the list, if one element is focused, i change the list index according to this element index.

    Here my change in the custom editor :
    Code (CSharp):
    1. [CustomEditor(typeof(MyCustomClass), true)]
    2.     public class testeditor : Editor{
    3.         // EDIT *** : used to name each element of the list
    4.         private const string C_LIST_NAME = "MyList";
    5.         private const string C_ELEMENT_DEFAULT_NAME = "element-";
    6.  
    7.         public ReorderableList _listDrawer;
    8.         private MyCustomClass _myClass;
    9.  
    10.         public void OnEnable () {
    11.             this._myClass = (MyCustomClass) target;
    12.  
    13.             this._listDrawer = new ReorderableList(_myClass.list, typeof(FeatureType));
    14.             this._listDrawer.drawHeaderCallback += this.DrawHeader;
    15.             this._listDrawer.drawElementCallback += this.DrawElement;
    16.         }
    17.                
    18.         public void OnDisable () {
    19.             this._listDrawer.drawHeaderCallback -= this.DrawHeader;
    20.             this._listDrawer.drawElementCallback -= this.DrawElement;
    21.         }
    22.  
    23.         public override void OnInspectorGUI () {
    24.             this._listDrawer.DoLayoutList();
    25.             this.OnElementFocusedHandler(); // EDIT *** : According the list index to it's element focused
    26.         }
    27.  
    28.         #region METHODES ____________________________________________________________
    29.  
    30.         /// <summary>
    31.         /// Draw the header of the list
    32.         /// </summary>
    33.         /// <param name="rect">the actual position</param>
    34.         protected virtual void DrawHeader(Rect rect){
    35.             GUI.Label(rect, "Liste Test");
    36.         }
    37.  
    38.    
    39.         /// <summary>
    40.         /// Draws one element of the list
    41.         /// </summary>
    42.         /// <param name="rect">The actual position in the editor</param>
    43.         /// <param name="index">The index element of the list</param>
    44.         /// <param name="active">Is the element active ?</param>
    45.         /// <param name="focused">Is the element focused ?</param>
    46.         protected void DrawElement (Rect rect, int index, bool active, bool focused) {
    47.             FeatureType currentItem = (FeatureType) _myClass.list[index];
    48.            
    49.             if (currentItem != null) {
    50.                 EditorGUI.BeginChangeCheck();
    51.                 GUI.SetNextControlName("Num." + C_LIST_NAME + "." + C_ELEMENT_DEFAULT_NAME + index.ToString());
    52.                 currentItem.Num = EditorGUI.LongField(new Rect(rect.x, rect.y, 45, rect.height), currentItem.Num);
    53.                 GUI.SetNextControlName("Name." + C_LIST_NAME + "." + C_ELEMENT_DEFAULT_NAME + index.ToString());
    54.                 currentItem.Name = EditorGUI.TextField(new Rect (rect.x + 60, rect.y, 150,rect.height), currentItem.Name);
    55.  
    56.                 EditorGUI.EndChangeCheck();
    57.             }
    58.         }
    59.  
    60.         // EDIT *** : to handle the focused element
    61.         /// <summary>
    62.         /// According the list index to it's focused element
    63.         /// </summary>
    64.         public void OnElementFocusedHandler () {
    65.             string currentFocusedName = GUI.GetNameOfFocusedControl();
    66.             // Check if the current focused element is in our list
    67.             if (currentFocusedName.Contains( C_LIST_NAME + "." + C_ELEMENT_DEFAULT_NAME)) {
    68.                 // Change the index if the current focused element have an one
    69.                 string[] controlNameElements = currentFocusedName.Split(new char[]{'-'});
    70.                 if(controlNameElements.Length > 1) { this._listDrawer.index = Int32.Parse(controlNameElements[1]); }              
    71.             }
    72.         }
    73.         #endregion
    74.     }
    I'm not sure that it's the best way to avoid this problem, but it works. If you have better idea you'll be welcom ;)