/// Must be drawn before DefaultProperty in order to receive input
    public static void DrawSelectionButtonForManagedReference(this SerializedProperty property,
                                                              Rect position, IEnumerable <Func <Type, bool> > filters = null)
    {
        //var backgroundColor = new Color(0f, 0.7f, 0.7f, 1f);
        var backgroundColor = new Color(0.1f, 0.45f, 0.8f, 1f);
        //var backgroundColor = GUI.backgroundColor;

        var buttonPosition = position;

        buttonPosition.x     += EditorGUIUtility.labelWidth + 1 * EditorGUIUtility.standardVerticalSpacing;
        buttonPosition.width  = position.width - EditorGUIUtility.labelWidth - 1 * EditorGUIUtility.standardVerticalSpacing;
        buttonPosition.height = EditorGUIUtility.singleLineHeight;

        var storedIndent = EditorGUI.indentLevel;

        EditorGUI.indentLevel = 0;
        var storedColor = GUI.backgroundColor;

        GUI.backgroundColor = backgroundColor;


        var names        = SerializeReferenceTypeNameUtility.GetSplitNamesFromTypename(property.managedReferenceFullTypename);
        var className    = string.IsNullOrEmpty(names.ClassName) ? "Null (Assign)" : names.ClassName;
        var assemblyName = names.AssemblyName;

        if (GUI.Button(buttonPosition, new GUIContent(className, className + "  ( " + assemblyName + " )")))
        {
            property.ShowContextMenuForManagedReference(filters);
        }

        GUI.backgroundColor   = storedColor;
        EditorGUI.indentLevel = storedIndent;
    }
    /// Purpose.
    /// This is generic selection menu.
    /// Filtering.
    /// You can add substring filter here to filter by search string.
    /// As well ass type or interface restrictions.
    /// As well as any custom restriction that is based on input type.
    /// And it will be performed on each Appropriate type found by TypeCache.
    public static void ShowContextMenuForManagedReference(this SerializedProperty property, IEnumerable <Func <Type, bool> > filters = null)
    {
        var context = new GenericMenu();

        FillContextMenu();
        context.ShowAsContext();

        void FillContextMenu()
        {
            context.AddItem(new GUIContent("Null"), false, MakeNull);
            var realPropertyType = SerializeReferenceTypeNameUtility.GetRealTypeFromTypename(property.managedReferenceFieldTypename);

            if (realPropertyType == null)
            {
                Debug.LogError("Can not get type from");
                return;
            }

            var types = TypeCache.GetTypesDerivedFrom(realPropertyType);

            foreach (var type in types)
            {
                // Skips unity engine Objects (because they are not serialized by SerializeReference)
                if (type.IsSubclassOf(typeof(UnityEngine.Object)))
                {
                    continue;
                }
                // Skip abstract classes because they should not be instantiated
                if (type.IsAbstract)
                {
                    continue;
                }
                if (FilterTypeByFilters(filters, type) == false)
                {
                    continue;
                }

                AddContextMenu(type, context);
            }

            void MakeNull()
            {
                property.serializedObject.Update();
                property.managedReferenceValue = null;
                property.serializedObject.ApplyModifiedPropertiesWithoutUndo(); // undo is bugged for now
            }

            void AddContextMenu(Type type, GenericMenu genericMenuContext)
            {
                var assemblyName = type.Assembly.ToString().Split('(', ',')[0];
                var entryName    = type.Name + "  ( " + assemblyName + " )";

                genericMenuContext.AddItem(new GUIContent(entryName), false, AssignNewInstanceOfType, type);
            }

            void AssignNewInstanceOfType(object typeAsObject)
            {
                var type     = (Type)typeAsObject;
                var instance = Activator.CreateInstance(type);

                property.serializedObject.Update();
                property.managedReferenceValue = instance;
                property.serializedObject.ApplyModifiedPropertiesWithoutUndo(); // undo is bugged for now
            }

            bool FilterTypeByFilters(IEnumerable <Func <Type, bool> > filters_, Type type) =>
            filters_.All(f => f.Invoke(type));
        }
    }