Example #1
0
        private static void DrawObjectFieldMiniThumb(Rect position, int id, Object obj, GUIContent content)
        {
            GUIStyle thumbStyle = EditorStyles.objectFieldMiniThumb;

            position.width = EditorGUI.kObjectFieldMiniThumbnailWidth;
            EditorGUI.BeginHandleMixedValueContentColor();
            bool hover    = obj != null; // we use hover texture for enhancing the border if we have a reference
            bool on       = DragAndDrop.activeControlID == id;
            bool keyFocus = GUIUtility.keyboardControl == id;

            thumbStyle.Draw(position, hover, false, on, keyFocus);
            EditorGUI.EndHandleMixedValueContentColor();

            if (obj != null && !EditorGUI.showMixedValue)
            {
                Rect      thumbRect = new Rect(position.x + 1, position.y + 1, position.height - 2, position.height - 2); // subtract 1 px border
                Texture2D t2d       = content.image as Texture2D;
                if (t2d != null && t2d.alphaIsTransparency)
                {
                    EditorGUI.DrawTextureTransparent(thumbRect, t2d);
                }
                else
                {
                    EditorGUI.DrawPreviewTexture(thumbRect, content.image);
                }

                // Tooltip
                if (thumbRect.Contains(Event.current.mousePosition))
                {
                    GUI.Label(thumbRect, Search.Utils.GUIContentTemp(string.Empty, "Ctrl + Click to show preview"));
                }
            }
        }
Example #2
0
        private static void DrawObjectFieldLargeThumb(Rect position, int id, Object obj, GUIContent content)
        {
            GUIStyle thumbStyle = EditorStyles.objectFieldThumb;

            thumbStyle.Draw(position, GUIContent.none, id, DragAndDrop.activeControlID == id, position.Contains(Event.current.mousePosition));

            if (obj != null && !EditorGUI.showMixedValue)
            {
                Matrix4x4 guiMatrix = GUI.matrix; // Initial matrix is saved in order to be able to reset it to default
                bool      isSprite  = obj is Sprite;
                bool      alphaIsTransparencyTex2D = (obj is Texture2D && (obj as Texture2D).alphaIsTransparency);
                Rect      thumbRect = thumbStyle.padding.Remove(position);

                Texture2D t2d = AssetPreview.GetAssetPreview(obj);
                if (t2d != null)
                {
                    // A checkerboard background is drawn behind transparent textures (for visibility)
                    if (isSprite || t2d.alphaIsTransparency || alphaIsTransparencyTex2D)
                    {
                        GUI.DrawTexture(thumbRect, EditorGUI.transparentCheckerTexture, ScaleMode.StretchToFill, false);
                    }

                    // Draw asset preview (scaled to fit inside the frame)
                    GUIUtility.ScaleAroundPivot(thumbRect.size / position.size, thumbRect.position);
                    GUIStyle.none.Draw(thumbRect, t2d, false, false, false, false);
                    GUI.matrix = guiMatrix;
                }
                else
                {
                    // Preview not loaded -> Draw icon
                    if (isSprite || alphaIsTransparencyTex2D)
                    {
                        // A checkerboard background is drawn behind transparent textures (for visibility)
                        GUI.DrawTexture(thumbRect, EditorGUI.transparentCheckerTexture, ScaleMode.StretchToFill, false);
                        GUI.DrawTexture(thumbRect, content.image, ScaleMode.StretchToFill, true);
                    }
                    else
                    {
                        EditorGUI.DrawPreviewTexture(thumbRect, content.image);
                    }

                    // Keep repainting until the object field has a proper preview
                    HandleUtility.Repaint();
                }
            }
            else
            {
                GUIStyle s2 = thumbStyle.name + "Overlay";
                EditorGUI.BeginHandleMixedValueContentColor();

                s2.Draw(position, content, id);
                EditorGUI.EndHandleMixedValueContentColor();
            }
            GUIStyle s3 = thumbStyle.name + "Overlay2";

            s3.Draw(position, s_Select, id);
        }
