Exemple #1
0
        /// <summary>
        /// Draws right-aligned toolbar paging buttons.
        /// </summary>
        public void DrawToolbarPagingButtons(ref Rect toolbarRect, bool showPaging, bool showItemCount, int btnWidth = 23)
        {
            if (this.prevRect.height == 0)
            {
                if (Event.current.type == EventType.Repaint)
                {
                    this.prevRect = toolbarRect;
                }

                return;
            }

            //var isRepaint = Event.current.type == EventType.Repaint;
            var drawPaging      = this.isEnabled && !this.IsExpanded && showPaging && this.pageCount > 1; // btnWith * 2
            var drawExpand      = this.isEnabled && this.pageCount > 1;                                   // btnWith
            var drawPagingField = drawPaging;                                                             // 40?

            // Expand
            if (drawExpand)
            {
                var btnRect = toolbarRect.AlignRight(btnWidth, true);
                toolbarRect.xMax = btnRect.xMin;
                if (GUI.Button(btnRect, GUIContent.none, SirenixGUIStyles.ToolbarButton))
                {
                    GUIHelper.RemoveFocusControl();
                    this.nextIsExpanded = !this.IsExpanded;
                }
                (this.IsExpanded ? EditorIcons.TriangleUp : EditorIcons.TriangleDown).Draw(btnRect, 16);
            }

            // Right
            if (drawPaging)
            {
                //if (this.IsOnLastPage && isRepaint) GUIHelper.PushGUIEnabled(false);
                var btnRect = toolbarRect.AlignRight(btnWidth, true);
                if (GUI.Button(btnRect, GUIContent.none, SirenixGUIStyles.ToolbarButton))
                {
                    GUIHelper.RemoveFocusControl();
                    if (Event.current.button == 1)
                    {
                        this.nextPageNumber = this.PageCount - 1;
                    }
                    else
                    {
                        this.nextPageNumber = this.currentPage + 1;

                        if (this.nextPageNumber >= this.pageCount)
                        {
                            this.nextPageNumber = 0;
                        }
                    }
                }
                EditorIcons.TriangleRight.Draw(btnRect, 16);
                //if (this.IsOnLastPage && isRepaint) GUIHelper.PopGUIEnabled();
                toolbarRect.xMax = btnRect.xMin;
            }

            // Paging field
            if (drawPagingField)
            {
                var pageCountLbl = "/ " + this.PageCount.ToString();
                var lblLength    = SirenixGUIStyles.Label.CalcSize(new GUIContent(pageCountLbl)).x;
                var lblRect      = toolbarRect.AlignRight(lblLength + 5, true);
                toolbarRect.xMax = lblRect.xMin;
                var fldRect = toolbarRect.AlignRight(lblLength, true);
                toolbarRect.xMax = fldRect.xMin;
                fldRect.xMin    += 4;
                fldRect.y       -= 1;
                GUI.Label(lblRect, pageCountLbl, SirenixGUIStyles.LabelCentered);

                var next = SirenixEditorGUI.SlideRectInt(lblRect, 0, this.CurrentPage);
                if (next != this.CurrentPage)
                {
                    this.nextPageNumber = next;
                }

                next = EditorGUI.IntField(fldRect.AlignCenterY(15), this.CurrentPage + 1) - 1;
                if (next != this.CurrentPage)
                {
                    this.nextPageNumber = next;
                }
            }

            // Left
            if (drawPaging)
            {
                //if (this.IsOnFirstPage && isRepaint) GUIHelper.PushGUIEnabled(false);
                var btnRect = toolbarRect.AlignRight(btnWidth, true);
                if (GUI.Button(btnRect, GUIContent.none, SirenixGUIStyles.ToolbarButton))
                {
                    GUIHelper.RemoveFocusControl();
                    if (Event.current.button == 1)
                    {
                        this.nextPageNumber = 0;
                    }
                    else
                    {
                        this.nextPageNumber = this.currentPage - 1;

                        if (this.nextPageNumber < 0)
                        {
                            this.nextPageNumber = this.pageCount - 1;
                        }
                    }
                }
                EditorIcons.TriangleLeft.Draw(btnRect, 16);
                //if (this.IsOnFirstPage && isRepaint) GUIHelper.PopGUIEnabled();
                toolbarRect.xMax = btnRect.xMin;
            }

            // Item Count
            if (showItemCount && Event.current.type != EventType.Layout)
            {
                var lbl     = new GUIContent(this.ElementCount == 0 ? "Empty" : this.ElementCount + " items");
                var width   = SirenixGUIStyles.LeftAlignedGreyMiniLabel.CalcSize(lbl).x + 5;
                var lblRect = toolbarRect.AlignRight(width);
                GUI.Label(lblRect, lbl, SirenixGUIStyles.LeftAlignedGreyMiniLabel);
                toolbarRect.xMax = lblRect.xMin;
            }

            if (Event.current.type == EventType.Repaint)
            {
                this.prevRect = toolbarRect;
            }
        }
        internal void Update()
        {
            this.lastSeenEvent = Event.current.type;

            this.SetCurrentDragAndDropMethod();

            if (this.lastSeenEvent == EventType.Repaint)
            {
                this.FinalizeDropObject();
            }

            if (Event.current.isMouse || Event.current.type == EventType.DragUpdated)
            {
                Rect screenSpaceRect;

                if (this.DragHandleRect.HasValue)
                {
                    screenSpaceRect = this.DragHandleRect.Value;
                }
                else
                {
                    screenSpaceRect = this.Rect;
                }

                Vector2 screenPos = GUIUtility.GUIToScreenPoint(new Vector2(screenSpaceRect.x, screenSpaceRect.y));
                screenSpaceRect.x = screenPos.x;
                screenSpaceRect.y = screenPos.y;

                this.IsHovering = screenSpaceRect.Contains(GUIUtility.GUIToScreenPoint(Event.current.mousePosition));
            }

            this.OnDragStarted = false;

            if (DragAndDropManager.IsDragInProgress == false)
            {
                if (Event.current.isMouse)
                {
                    if (this.IsHovering)
                    {
                        if (this.Enabled && Event.current.type == EventType.MouseDown == true && Event.current.button == 0)
                        {
                            this.isMouseDown            = true;
                            this.mouseDownPostionOffset = Event.current.mousePosition - new Vector2(this.Rect.x, this.Rect.y);
                            GUIHelper.RemoveFocusControl();
                            Event.current.Use();
                            DragAndDrop.PrepareStartDrag();
                        }

                        if (this.isMouseDown && Event.current.type == EventType.MouseDrag)
                        {
                            this.isDragging    = true;
                            this.OnDragStarted = true;
                            if (this.Object != null)
                            {
                                DragAndDrop.objectReferences = new UnityEngine.Object[0];
                                DragAndDrop.paths            = null;
                                DragAndDrop.SetGenericData(this.Object.GetType().Name, this.Object);
                                DragAndDrop.StartDrag("Odin Drag Operation");
                            }
                        }
                    }
                }
            }
            else
            {
                GUIHelper.RequestRepaint();
            }

            if (this.isDragging)
            {
                GUIHelper.RequestRepaint();

                DragAndDropManager.CurrentDraggingHandle = this;

                if (EditorWindow.mouseOverWindow != null)
                {
                    EditorWindow.mouseOverWindow.Focus();
                }

                if (DragAndDropManager.WasDragPerformed)
                {
                    this.IsReadyToBeClaimed = true;

                    if (DragAndDropManager.IsHoveringDropZone == false)
                    {
                        this.DropObject(DropEvents.Canceled);
                    }
                }
            }
            else
            {
                if (this.IsHovering)
                {
                    if (currentHoveringDragHandle == null || this.LayoutDepth >= currentHoveringDragHandle.LayoutDepth)
                    {
                        currentHoveringDragHandle = this;
                    }
                }
                else if (currentHoveringDragHandle == this)
                {
                    currentHoveringDragHandle = null;
                }

                this.IsHovering = currentHoveringDragHandle == this;
            }
        }
        /// <summary>
        /// Draws a objectpicker butter, in the given rect. This one is designed to look good on top of DrawDropZone().
        /// </summary>
        public static object ObjectPickerZone(Rect rect, object value, Type type, bool allowSceneObjects, int id)
        {
            var btnId        = GUIUtility.GetControlID(FocusType.Passive);
            var objectPicker = ObjectPicker.GetObjectPicker(type.FullName + "+" + btnId, type);
            var selectRect   = rect.AlignBottom(15).AlignCenter(45);
            var uObj         = value as UnityEngine.Object;

            selectRect.xMin = Mathf.Max(selectRect.xMin, rect.xMin);

            var hide = IsDragging || Event.current.type == EventType.Repaint && !rect.Contains(Event.current.mousePosition);

            if (hide)
            {
                GUIHelper.PushColor(new Color(0, 0, 0, 0));
                GUIHelper.PushGUIEnabled(false);
            }

            bool hideInspectorBtn = !hide && !(uObj);

            if (hideInspectorBtn)
            {
                GUIHelper.PushGUIEnabled(false);
                GUIHelper.PushColor(new Color(0, 0, 0, 0));
            }

            var inspectBtn = rect.AlignRight(14);

            inspectBtn.height = 14;
            SirenixEditorGUI.BeginDrawOpenInspector(inspectBtn, uObj, rect);
            SirenixEditorGUI.EndDrawOpenInspector(inspectBtn, uObj);

            if (hideInspectorBtn)
            {
                GUIHelper.PopColor();
                GUIHelper.PopGUIEnabled();
            }

            if (GUI.Button(selectRect, "select", SirenixGUIStyles.TagButton))
            {
                GUIHelper.RemoveFocusControl();
                objectPicker.ShowObjectPicker(allowSceneObjects, rect, false);
                Event.current.Use();
            }

            if (Event.current.keyCode == KeyCode.Return && Event.current.type == EventType.KeyDown && EditorGUIUtility.keyboardControl == id)
            {
                objectPicker.ShowObjectPicker(allowSceneObjects, rect, false);
                Event.current.Use();
            }

            if (hide)
            {
                GUIHelper.PopColor();
                GUIHelper.PopGUIEnabled();
            }

            if (objectPicker.IsReadyToClaim)
            {
                GUIHelper.RequestRepaint();
                GUI.changed = true;
                var newValue = objectPicker.ClaimObject();
                Event.current.Use();
                return(newValue);
            }

            if (Event.current.keyCode == KeyCode.Delete && Event.current.type == EventType.KeyDown && EditorGUIUtility.keyboardControl == id)
            {
                Event.current.Use();
                GUI.changed = true;
                return(null);
            }

            if (uObj && Event.current.type == EventType.MouseUp && rect.Contains(Event.current.mousePosition) && EditorGUIUtility.hotControl == id && Event.current.button == 0)
            {
                EditorGUIUtility.PingObject(uObj);
            }

            return(value);
        }
        /// <summary>
        /// A draggable zone for both Unity and non-unity objects.
        /// </summary>
        public static object DragZone(Rect rect, object value, Type type, bool allowMove, bool allowSwap, int id)
        {
            if (value == null)
            {
                return(null);
            }

            // Unity null
            if (typeof(UnityEngine.Object).IsAssignableFrom(value.GetType()) && !(value as UnityEngine.Object))
            {
                return(value);
            }

            var t           = Event.current.type;
            var isMouseOver = rect.Contains(Event.current.mousePosition);
            var unityObject = value as UnityEngine.Object;

            if (isMouseOver && t == EventType.MouseDown)
            {
                GUIHelper.RemoveFocusControl();
                GUIUtility.hotControl      = id;
                GUIUtility.keyboardControl = id;
                dragginObjects             = new object[] { };
                DragAndDrop.PrepareStartDrag();
                GUIHelper.RequestRepaint();
                isAccepted        = false;
                dropZoneObject    = null;
                draggingId        = 0;
                currentDragIsMove = false;
            }

            if (isAccepted && draggingId == id)
            {
                GUIHelper.RequestRepaint();
                GUI.changed = true;
                draggingId  = 0;

                // TODO: Validate drop zone object, and only return that if it's assignable from type.

                return(allowMove ? (allowSwap ? dropZoneObject : null) : value);
            }

            if (GUIUtility.hotControl != id)
            {
                return(value);
            }
            else if (t == EventType.MouseMove)
            {
                GUIHelper.RequestRepaint();
                draggingId = 0;
                DragAndDrop.PrepareStartDrag();
                DragAndDrop.objectReferences = new UnityEngine.Object[] { };
                //GUIHelper.RemoveFocusControl();
                dragginObjects    = new object[] { };
                currentDragIsMove = false;
            }

            if (Event.current.type == EventType.MouseDrag && isMouseOver && (DragAndDrop.objectReferences == null || DragAndDrop.objectReferences.Length == 0))
            {
                isAccepted     = false;
                dropZoneObject = null;
                draggingId     = id;
                DragAndDrop.StartDrag("Movable drag");
                if (unityObject)
                {
                    DragAndDrop.objectReferences = new UnityEngine.Object[] { unityObject };
                    dragginObjects = new object[] { };
                }
                else
                {
                    DragAndDrop.objectReferences = new UnityEngine.Object[] { };
                    dragginObjects = new object[] { value };
                }

                DragAndDrop.activeControlID = 0;
                currentDragIsMove           = allowMove;
                Event.current.Use();
                GUIHelper.RequestRepaint();
            }

            return(value);
        }
        /// <summary>
        /// A drop zone area for bot Unity and non-unity objects.
        /// </summary>
        public static object DropZone(Rect rect, object value, Type type, bool allowSceneObjects, int id)
        {
            if (rect.Contains(Event.current.mousePosition))
            {
                var t = Event.current.type;

                if (t == EventType.DragUpdated || t == EventType.DragPerform)
                {
                    object obj = null;

                    if (obj == null)
                    {
                        obj = dragginObjects.Where(x => x != null && x.GetType().InheritsFrom(type)).FirstOrDefault();
                    }
                    if (obj == null)
                    {
                        obj = DragAndDrop.objectReferences.Where(x => x != null && x.GetType().InheritsFrom(type)).FirstOrDefault();
                    }

                    if (type.InheritsFrom <Component>() || type.IsInterface)
                    {
                        if (obj == null)
                        {
                            obj = dragginObjects.OfType <GameObject>().Where(x => x != null).Select(x => x.GetComponent(type)).Where(x => x != null).FirstOrDefault();
                        }
                        if (obj == null)
                        {
                            obj = DragAndDrop.objectReferences.OfType <GameObject>().Where(x => x != null).Select(x => x.GetComponent(type)).Where(x => x != null).FirstOrDefault();
                        }
                    }

                    bool acceptsDrag = obj != null;

                    if (acceptsDrag && allowSceneObjects == false)
                    {
                        var uObj = (UnityEngine.Object)obj;
                        if (uObj != null)
                        {
                            if (typeof(Component).IsAssignableFrom(uObj.GetType()))
                            {
                                uObj = ((Component)uObj).gameObject;
                            }

                            acceptsDrag = EditorUtility.IsPersistent(uObj);
                        }
                    }

                    if (acceptsDrag)
                    {
                        isHoveringAcceptedDropZone = true;
                        bool move = Event.current.modifiers != EventModifiers.Control && draggingId != 0 && currentDragIsMove;
                        if (move)
                        {
                            DragAndDrop.visualMode = DragAndDropVisualMode.Move;
                        }
                        else
                        {
                            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                        }

                        Event.current.Use();
                        if (t == EventType.DragPerform)
                        {
                            if (!move)
                            {
                                draggingId = 0;
                            }

                            DragAndDrop.objectReferences = new UnityEngine.Object[] { };
                            DragAndDrop.AcceptDrag();
                            GUI.changed = true;
                            GUIHelper.RemoveFocusControl();
                            dragginObjects              = new object[] { };
                            currentDragIsMove           = false;
                            isAccepted                  = true;
                            dropZoneObject              = value;
                            DragAndDrop.activeControlID = 0;
                            GUIHelper.RequestRepaint();
                            return(obj);
                        }
                        else
                        {
                            DragAndDrop.activeControlID = id;
                        }
                    }
                    else
                    {
                        isHoveringAcceptedDropZone = false;
                        DragAndDrop.visualMode     = DragAndDropVisualMode.Rejected;
                    }
                }
            }

            return(value);
        }
        /// <summary>
        /// A drop zone area for bot Unity and non-unity objects.
        /// </summary>
        public static object DropZone(Rect rect, object value, Type type, bool allowSceneObjects, int id)
        {
            if (rect.Contains(Event.current.mousePosition))
            {
                var t = Event.current.type;

                if (t == EventType.DragUpdated || t == EventType.DragPerform)
                {
                    // This bit disables all dropzones inside the provided preventDropAreaRect.
                    //
                    // RootNode1
                    //    ChileNode1
                    //    ChileNode2
                    //       ChileNode2.1
                    //       ChileNode2.2
                    //    ChileNode3
                    // RootNode2
                    //
                    // If the RootNode has provided a preventDropAreaRect, then that means that the RootNode won't be able to be dragged into any of its child nodes.

                    if (preventDropAreaRect.Contains(new Vector2(rect.x, rect.y)) && preventDropAreaRect.Contains(new Vector2(rect.xMax, rect.yMax)))
                    {
                        return(value);
                    }

                    object obj = null;

                    if (obj == null)
                    {
                        obj = dragginObjects.Where(x => x != null && x.GetType().InheritsFrom(type)).FirstOrDefault();
                    }
                    if (obj == null)
                    {
                        obj = DragAndDrop.objectReferences.Where(x => x != null && x.GetType().InheritsFrom(type)).FirstOrDefault();
                    }

                    if (type.InheritsFrom <Component>() || type.IsInterface)
                    {
                        if (obj == null)
                        {
                            obj = dragginObjects.OfType <GameObject>().Where(x => x != null).Select(x => x.GetComponent(type)).Where(x => x != null).FirstOrDefault();
                        }
                        if (obj == null)
                        {
                            obj = DragAndDrop.objectReferences.OfType <GameObject>().Where(x => x != null).Select(x => x.GetComponent(type)).Where(x => x != null).FirstOrDefault();
                        }
                    }

                    bool acceptsDrag = obj != null;

                    if (acceptsDrag && allowSceneObjects == false)
                    {
                        var uObj = obj as UnityEngine.Object;
                        if (uObj != null)
                        {
                            if (typeof(Component).IsAssignableFrom(uObj.GetType()))
                            {
                                uObj = ((Component)uObj).gameObject;
                            }

                            acceptsDrag = EditorUtility.IsPersistent(uObj);
                        }
                    }

                    if (acceptsDrag)
                    {
                        hoveringAcceptedDropZone = id;
                        bool move = Event.current.modifiers != EventModifiers.Control && draggingId != 0 && currentDragIsMove;
                        if (move)
                        {
                            DragAndDrop.visualMode = DragAndDropVisualMode.Move;
                        }
                        else
                        {
                            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                        }

                        Event.current.Use();
                        if (t == EventType.DragPerform)
                        {
                            if (!move)
                            {
                                draggingId = 0;
                                //preventDropAreaRect = new Rect();
                            }

                            // Calling this here makes Unity crash on MacOS
                            // DragAndDrop.objectReferences = new UnityEngine.Object[] { };
                            DragAndDrop.AcceptDrag();
                            GUI.changed = true;
                            GUIHelper.RemoveFocusControl();
                            dragginObjects              = new object[] { };
                            currentDragIsMove           = false;
                            isAccepted                  = true;
                            dropZoneObject              = value;
                            preventDropAreaRect         = new Rect();
                            DragAndDrop.activeControlID = 0;
                            GUIHelper.RequestRepaint();
                            return(obj);
                        }
                        else
                        {
                            DragAndDrop.activeControlID = id;
                        }
                    }
                    else
                    {
                        hoveringAcceptedDropZone = 0;
                        DragAndDrop.visualMode   = DragAndDropVisualMode.Rejected;
                    }
                }
            }
            else
            {
                if (hoveringAcceptedDropZone == id)
                {
                    hoveringAcceptedDropZone = 0;
                }
            }

            return(value);
        }
        /// <summary>
        /// Draws a objectpicker button in the given rect. This one is designed to look good on top of DrawDropZone().
        /// </summary>
        public static object ObjectPickerZone(Rect rect, object value, Type type, bool allowSceneObjects, int id)
        {
            // TODO: btnId wasn't used, but the GetControlID call is probably still important.
            //var btnId = GUIUtility.GetControlID(FocusType.Passive);
            GUIUtility.GetControlID(FocusType.Passive);
            var objectPicker = ObjectPicker.GetObjectPicker(type.FullName + "+" + GUIHelper.CurrentWindowInstanceID.ToString() + "+" + id, type);
            var selectRect   = rect.AlignBottom(15).AlignCenter(45);
            var uObj         = value as UnityEngine.Object;

            selectRect.xMin = Mathf.Max(selectRect.xMin, rect.xMin);

            var hide = IsDragging || Event.current.type == EventType.Repaint && !rect.Contains(Event.current.mousePosition);

            if (hide)
            {
                GUIHelper.PushColor(new Color(0, 0, 0, 0));
                GUIHelper.PushGUIEnabled(false);
            }

            bool hideInspectorBtn = !hide && !(uObj);

            if (hideInspectorBtn)
            {
                GUIHelper.PushGUIEnabled(false);
                GUIHelper.PushColor(new Color(0, 0, 0, 0));
            }

            var inspectBtn = rect.AlignRight(14);

            inspectBtn.height = 14;
            SirenixEditorGUI.BeginDrawOpenInspector(inspectBtn, uObj, rect);
            SirenixEditorGUI.EndDrawOpenInspector(inspectBtn, uObj);

            if (hideInspectorBtn)
            {
                GUIHelper.PopColor();
                GUIHelper.PopGUIEnabled();
            }

            if (GUI.Button(selectRect, "select", SirenixGUIStyles.TagButton))
            {
                GUIHelper.RemoveFocusControl();
                objectPicker.ShowObjectPicker(value, allowSceneObjects, rect, false);
                Event.current.Use();
            }

            if (Event.current.keyCode == KeyCode.Return && Event.current.type == EventType.KeyDown && EditorGUIUtility.keyboardControl == id)
            {
                objectPicker.ShowObjectPicker(value, allowSceneObjects, rect, false);
                Event.current.Use();
            }

            if (hide)
            {
                GUIHelper.PopColor();
                GUIHelper.PopGUIEnabled();
            }

            if (objectPicker.IsReadyToClaim)
            {
                GUIHelper.RequestRepaint();
                GUI.changed = true;
                var newValue = objectPicker.ClaimObject();
                Event.current.Use();
                return(newValue);
            }

            if (objectPicker.IsPickerOpen && typeof(UnityEngine.Object).IsAssignableFrom(type))
            {
                return(objectPicker.CurrentSelectedObject);
            }

            if (Event.current.keyCode == KeyCode.Delete && Event.current.type == EventType.KeyDown && EditorGUIUtility.keyboardControl == id)
            {
                Event.current.Use();
                GUI.changed = true;
                return(null);
            }

            if (uObj && Event.current.rawType == EventType.MouseUp && rect.Contains(Event.current.mousePosition) && Event.current.button == 0)
            {
                // For components ping the attached game object instead, because then Unity can figure out to ping prefabs in the project window too.
                UnityEngine.Object pingObj = uObj;
                if (pingObj is Component)
                {
                    pingObj = (pingObj as Component).gameObject;
                }

                EditorGUIUtility.PingObject(pingObj);
            }

            return(value);
        }