public static void Open([NotNull] IInspector inspector, [NotNull] List <PopupMenuItem> rootItems, [NotNull] Dictionary <string, PopupMenuItem> groupsByLabel, [NotNull] Dictionary <string, PopupMenuItem> itemsByLabel, [CanBeNull] List <PopupMenuItem> tickedItems, bool canTickMultipleItems, Rect clickedItemRect, [NotNull] Action <PopupMenuItem> onMenuItemClicked, [CanBeNull] Action onClosed, GUIContent label, [CanBeNull] IDrawer subject)
        {
                        #if DEV_MODE && SAFE_MODE
            Debug.Assert(rootItems.TrueForAll(item => item.parent == null));
            Debug.Assert(groupsByLabel.Select(pair => pair.Value).ToList().TrueForAll(item => item.IsGroup));
            Debug.Assert(itemsByLabel.Select(pair => pair.Value).ToList().TrueForAll(item => !item.IsGroup));
            Debug.Assert(itemsByLabel.Count > 0);
            Debug.Assert(groupsByLabel.Count > 0 || rootItems.Count == itemsByLabel.Count);
                        #endif

                        #if DEV_MODE || PROFILE_POWER_INSPECTOR
            Profiler.BeginSample("PopupMenuManager.Open");
                        #endif

            lastmenuOpenedForDrawer    = subject;
            lastmenuOpenedForInspector = inspector;

            if (OnPopupMenuOpening != null)
            {
                OnPopupMenuOpening(rootItems, subject);
            }

            var unrollPos = clickedItemRect;

            // menu should open underneath the clicked item
            //unrollPos.y += clickedItemRect.height;

            // add inspector y-axis position to open position so that if this is a split view
            // the menu is opened with the correct offset
            unrollPos.y += inspector.State.WindowRect.y;

                        #if DEV_MODE && DEBUG_OPEN
            Debug.Log(inspector + " WindowRect.y=" + inspector.State.WindowRect.y + ", subject=" + (subject == null?"null":subject.ToString()));;
                        #endif

            var inspectorDrawer = inspector.InspectorDrawer;

            // when converting unroll position to screen space,
            // if menu is opening for Drawer inside the inspector viewport,
            // then we need to consider things like current scroll amounts
            // of the view
            if (subject != null)
            {
                // Not sure where why this offset is needed. Perhaps EditorWindows
                // introduce some padding to the position values?
                unrollPos.y += 8f;

                // if menu was opened outside the current view rect of the viewport
                // (e.g. Add Component menu was opened via a shortcut key) then
                // adjust the opening position so that it doesn't get opened outside
                // the bounds of the window (alt solution would be to always scroll
                // down to the button before opening the menu)
                if (inspector.IsOutsideViewport(unrollPos))
                {
                                        #if DEV_MODE
                    Debug.LogWarning(unrollPos + " Outside Viewport. Maybe you want to scroll to show the target (" + subject + ") before opening the menu?");
                                        #endif
                    //unrollPosScreenSpace.y = inspectorDrawer.position.y + inspectorDrawer.position.height - PopupMenu.TotalMaxHeightWithNavigationBar;
                    unrollPos.y = inspectorDrawer.position.height - PopupMenu.TotalMaxHeightWithNavigationBar;
                }
                else
                {
                                        #if DEV_MODE
                    Debug.Log("<color=green>" + unrollPos + " Not Outside Viewport. Adding inspectorDrawer.pos.y (" + inspectorDrawer.position.y + ") - scrollPos.y (" + inspector.State.ScrollPos.y + ") + 68f</color>");
                                        #endif
                    unrollPos.y += inspectorDrawer.position.y - inspector.State.ScrollPos.y + 15f;
                }

                var screenHeight = Screen.currentResolution.height;

                // If there's not enough screen estate to draw the menu below target position then draw it above.
                if (unrollPos.y + PopupMenu.TotalMaxHeightWithNavigationBar > screenHeight)
                {
                                        #if DEV_MODE
                    Debug.Log("<color=red>Not enough space to draw below. screenHeight=" + screenHeight + ", unrollPos.y=" + unrollPos + ", TotalMaxHeightWithNavigationBar=" + PopupMenu.TotalMaxHeightWithNavigationBar + "</color>");
                                        #endif
                    unrollPos.y -= PopupMenu.TotalMaxHeightWithNavigationBar + clickedItemRect.height + 2f;
                }

                if (clickedItemRect.width < PopupMenu.MinWidth)
                {
                    // if menu width is too small, roll it open towards the left
                    // this is so that when controls are clicked, the menu is less likely to expand
                    // outside the bounds of the inspector, which would look ugly and could result
                    // int the menu clipping outside the screen bounds
                    float width = PopupMenu.MinWidth;
                    unrollPos.x     = inspectorDrawer.position.x + clickedItemRect.xMax - width;
                    unrollPos.width = width;
                }
                else
                {
                    float width = Mathf.Round(clickedItemRect.width);
                    unrollPos.x     = inspectorDrawer.position.x + unrollPos.x;
                    unrollPos.width = width;
                }
            }
            // if menu is being opened from outside the inspector viewport
            // then converting to screen space is as simple as adding
            // the screenspace positions of the inspector drawer to it
            else
            {
                //unrollPos.x += inspectorDrawer.position.x;

                // Not sure where why this offset is needed. Perhaps EditorWindows
                // introduce some padding to the position values?
                unrollPos.y += inspectorDrawer.position.y;                 // + 5f;

                unrollPos.width = Mathf.Max(unrollPos.width, PopupMenu.MinWidth);
            }

                        #if !UNITY_2019_3_OR_NEWER
            // if the inspector window is docked, the positions need to be adjusted somewhat to be accurate
            var inspectorWindow = inspectorDrawer as UnityEditor.EditorWindow;
            if (inspectorWindow != null)
            {
                if (inspectorWindow.IsDocked())
                {
                    unrollPos.x += 2f;
                    unrollPos.y -= 4f;
                }
            }
                        #endif

            openMenu(inspector, rootItems, groupsByLabel, itemsByLabel, tickedItems, canTickMultipleItems, unrollPos, onMenuItemClicked, onClosed, label);

                        #if DEV_MODE || PROFILE_POWER_INSPECTOR
            Profiler.EndSample();
                        #endif
        }