Example #3
0
        static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, Object objBeingEdited, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidator validator, GUIStyle style, SearchContext context, SearchViewFlags searchViewFlags = SearchViewFlags.None)
        {
            if (validator == null)
            {
                validator = EditorGUI.ValidateObjectFieldAssignment;
            }
            if (property != null)
            {
                obj = property.objectReferenceValue;
            }
            Event     evt       = Event.current;
            EventType eventType = evt.type;

            // special case test, so we continue to ping/select objects with the object field disabled
            if (!GUI.enabled && Utils.IsGUIClipEnabled() && (Event.current.rawType == EventType.MouseDown))
            {
                eventType = Event.current.rawType;
            }

            bool hasThumbnail = EditorGUIUtility.HasObjectThumbnail(objType);

            // Determine visual type
            ObjectFieldVisualType visualType = ObjectFieldVisualType.IconAndText;

            if (hasThumbnail && position.height <= EditorGUI.kObjectFieldMiniThumbnailHeight && position.width <= EditorGUI.kObjectFieldMiniThumbnailWidth)
            {
                visualType = ObjectFieldVisualType.MiniPreview;
            }
            else if (hasThumbnail && position.height > EditorGUI.kSingleLineHeight)
            {
                visualType = ObjectFieldVisualType.LargePreview;
            }

            Vector2 oldIconSize = EditorGUIUtility.GetIconSize();

            if (visualType == ObjectFieldVisualType.IconAndText)
            {
                EditorGUIUtility.SetIconSize(new Vector2(12, 12));  // Have to be this small to fit inside a single line height ObjectField
            }
            else if (visualType == ObjectFieldVisualType.LargePreview)
            {
                EditorGUIUtility.SetIconSize(new Vector2(64, 64));
            }

            if ((eventType == EventType.MouseDown && Event.current.button == 1 || eventType == EventType.ContextClick) &&
                position.Contains(Event.current.mousePosition))
            {
                var actualObject = property != null ? property.objectReferenceValue : obj;
                var contextMenu  = new GenericMenu();

                if (EditorGUI.FillPropertyContextMenu(property, null, contextMenu) != null)
                {
                    contextMenu.AddSeparator("");
                }
                contextMenu.AddItem(Utils.GUIContentTemp("Properties..."), false, () => Utils.OpenPropertyEditor(actualObject));
                contextMenu.DropDown(position);
                Event.current.Use();
            }

            switch (eventType)
            {
            case EventType.DragExited:
                if (GUI.enabled)
                {
                    HandleUtility.Repaint();
                }

                break;

            case EventType.DragUpdated:
            case EventType.DragPerform:

                if (eventType == EventType.DragPerform)
                {
                    string errorString;
                    if (!ValidDroppedObject(DragAndDrop.objectReferences, objType, out errorString))
                    {
                        Object reference = DragAndDrop.objectReferences[0];
                        EditorUtility.DisplayDialog("Can't assign script", errorString, "OK");
                        break;
                    }
                }

                if (dropRect.Contains(Event.current.mousePosition) && GUI.enabled)
                {
                    Object[] references      = DragAndDrop.objectReferences;
                    Object   validatedObject = validator(references, objType, property, EditorGUI.ObjectFieldValidatorOptions.None);

                    if (validatedObject != null)
                    {
                        DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
                        if (eventType == EventType.DragPerform)
                        {
                            if (property != null)
                            {
                                property.objectReferenceValue = validatedObject;
                            }
                            else
                            {
                                obj = validatedObject;
                            }

                            GUI.changed = true;
                            DragAndDrop.AcceptDrag();
                            DragAndDrop.activeControlID = 0;
                        }
                        else
                        {
                            DragAndDrop.activeControlID = id;
                        }
                        Event.current.Use();
                    }
                }
                break;

            case EventType.MouseDown:
                if (position.Contains(Event.current.mousePosition) && Event.current.button == 0)
                {
                    // Get button rect for Object Selector
                    Rect buttonRect = GetButtonRect(visualType, position);

                    EditorGUIUtility.editingTextField = false;

                    if (buttonRect.Contains(Event.current.mousePosition))
                    {
                        if (GUI.enabled)
                        {
                            GUIUtility.keyboardControl = id;
                            ShowSearchPicker(context, searchViewFlags, property, property == null ? obj : null, id, evt, objType);
                        }
                    }
                    else
                    {
                        Object    actualTargetObject = property != null ? property.objectReferenceValue : obj;
                        Component com = actualTargetObject as Component;
                        if (com)
                        {
                            actualTargetObject = com.gameObject;
                        }
                        if (EditorGUI.showMixedValue)
                        {
                            actualTargetObject = null;
                        }

                        // One click shows where the referenced object is, or pops up a preview
                        if (Event.current.clickCount == 1)
                        {
                            GUIUtility.keyboardControl = id;

                            PingObjectOrShowPreviewOnClick(actualTargetObject, position);
                            evt.Use();
                        }
                        // Double click opens the asset in external app or changes selection to referenced object
                        else if (Event.current.clickCount == 2)
                        {
                            if (actualTargetObject)
                            {
                                AssetDatabase.OpenAsset(actualTargetObject);
                                evt.Use();
                                GUIUtility.ExitGUI();
                            }
                        }
                    }
                }
                break;

            case EventType.ExecuteCommand:
                string commandName = evt.commandName;
                if (commandName == k_PickerUpdatedCommand && s_LastPickerId == id && GUIUtility.keyboardControl == id && (property == null || !Utils.SerializedPropertyIsScript(property)))
                {
                    return(AssignSelectedObject(property, validator, objType, evt));
                }
                else if (commandName == k_PickerClosedCommand && s_LastPickerId == id && GUIUtility.keyboardControl == id)
                {
                    if (s_LastSelectionWasCanceled)
                    {
                        // User canceled object selection; don't apply
                        evt.Use();

                        // When we operate directly on objects, the undo system doesn't work.
                        // We added a hack that sets the s_LastSelectedItem to the original item
                        // when canceling with an object.
                        if (property == null)
                        {
                            return(s_LastSelectedItem);
                        }

                        break;
                    }

                    // When property is script, it is not assigned on update, so assign it on close
                    if (property != null && Utils.SerializedPropertyIsScript(property))
                    {
                        return(AssignSelectedObject(property, validator, objType, evt));
                    }

                    return(property != null ? property.objectReferenceValue : obj);
                }
                else if (Utils.IsCommandDelete(evt.commandName) && GUIUtility.keyboardControl == id)
                {
                    if (property != null)
                    {
                        property.objectReferenceValue = null;
                    }
                    else
                    {
                        obj = null;
                    }

                    GUI.changed = true;
                    evt.Use();
                }
                break;

            case EventType.ValidateCommand:
                if (Utils.IsCommandDelete(evt.commandName) && GUIUtility.keyboardControl == id)
                {
                    evt.Use();
                }
                break;

            case EventType.KeyDown:
                if (GUIUtility.keyboardControl == id)
                {
                    if (evt.keyCode == KeyCode.Backspace || (evt.keyCode == KeyCode.Delete && (evt.modifiers & EventModifiers.Shift) == 0))
                    {
                        if (property != null)
                        {
                            property.objectReferenceValue = null;
                        }
                        else
                        {
                            obj = null;
                        }

                        GUI.changed = true;
                        evt.Use();
                    }

                    // Apparently we have to check for the character being space instead of the keyCode,
                    // otherwise the Inspector will maximize upon pressing space.
                    if (Utils.MainActionKeyForControl(evt, id))
                    {
                        ShowSearchPicker(context, searchViewFlags, property, property == null ? obj : null, id, evt, objType);
                    }
                }
                break;

            case EventType.Repaint:
                GUIContent temp;
                if (EditorGUI.showMixedValue)
                {
                    temp = EditorGUI.mixedValueContent;
                }
                else
                {
                    // If obj or objType are both null, we have to rely on
                    // property.objectReferenceStringValue to display None/Missing and the
                    // correct type. But if not, EditorGUIUtility.ObjectContent is more reliable.
                    // It can take a more specific object type specified as argument into account,
                    // and it gets the icon at the same time.
                    if (obj == null && objType == null && property != null)
                    {
                        temp = Utils.GUIContentTemp(Utils.SerializedPropertyObjectReferenceStringValue(property));
                    }
                    else
                    {
                        // In order for ObjectContext to be able to distinguish between None/Missing,
                        // we need to supply an instanceID. For some reason, getting the instanceID
                        // from property.objectReferenceValue is not reliable, so we have to
                        // explicitly check property.objectReferenceInstanceIDValue if a property exists.
                        if (property != null)
                        {
                            temp = Utils.ObjectContent(obj, objType, property.objectReferenceInstanceIDValue);
                        }
                        else
                        {
                            temp = EditorGUIUtility.ObjectContent(obj, objType);
                        }
                    }

                    if (property != null)
                    {
                        if (obj != null)
                        {
                            Object[] references = { obj };
                            if (EditorSceneManager.preventCrossSceneReferences && EditorGUI.CheckForCrossSceneReferencing(obj, property.serializedObject.targetObject))
                            {
                                if (!EditorApplication.isPlaying)
                                {
                                    temp = s_SceneMismatch;
                                }
                                else
                                {
                                    temp.text = temp.text + string.Format(" ({0})", EditorGUI.GetGameObjectFromObject(obj).scene.name);
                                }
                            }
                            else if (validator(references, objType, property, EditorGUI.ObjectFieldValidatorOptions.ExactObjectTypeValidation) == null)
                            {
                                temp = s_TypeMismatch;
                            }
                        }
                    }
                }

                switch (visualType)
                {
                case ObjectFieldVisualType.IconAndText:
                    EditorGUI.BeginHandleMixedValueContentColor();
                    style.Draw(position, temp, id, DragAndDrop.activeControlID == id, position.Contains(Event.current.mousePosition));

                    Rect buttonRect = Utils.objectFieldButton.margin.Remove(GetButtonRect(visualType, position));
                    Utils.objectFieldButton.Draw(buttonRect, GUIContent.none, id, DragAndDrop.activeControlID == id, buttonRect.Contains(Event.current.mousePosition));
                    EditorGUI.EndHandleMixedValueContentColor();
                    break;

                case ObjectFieldVisualType.LargePreview:
                    DrawObjectFieldLargeThumb(position, id, obj, temp);
                    break;

                case ObjectFieldVisualType.MiniPreview:
                    DrawObjectFieldMiniThumb(position, id, obj, temp);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                break;
            }

            EditorGUIUtility.SetIconSize(oldIconSize);

            return(obj);
        }