public override void OnGUI(SerializedTypeDrawerData data, Rect position, SerializedProperty property, GUIContent label) { int idHash = 0; // By manually creating the control ID, we can keep the ID for the // label and button the same. This lets them be selected together // with the keyboard in the inspector, much like a normal popup. if (idHash == 0) { idHash = "SerializedTypeDrawer".GetHashCode(); } int id = GUIUtility.GetControlID(idHash, FocusType.Keyboard, position); if (m_ShowSimplifiedNames != ShowSimplifiedTypeNames) { m_ShowSimplifiedNames = ShowSimplifiedTypeNames; // NOTE Ideally UserSetting.ValueChanged event would exist and we would react to its changes. m_PropertyPathToOptions.Clear(); } Options options; if (!m_PropertyPathToOptions.TryGetValue(property.propertyPath, out options)) { var filterAttribute = Attribute.GetCustomAttribute(fieldInfo, typeof(SerializedTypeFilterAttributeBase), true) as SerializedTypeFilterAttributeBase; options = new Options(filterAttribute.BaseType, filterAttribute.HideAbstractTypes); m_PropertyPathToOptions[property.propertyPath] = options; } var typeNameProperty = property.FindPropertyRelative(k_TypeNamePath); int selectedIndex = ArrayUtility.IndexOf(options.assemblyQualifiedNames, typeNameProperty.stringValue); label = EditorGUI.BeginProperty(position, label, property); position = EditorGUI.PrefixLabel(position, id, label); GUIContent buttonText; if (selectedIndex <= 0 || selectedIndex >= options.assemblyQualifiedNames.Length) { buttonText = options.displayedOptions[0]; //"None" } else { buttonText = options.displayedOptions[selectedIndex]; } if (DropdownButton(id, position, buttonText)) { Action <int> onItemSelected = (i) => OnItemSelected(i, position, options, property, typeNameProperty); SearchablePopup.Show(position, options.displayedOptions, selectedIndex, onItemSelected); } if (data.HasChanged) { /* HACK: removing those EndChangeCheck() will make ImGUI unable to detect changes in the SerializedTypes * edited through the popup. There's probably something internal happening here, as * in the rest of the code there seems to already be an EndChangeCheck() for each BeginChangeCheck */ EditorGUI.EndChangeCheck(); EditorGUI.EndChangeCheck(); data.HasChanged = false; SetDataForProperty(property, data); typeNameProperty.stringValue = options.assemblyQualifiedNames[data.NewTypeIndex]; } EditorGUI.EndProperty(); }
public override void OnGUI(SerializedTypeDrawerData data, Rect position, SerializedProperty property, GUIContent label) { int idHash = 0; // By manually creating the control ID, we can keep the ID for the // label and button the same. This lets them be selected together // with the keyboard in the inspector, much like a normal popup. if (idHash == 0) { idHash = "SerializedTypeDrawer".GetHashCode(); } int id = GUIUtility.GetControlID(idHash, FocusType.Keyboard, position); if (m_ShowSimplifiedNames != ShowSimplifiedTypeNames) { m_ShowSimplifiedNames = ShowSimplifiedTypeNames; // NOTE Ideally UserSetting.ValueChanged event would exist and we would react to its changes. m_PropertyPathToOptions.Clear(); } var typeNameProperty = property.FindPropertyRelative(k_TypeNamePath); var assemblyQualifiedName = typeNameProperty.stringValue; Options options; if (!m_PropertyPathToOptions.TryGetValue(property.propertyPath, out options)) { var filterAttribute = Attribute.GetCustomAttribute(fieldInfo, typeof(SerializedTypeFilterAttributeBase), true) as SerializedTypeFilterAttributeBase; options = new Options(assemblyQualifiedName, filterAttribute.BaseType, filterAttribute.HideAbstractTypes); m_PropertyPathToOptions[property.propertyPath] = options; } var origBgColor = GUI.backgroundColor; label = EditorGUI.BeginProperty(position, label, property); position = EditorGUI.PrefixLabel(position, id, label); var resolvedType = Type.GetType(assemblyQualifiedName); if (resolvedType == null && assemblyQualifiedName.IsNotNullOrEmpty()) { GUI.backgroundColor = Color.red; } else if (resolvedType != null && resolvedType.AssemblyQualifiedName != assemblyQualifiedName) { // Resolved type's AQN different than the original AQN: for example, SceneView behaves like this when upgrading from 2019.4 // to 2020 or newer (moved from UnityEngine to UnityEngine.CoreModule assembly). GUI.backgroundColor = Color.yellow; } var selectedIndex = ArrayUtility.IndexOf(options.assemblyQualifiedNames, assemblyQualifiedName); if (selectedIndex < 0) { selectedIndex = 0; // Not Found } GUIContent buttonText = options.displayedOptions[selectedIndex]; if (DropdownButton(id, position, buttonText)) { Action <int> onItemSelected = (i) => OnItemSelected(i, position, options, property, typeNameProperty); SearchablePopup.Show(position, options.displayedOptions, selectedIndex, onItemSelected); } if (data.HasChanged) { /* HACK: removing those EndChangeCheck() will make ImGUI unable to detect changes in the SerializedTypes * edited through the popup. There's probably something internal happening here, as * in the rest of the code there seems to already be an EndChangeCheck() for each BeginChangeCheck */ EditorGUI.EndChangeCheck(); EditorGUI.EndChangeCheck(); data.HasChanged = false; SetDataForProperty(property, data); typeNameProperty.stringValue = options.assemblyQualifiedNames[data.NewTypeIndex]; } EditorGUI.EndProperty(); GUI.backgroundColor = origBgColor; }