/// <summary>
        /// Builds and returns a <see cref="GenericMenu"/> for the given <see cref="EditorMenu"/>.
        /// </summary>
        /// <param name="menu">Input menu data structure.</param>
        /// <returns>
        /// A new <see cref="GenericMenu"/> instance.
        /// </returns>
        public virtual GenericMenu BuildMenu(EditorMenu menu)
        {
            var genericMenu    = new GenericMenu();
            var populatedPaths = new HashSet <string>();

            int entryIndex = -1;

            foreach (var entry in menu.Entries)
            {
                ++entryIndex;

                if (entry.EvaluateIsVisible() == false)
                {
                    continue;
                }

                var separatorEntry = entry as EditorMenuSeparatorEntry;
                if (separatorEntry != null)
                {
                    bool isFirstAtPath = !populatedPaths.Contains(entry.Path);
                    if (this.CanAddSeparatorEntryToMenu(menu, entryIndex, entry.Path, isFirstAtPath))
                    {
                        this.AddSeparatorEntryToMenu(genericMenu, separatorEntry);
                    }
                    continue;
                }

                populatedPaths.Add(entry.Path);

                this.AddEntryToMenu(genericMenu, entry);
            }

            return(genericMenu);
        }
        /// <inheritdoc/>
        public void ShowAsDropdown(Rect position, EditorMenu menu)
        {
            var genericMenu = this.BuildMenu(menu);

            if (genericMenu.GetItemCount() > 0)
            {
                genericMenu.DropDown(position);
            }
        }
        /// <inheritdoc/>
        public void ShowAsContext(EditorMenu menu)
        {
            var genericMenu = this.BuildMenu(menu);

            if (genericMenu.GetItemCount() > 0)
            {
                genericMenu.ShowAsContext();
            }
        }
 /// <summary>
 /// Finds the next visible menu entry at the given path.
 /// </summary>
 /// <param name="menu">Input menu data structure.</param>
 /// <param name="path">Path of the entry.</param>
 /// <param name="fromEntryIndex">Zero-based index of the starting entry (excluded).</param>
 /// <returns>
 /// The next visible <see cref="IEditorMenuEntry"/> instance when found;
 /// otherwise, a value of <c>null</c>.
 /// </returns>
 protected static IEditorMenuEntry FindNextVisibleMenuEntryAtPath(EditorMenu menu, string path, int fromEntryIndex)
 {
     for (int entryIndex = fromEntryIndex + 1; entryIndex < menu.Entries.Count; ++entryIndex)
     {
         var entry = menu.Entries[entryIndex];
         if (entry.Path == path && entry.EvaluateIsVisible())
         {
             return(entry);
         }
     }
     return(null);
 }
        /// <summary>
        /// Determines whether a separator can be added to the <see cref="GenericMenu"/>.
        /// </summary>
        /// <param name="menu">Input menu data structure.</param>
        /// <param name="entryIndex">Zero-based index of the separator entry.</param>
        /// <param name="path">Path of the separator entry.</param>
        /// <param name="isFirstAtPath">Indicates if the separator would be the first
        /// output entry at that path.</param>
        /// <returns>
        /// A value of <c>true</c> if the separator entry can be added to the output
        /// <see cref="GenericMenu"/>; else, a value of <c>false</c>.
        /// </returns>
        protected virtual bool CanAddSeparatorEntryToMenu(EditorMenu menu, int entryIndex, string path, bool isFirstAtPath)
        {
            // Don't output separator at the start of a path... it just doesn't look good!
            if (isFirstAtPath)
            {
                return(false);
            }

            var nextEntryAtPath = FindNextVisibleMenuEntryAtPath(menu, path, entryIndex);

            // Don't output separator if no entry follows in same menu path.
            if (nextEntryAtPath == null)
            {
                return(false);
            }
            // Don't output separator if next entry is also separator... it doesn't look good!
            if (nextEntryAtPath is EditorMenuSeparatorEntry)
            {
                return(false);
            }

            return(true);
        }