Exemplo n.º 1
0
        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;
        }