WindowsManager.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. namespace SoftKitty.InventoryEngine
  6. {
  7. public class WindowsManager : MonoBehaviour
  8. {
  9. /// <summary>
  10. /// Returns true if there is any UI window exists.
  11. /// </summary>
  12. public static bool anyWindowExists
  13. {
  14. get
  15. {
  16. return windowsDic.Keys.Count > 0;
  17. }
  18. }
  19. #region Variables
  20. public static UiWindow ActiveWindow;
  21. private static WindowsManager instance;
  22. private static Dictionary<InventoryHolder, UiWindow> windowsDic = new Dictionary<InventoryHolder, UiWindow>();
  23. #endregion
  24. #region Internal Methods
  25. void Awake()
  26. {
  27. instance = this;
  28. windowsDic.Clear();
  29. }
  30. IEnumerator ActiveWindowLater(UiWindow _window)
  31. {
  32. yield return 1;
  33. _window.ActiveWindow();
  34. }
  35. public static GameObject GetMainCanvas(GameObject _base=null)
  36. {
  37. if (ItemManager.instance.CanvasTag.Replace(" ", "").Length > 0)
  38. {
  39. Canvas[] _canvas = FindObjectsByType<Canvas>(FindObjectsInactive.Include, FindObjectsSortMode.InstanceID);
  40. foreach (var obj in _canvas) {
  41. if (obj.gameObject.tag == ItemManager.instance.CanvasTag) return obj.gameObject;
  42. }
  43. Debug.LogError("[InventoryEngine] Could not find Canvas GameObject with the tag you specified!");
  44. }
  45. //If it fails to get canvas with the specified tag or the tag is null, search canvas from the parent of the base gameObject.
  46. if (_base != null && _base.GetComponentInParent<CanvasScaler>()) return _base.GetComponentInParent<CanvasScaler>().gameObject;
  47. //If there is no base gameObject, or could not find root canvas from the parents, then search canvas from the scene.
  48. //The reason we use <CanvasScaler> instead of <Canvas> is becuase Canvas can be nested, we only aiming to find the root canvas which usually come with <CanvasScaler> together.
  49. if (FindFirstObjectByType<CanvasScaler>()!=null) return FindFirstObjectByType<CanvasScaler>().gameObject;
  50. Debug.LogError("[InventoryEngine] Could not find Canvas GameObject in your scene! Creating one...");
  51. //If there is no canvas at all in the scene, we're going to create one.
  52. GameObject _tempCanvasObj = new GameObject("InventoryEngineCanvas");
  53. Canvas _tempCanvas= _tempCanvasObj.AddComponent<Canvas>();
  54. _tempCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
  55. if (ItemManager.instance.CanvasTag.Replace(" ", "").Length > 0) _tempCanvasObj.tag = ItemManager.instance.CanvasTag;
  56. CanvasScaler _tempScaler= _tempCanvasObj.AddComponent<CanvasScaler>();
  57. _tempScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
  58. _tempScaler.referenceResolution = new Vector2(1920F,1080F);
  59. _tempScaler.matchWidthOrHeight = 1F;
  60. _tempCanvasObj.AddComponent<GraphicRaycaster>();
  61. return _tempCanvasObj;
  62. }
  63. public UiWindow OpenWindow(string _prefabName, InventoryHolder _holder, bool _bringToTop = true)
  64. {
  65. if (windowsDic.ContainsKey(_holder))
  66. {
  67. windowsDic[_holder].Close();
  68. return null;
  69. }
  70. GameObject _newWindow = Instantiate(Resources.Load<GameObject>("InventoryEngine/UiWindows/" + _prefabName), transform);
  71. if (!_newWindow.GetComponent<UiWindow>().FixedDefaultPosition)
  72. {
  73. float _width = _newWindow.GetComponent<RectTransform>().sizeDelta.x * 0.5F;
  74. float _screenWidth = GetMainCanvas(_newWindow).GetComponent<RectTransform>().sizeDelta.x * 0.5F;
  75. _newWindow.transform.localPosition = new Vector3(Mathf.Clamp(-450F + (windowsDic.Count + 1) * 50F, _width - _screenWidth + 270F, _screenWidth - _width)
  76. , _newWindow.transform.localPosition.y - windowsDic.Count * 50F, 0F);
  77. }
  78. windowsDic.Add(_holder, _newWindow.GetComponent<UiWindow>());
  79. _newWindow.GetComponent<UiWindow>().RegisterCloseCallback(OnWindowClose, _holder);
  80. if (_bringToTop) _newWindow.GetComponent<UiWindow>().ActiveWindow();
  81. return _newWindow.GetComponent<UiWindow>();
  82. }
  83. public void OnWindowClose(InventoryHolder _key)
  84. {
  85. if (windowsDic.ContainsKey(_key)) windowsDic.Remove(_key);
  86. InventoryHolder lastKey = null;
  87. foreach (var key in windowsDic.Keys)
  88. {
  89. if (windowsDic[key] != null) lastKey = key;
  90. }
  91. if (lastKey != null) StartCoroutine(ActiveWindowLater(windowsDic[lastKey]));
  92. }
  93. #endregion
  94. /// <summary>
  95. /// Close all active windows
  96. /// </summary>
  97. public static void CloseAllWindows()
  98. {
  99. List<UiWindow> _windows = new List<UiWindow>();
  100. foreach (var obj in windowsDic.Keys) _windows.Add(windowsDic[obj]);
  101. windowsDic.Clear();
  102. foreach (var obj in _windows) obj.Close();
  103. }
  104. /// <summary>
  105. /// Open an window by the ui prefab name and the InventoryHolder component, you can find the prefabs in SoftKitty/InventoryEngine/Resources/InventoryEngine/UiWindows/
  106. /// </summary>
  107. /// <param name="_prefabName"></param>
  108. /// <param name="_holder"></param>
  109. /// <param name="_bringToTop"></param>
  110. /// <returns></returns>
  111. public static UiWindow GetWindow(string _prefabName,InventoryHolder _holder, bool _bringToTop=true)
  112. {
  113. if (instance == null)
  114. {
  115. GameObject newObj = Instantiate(Resources.Load<GameObject>("InventoryEngine/WindowsManager"),GetMainCanvas().transform);
  116. newObj.transform.SetAsLastSibling();
  117. newObj.transform.localPosition = Vector3.zero;
  118. newObj.transform.localScale = Vector3.one;
  119. instance = newObj.GetComponent<WindowsManager>();
  120. }
  121. return instance.OpenWindow(_prefabName, _holder, _bringToTop);
  122. }
  123. /// <summary>
  124. /// Check if the window of an InventoryHolder is opened
  125. /// </summary>
  126. /// <param name="_key"></param>
  127. /// <returns></returns>
  128. public static bool isWindowOpen(InventoryHolder _key)
  129. {
  130. if (_key == null) return false;
  131. return windowsDic.ContainsKey(_key);
  132. }
  133. /// <summary>
  134. /// Returns the window class by an InventoryHolder as the key.
  135. /// </summary>
  136. /// <param name="_key"></param>
  137. /// <returns></returns>
  138. public static UiWindow getOpenedWindow(InventoryHolder _key)
  139. {
  140. if (_key == null) return null;
  141. if (windowsDic.ContainsKey(_key))
  142. return windowsDic[_key];
  143. else
  144. return null;
  145. }
  146. }
  147. }