Search Unity

When I type, why does my Drawer input lost focus and the scrollbar jump to a different spot?

Discussion in 'Immediate Mode GUI (IMGUI)' started by AcademyOfFetishes, Mar 22, 2019.

  1. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    I've got this drawer that seemed to work fine, but when my list of properties get too long, typing in one of the fields makes the inspector scroll up and sometimes lose focus? Here's a gif of it happening:



    Whenever I type into an input that's near the bottom, the scroll bar jumps like I've described above.

    Here's the drawer:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5. [CustomPropertyDrawer(typeof(CharacterAccessory))]
    6. public class CharacterAccessoryDrawer : PropertyDrawer
    7. {
    8.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    9.     {
    10.         EditorGUI.BeginProperty(position, label, property);
    11.         var indent = EditorGUI.indentLevel;
    12.         EditorGUI.indentLevel = 1;
    13.         SerializedProperty nameProperty = property.FindPropertyRelative("name");
    14.         SerializedProperty spritesProperty = property.FindPropertyRelative("sprites");
    15.         SerializedProperty unlockableProperty = property.FindPropertyRelative("unlockable");
    16.         SerializedProperty topProperty = property.FindPropertyRelative("top");
    17.         SerializedProperty bottomProperty = property.FindPropertyRelative("bottom");
    18.         SerializedProperty ankleProperty = property.FindPropertyRelative("ankle");
    19.         SerializedProperty neckProperty = property.FindPropertyRelative("neck");
    20.         var yPosition = position.y;
    21.         var nameRect = new Rect(position.x, yPosition, 175, EditorGUI.GetPropertyHeight(nameProperty));
    22.         var spritesRect = new Rect(position.x + 180, yPosition, position.width - 155, EditorGUI.GetPropertyHeight(spritesProperty));
    23.         yPosition += EditorGUI.GetPropertyHeight(nameProperty) + EditorGUI.GetPropertyHeight(spritesProperty);
    24.         var unlockableRect = new Rect(position.x, yPosition, position.width, EditorGUI.GetPropertyHeight(unlockableProperty));
    25.         yPosition += EditorGUI.GetPropertyHeight(unlockableProperty);
    26.         var xPosition = position.x;
    27.         var neckRect = new Rect(xPosition, yPosition, 90, EditorGUI.GetPropertyHeight(neckProperty));
    28.         xPosition += 80;
    29.         var topRect = new Rect(xPosition, yPosition, 90, EditorGUI.GetPropertyHeight(topProperty));
    30.         xPosition += 80;
    31.         var bottomRect = new Rect(xPosition, yPosition, 90, EditorGUI.GetPropertyHeight(bottomProperty));
    32.         xPosition += 80;
    33.         var ankleRect = new Rect(xPosition, yPosition, 90, EditorGUI.GetPropertyHeight(ankleProperty));
    34.         EditorGUI.PropertyField(nameRect, nameProperty, GUIContent.none);
    35.         EditorGUI.PropertyField(spritesRect, spritesProperty, true);
    36.         EditorGUI.PropertyField(unlockableRect, unlockableProperty, true);
    37.         var labelWidth = EditorGUIUtility.labelWidth;
    38.         EditorGUIUtility.labelWidth = 70;
    39.         EditorGUI.PropertyField(neckRect, neckProperty, new GUIContent("Neck"));
    40.         EditorGUI.PropertyField(topRect, topProperty, new GUIContent("Top"));
    41.         EditorGUI.PropertyField(bottomRect, bottomProperty, new GUIContent("Bottom"));
    42.         EditorGUI.PropertyField(ankleRect, ankleProperty, new GUIContent("Ankle"));
    43.         EditorGUIUtility.labelWidth = labelWidth;
    44.         EditorGUI.indentLevel = indent;
    45.         EditorGUI.EndProperty();
    46.     }
    47.     public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    48.     {
    49.         float totalHeight = 0;
    50.         totalHeight += EditorGUI.GetPropertyHeight(property.FindPropertyRelative("sprites"));
    51.         totalHeight += EditorGUI.GetPropertyHeight(property.FindPropertyRelative("top"));
    52.         totalHeight += EditorGUI.GetPropertyHeight(property.FindPropertyRelative("unlockable"));
    53.         totalHeight += 30;
    54.         return totalHeight;
    55.     }
    56. }
    Here's how the class looks:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System.Linq;
    6.  
    7. [Serializable]
    8. public class CharacterAccessory
    9. {
    10.     public string name;
    11.     public List<GameObject> sprites;
    12.     public Unlockable unlockable;
    13.     public bool top;
    14.     public bool bottom;
    15.     public bool ankle;
    16.     public bool neck;
    17.  
    18.     public void SetActive(bool active)
    19.     {
    20.         sprites.ForEach(s => s.SetActive(active));
    21.     }
    22.  
    23.     public bool IsWearing()
    24.     {
    25.         return sprites.Any(s => s.activeSelf);
    26.     }
    27.  
    28.     public Dictionary<string, bool> GetSlots()
    29.     {
    30.         Dictionary<string, bool> slots = new Dictionary<string, bool>
    31.         {
    32.             ["top"] = top,
    33.             ["bottom"] = bottom,
    34.             ["ankle"] = ankle,
    35.             ["neck"] = neck
    36.         };
    37.  
    38.         return slots;
    39.     }
    40. }
    Notice there's an Unlockable class there? That has it's own drawer, too:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. [Serializable]
    6. public class Unlockable
    7. {
    8.     public int successCount;
    9.     public NeedData needData;
    10. }
    And here's how the UnlockableDrawer looks:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEditor;
    4. using UnityEngine;
    5.  
    6. [CustomPropertyDrawer(typeof(Unlockable))]
    7. public class UnlockableDrawer : PropertyDrawer
    8. {
    9.     public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    10.     {
    11.         EditorGUI.BeginProperty(position, label, property);
    12.  
    13.         var indent = EditorGUI.indentLevel;
    14.         EditorGUI.indentLevel = 1;
    15.  
    16.         SerializedProperty successCountProperty = property.FindPropertyRelative("successCount");
    17.         SerializedProperty needDataProperty = property.FindPropertyRelative("needData");
    18.  
    19.         float xPosition = position.x;
    20.         var labelPosition = new Rect(xPosition, position.y, 80, EditorGUI.GetPropertyHeight(successCountProperty));
    21.         xPosition += 90;
    22.         var successCountRect = new Rect(xPosition, position.y, 140, EditorGUI.GetPropertyHeight(successCountProperty));
    23.         xPosition += 150;
    24.         var needDataRect = new Rect(xPosition, position.y, 230, EditorGUI.GetPropertyHeight(needDataProperty));
    25.  
    26.         var labelWidth = EditorGUIUtility.labelWidth;
    27.         EditorGUIUtility.labelWidth = 110;
    28.         EditorGUI.LabelField(labelPosition, new GUIContent("Unlockable"));
    29.         EditorGUI.PropertyField(successCountRect, successCountProperty, new GUIContent("Success Count:"));
    30.         EditorGUIUtility.labelWidth = 90;
    31.         EditorGUI.PropertyField(needDataRect, needDataProperty, new GUIContent("Need Data:"));
    32.         EditorGUIUtility.labelWidth = labelWidth;
    33.  
    34.         EditorGUI.indentLevel = indent;
    35.  
    36.         EditorGUI.EndProperty();
    37.     }
    38.  
    39. }
    I've confirmed that if I comment out both drawers, it doesn't happen anymore, but if I leave either one on (or both), it does.
     
    Last edited: Mar 22, 2019
  2. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    I tried a whole bunch of things, including creating a fresh project and trying this code in there. I noticed the problem didn't happen in the fresh project. I started installing some of the same packages as the original to see if that would break it. It didn't. The last thing I was going to try was delete my Library directory. After that, everything worked correctly.
     
  3. AkshayVats

    AkshayVats

    Joined:
    Jun 19, 2013
    Posts:
    4
    This is happening to me as well, with a custom property drawer (with DrawIf to be exact). But your solution is not clear to me, what library directory are you talking about?
     
  4. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,323
    The Library folder is located next to the Assets folder of your project.
    https://docs.unity3d.com/Manual/BehindtheScenes.html

    If it is deleted it causes all assets in the project to be reimported, which can sometimes help get rid of bugs if the temporary cached files contain corrupted data.
     
  5. AkshayVats

    AkshayVats

    Joined:
    Jun 19, 2013
    Posts:
    4
    Thanks SisusCo and AcademyOfFetishes. This resolved the issue!
    :)
     
    SisusCo likes this.