MenuManager.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /// Credit Adam Kapos (Nezz) - http://www.songarc.net
  2. /// Sourced from - https://github.com/YousicianGit/UnityMenuSystem
  3. /// Updated by SimonDarksideJ - Refactored to be a more generic component
  4. /// Updated by SionDarksideJ - Fixed implementation as it assumed GO's we automatically assigned to instances
  5. using System.Collections.Generic;
  6. using System.Reflection;
  7. namespace UnityEngine.UI.Extensions
  8. {
  9. [AddComponentMenu("UI/Extensions/Menu Manager")]
  10. [DisallowMultipleComponent]
  11. public class MenuManager : MonoBehaviour
  12. {
  13. [SerializeField]
  14. private Menu[] menuScreens;
  15. public Menu[] MenuScreens
  16. {
  17. get { return menuScreens; }
  18. set { menuScreens = value; }
  19. }
  20. [SerializeField]
  21. private int startScreen = 0;
  22. public int StartScreen
  23. {
  24. get { return startScreen; }
  25. set { startScreen = value; }
  26. }
  27. private Stack<Menu> menuStack = new Stack<Menu>();
  28. public static MenuManager Instance { get; set; }
  29. private void Start()
  30. {
  31. Instance = this;
  32. if (MenuScreens.Length > 0 + StartScreen)
  33. {
  34. var startMenu = CreateInstance(MenuScreens[StartScreen].name);
  35. OpenMenu(startMenu.GetMenu());
  36. }
  37. else
  38. {
  39. Debug.LogError("Not enough Menu Screens configured");
  40. }
  41. }
  42. private void OnDestroy()
  43. {
  44. Instance = null;
  45. }
  46. public GameObject CreateInstance(string MenuName)
  47. {
  48. var prefab = GetPrefab(MenuName);
  49. return Instantiate(prefab, transform);
  50. }
  51. public void CreateInstance(string MenuName, out GameObject menuInstance)
  52. {
  53. var prefab = GetPrefab(MenuName);
  54. menuInstance = Instantiate(prefab, transform);
  55. }
  56. public void OpenMenu(Menu menuInstance)
  57. {
  58. // De-activate top menu
  59. if (menuStack.Count > 0)
  60. {
  61. if (menuInstance.DisableMenusUnderneath)
  62. {
  63. foreach (var menu in menuStack)
  64. {
  65. menu.gameObject.SetActive(false);
  66. if (menu.DisableMenusUnderneath)
  67. break;
  68. }
  69. }
  70. Canvas topCanvas = menuInstance.GetComponent<Canvas>();
  71. if (topCanvas != null)
  72. {
  73. Canvas previousCanvas = menuStack.Peek().GetComponent<Canvas>();
  74. if(previousCanvas != null)
  75. {
  76. topCanvas.sortingOrder = previousCanvas.sortingOrder + 1;
  77. }
  78. }
  79. }
  80. menuStack.Push(menuInstance);
  81. }
  82. private GameObject GetPrefab(string PrefabName)
  83. {
  84. for (int i = 0; i < MenuScreens.Length; i++)
  85. {
  86. if (MenuScreens[i].name == PrefabName)
  87. {
  88. return MenuScreens[i].gameObject;
  89. }
  90. }
  91. throw new MissingReferenceException("Prefab not found for " + PrefabName);
  92. }
  93. public void CloseMenu(Menu menu)
  94. {
  95. if (menuStack.Count == 0)
  96. {
  97. Debug.LogErrorFormat(menu, "{0} cannot be closed because menu stack is empty", menu.GetType());
  98. return;
  99. }
  100. if (menuStack.Peek() != menu)
  101. {
  102. Debug.LogErrorFormat(menu, "{0} cannot be closed because it is not on top of stack", menu.GetType());
  103. return;
  104. }
  105. CloseTopMenu();
  106. }
  107. public void CloseTopMenu()
  108. {
  109. var menuInstance = menuStack.Pop();
  110. if (menuInstance.DestroyWhenClosed)
  111. Destroy(menuInstance.gameObject);
  112. else
  113. menuInstance.gameObject.SetActive(false);
  114. // Re-activate top menu
  115. // If a re-activated menu is an overlay we need to activate the menu under it
  116. foreach (var menu in menuStack)
  117. {
  118. menu.gameObject.SetActive(true);
  119. if (menu.DisableMenusUnderneath)
  120. break;
  121. }
  122. }
  123. private void Update()
  124. {
  125. // On Android the back button is sent as Esc
  126. if (UIExtensionsInputManager.GetKeyDown(KeyCode.Escape) && menuStack.Count > 0)
  127. {
  128. menuStack.Peek().OnBackPressed();
  129. }
  130. }
  131. }
  132. public static class MenuExtensions
  133. {
  134. public static Menu GetMenu(this GameObject go)
  135. {
  136. return go.GetComponent<Menu>();
  137. }
  138. }
  139. }