using System; using System.Collections.Generic; using JetBrains.Annotations; using Unity.Cloud.Collaborate.UserInterface; using Unity.Cloud.Collaborate.Utilities; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace Unity.Cloud.Collaborate.Components.Menus { [UsedImplicitly] internal class FloatingMenu { public const string ussClassName = "unity-floating-menu"; // Fields used to display the option list. const float k_ItemHeight = 28f; readonly List<(string Text, Action Action, bool Enabled)> m_Items; /// /// Location the uss file for this element is stored. /// static readonly string k_StylePath = $"{CollaborateWindow.StylePath}/{nameof(FloatingMenu)}.uss"; /// /// Container for the menu items. /// readonly VisualElement m_Content; /// /// Direction to open the menu. /// MenuUtilities.OpenDirection m_OpenDirection = MenuUtilities.OpenDirection.DownLeft; /// /// Create a new floating menu. Follows the builder pattern. /// public FloatingMenu() { m_Items = new List<(string Text, Action Action, bool Enabled)>(); m_Content = new VisualElement(); m_Content.AddToClassList(ussClassName); m_Content.styleSheets.Add(AssetDatabase.LoadAssetAtPath(k_StylePath)); } /// /// Add a single option to the menu. /// /// Text in the option. /// Action to invoke on click. /// State of the entry. /// This. public FloatingMenu AddEntry(string text, Action action, bool enabled) { m_Items.Add((text, action, enabled)); return this; } /// /// Add a list of entries. /// /// Entries to add. /// This. public FloatingMenu AddEntries(IEnumerable<(string Text, Action Action, bool Enabled)> items) { m_Items.AddRange(items); return this; } /// /// Sets the open direction of the menu. /// /// Direction the menu opens towards. /// This. public FloatingMenu SetOpenDirection(MenuUtilities.OpenDirection openDirection) { m_OpenDirection = openDirection; return this; } /// /// Opens the constructed menu. /// /// World x coordinate. /// World y coordinate. public void Open(float x, float y) { FloatingDialogue.Instance.Open(x, y, GenerateContent(), m_OpenDirection); } /// /// Generate the visual element that displays the content of this menu. /// /// The constructed visual element. VisualElement GenerateContent() { m_Content.Clear(); foreach (var item in m_Items) { // Ensure the dialogue closes once the option is selected void Action() { FloatingDialogue.Instance.Close(); item.Action(); } var elem = new FloatingMenuItem(item.Text, Action, item.Enabled, k_ItemHeight); m_Content.Add(elem); } return m_Content; } } }