Exemple #2
0
        /// <summary>
        /// Setup the newly created instance.
        /// </summary>
        /// <param name="setInspector">  The inspector which contains the target. </param>
        /// <param name="target"> Target onto which components should be added Target onto which components should be added. </param>
        /// <param name="unrollPosition">The button position. </param>
        /// <param name="onClosed">
        /// This action is invoked
        /// when the editor window is
        /// closed. </param>
        private void Setup(IInspector setInspector, IGameObjectDrawer target, Rect unrollPosition, Action onClosed)
        {
            inspector = setInspector;
            var inspectorDrawer = inspector.InspectorDrawer;

            this.onClosed = onClosed;

            inspector.InspectorDrawer.Manager.IgnoreAllMouseInputs = true;

            var unrollPosScreenSpace = unrollPosition;

            //menu should open underneath the button
            unrollPosScreenSpace.y += unrollPosition.height - 1f;

            // add inspector y-axis position to open position
            // so that if this is a split view, the menu is opened
            // with the correct offset
            unrollPosScreenSpace.y += inspector.State.WindowRect.y;

            //TO DO: if it's off-screen, scroll to it!
            //if it's hidden via filter field, maybe clear the filter?
            //or maybe never hide it via the filter field?
            //or maybe disable the keyboard shortcut if it's hidden
            //even trigger it via the addcomponentmenu item?
            if (setInspector.IsOutsideViewport(unrollPosScreenSpace))
            {
                unrollPosScreenSpace.y = inspectorDrawer.position.y + inspectorDrawer.position.height - AddComponentMenuDrawer.TotalHeight;
            }
            else
            {
                unrollPosScreenSpace.y += inspectorDrawer.position.y - setInspector.State.ScrollPos.y + 20f;
            }

            var screenHeight = Screen.currentResolution.height;

            //if there's not enough screen estate to draw the menu below
            //the add component button then draw it above
            if (unrollPosScreenSpace.y + AddComponentMenuDrawer.TotalHeight > screenHeight)
            {
                unrollPosScreenSpace.y -= AddComponentMenuDrawer.TotalHeight + unrollPosition.height + 2f;
            }

            unrollPosScreenSpace.x = Mathf.CeilToInt(inspectorDrawer.position.x + setInspector.State.WindowRect.width * 0.5f - AddComponentMenuDrawer.Width * 0.5f);

            // if the inspector window is docked, the positions need to be adjusted somewhat to be accurate
            var inspectorWindow = setInspector.InspectorDrawer as EditorWindow;

            if (inspectorWindow != null)
            {
                if (inspectorWindow.IsDocked())
                {
                    unrollPosScreenSpace.x += 2f;
                    unrollPosScreenSpace.y -= 4f;
                }
            }

            if (drawer == null)
            {
                drawer = AddComponentMenuDrawer.Create(inspector, target, unrollPosition, Close);
            }
            else
            {
                drawer.Setup(inspector, target, unrollPosition, Close);
            }

            ShowAsDropDown(unrollPosScreenSpace, new Vector2(AddComponentMenuDrawer.Width, AddComponentMenuDrawer.TotalHeight));
        }