DropDown.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using System;
  2. using UnityEngine;
  3. using DropdownCloseArgs = MeidoPhotoStudio.Plugin.DropdownHelper.DropdownCloseArgs;
  4. using DropdownSelectArgs = MeidoPhotoStudio.Plugin.DropdownHelper.DropdownSelectArgs;
  5. namespace MeidoPhotoStudio.Plugin;
  6. public class Dropdown : BaseControl
  7. {
  8. private readonly string label;
  9. private readonly bool isMenu;
  10. private Vector2 elementSize;
  11. private int selectedItemIndex;
  12. private bool clickedYou;
  13. private bool showDropdown;
  14. private Vector2 scrollPos;
  15. private Rect buttonRect;
  16. public Dropdown(string label, string[] itemList, int selectedItemIndex = 0)
  17. : this(itemList, selectedItemIndex)
  18. {
  19. this.label = label;
  20. isMenu = true;
  21. }
  22. public Dropdown(string[] itemList, int selectedItemIndex = 0)
  23. {
  24. DropdownID = DropdownHelper.DropdownID;
  25. SetDropdownItems(itemList, selectedItemIndex);
  26. DropdownHelper.SelectionChange += OnChangeSelection;
  27. DropdownHelper.DropdownClose += OnCloseDropdown;
  28. }
  29. // TODO: I don't think this works the way I think it does
  30. ~Dropdown()
  31. {
  32. DropdownHelper.SelectionChange -= OnChangeSelection;
  33. DropdownHelper.DropdownClose -= OnCloseDropdown;
  34. }
  35. public event EventHandler SelectionChange;
  36. public event EventHandler DropdownOpen;
  37. public event EventHandler DropdownClose;
  38. public int DropdownID { get; }
  39. public string[] DropdownList { get; private set; }
  40. public Vector2 ScrollPos =>
  41. scrollPos;
  42. public string SelectedItem =>
  43. DropdownList[SelectedItemIndex];
  44. public Rect ButtonRect
  45. {
  46. get => buttonRect;
  47. private set => buttonRect = value;
  48. }
  49. public Vector2 ElementSize =>
  50. elementSize;
  51. public int SelectedItemIndex
  52. {
  53. get => selectedItemIndex;
  54. set
  55. {
  56. selectedItemIndex = Mathf.Clamp(value, 0, DropdownList.Length - 1);
  57. OnDropdownEvent(SelectionChange);
  58. }
  59. }
  60. public void SetDropdownItems(string[] itemList, int selectedItemIndex = -1)
  61. {
  62. if (selectedItemIndex < 0)
  63. selectedItemIndex = SelectedItemIndex;
  64. elementSize = Vector2.zero;
  65. // TODO: Calculate scrollpos position maybe
  66. if (selectedItemIndex != this.selectedItemIndex || itemList.Length != DropdownList?.Length)
  67. scrollPos = Vector2.zero;
  68. DropdownList = itemList;
  69. SelectedItemIndex = selectedItemIndex;
  70. }
  71. public void SetDropdownItem(int index, string newItem)
  72. {
  73. if (index < 0 || index >= DropdownList.Length)
  74. return;
  75. var itemSize = DropdownHelper.CalculateElementSize(newItem);
  76. if (itemSize.x > ElementSize.x)
  77. elementSize = itemSize;
  78. DropdownList[index] = newItem;
  79. }
  80. public void SetDropdownItem(string newItem) =>
  81. SetDropdownItem(SelectedItemIndex, newItem);
  82. public void Step(int dir)
  83. {
  84. dir = (int)Mathf.Sign(dir);
  85. SelectedItemIndex = Utility.Wrap(SelectedItemIndex + dir, 0, DropdownList.Length);
  86. }
  87. public void Draw(GUIStyle buttonStyle, params GUILayoutOption[] layoutOptions) =>
  88. Draw(buttonStyle, null, layoutOptions);
  89. public void Draw(GUIStyle buttonStyle, GUIStyle dropdownStyle = null, params GUILayoutOption[] layoutOptions)
  90. {
  91. var clicked = GUILayout.Button(isMenu ? label : DropdownList[selectedItemIndex], buttonStyle, layoutOptions);
  92. if (clicked)
  93. {
  94. showDropdown = !clickedYou;
  95. clickedYou = false;
  96. }
  97. if (showDropdown && Event.current.type is EventType.Repaint)
  98. InitializeDropdown(dropdownStyle);
  99. }
  100. public override void Draw(params GUILayoutOption[] layoutOptions)
  101. {
  102. var buttonStyle = new GUIStyle(GUI.skin.button)
  103. {
  104. alignment = TextAnchor.MiddleLeft,
  105. };
  106. Draw(buttonStyle, layoutOptions);
  107. }
  108. private void OnChangeSelection(object sender, DropdownSelectArgs args)
  109. {
  110. if (args.DropdownID == DropdownID)
  111. SelectedItemIndex = args.SelectedItemIndex;
  112. }
  113. private void OnCloseDropdown(object sender, DropdownCloseArgs args)
  114. {
  115. if (args.DropdownID != DropdownID)
  116. return;
  117. scrollPos = args.ScrollPos;
  118. clickedYou = args.ClickedYou;
  119. if (clickedYou)
  120. OnDropdownEvent(SelectionChange);
  121. OnDropdownEvent(DropdownClose);
  122. }
  123. private void InitializeDropdown(GUIStyle dropdownStyle)
  124. {
  125. showDropdown = false;
  126. buttonRect = GUILayoutUtility.GetLastRect();
  127. var rectPos = GUIUtility.GUIToScreenPoint(new(buttonRect.x, buttonRect.y));
  128. buttonRect.x = rectPos.x;
  129. buttonRect.y = rectPos.y;
  130. if (elementSize == Vector2.zero)
  131. elementSize = DropdownHelper.CalculateElementSize(DropdownList, dropdownStyle);
  132. DropdownHelper.Set(this, dropdownStyle);
  133. OnDropdownEvent(DropdownOpen);
  134. }
  135. private void OnDropdownEvent(EventHandler handler) =>
  136. handler?.Invoke(this, EventArgs.Empty);
  137. }