ClickEvent.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. using System.Collections.Generic;
  2. using System;
  3. using UnityEngine.EventSystems;
  4. using UnityEngine;
  5. public class ClickEvent : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
  6. {
  7. private List<IClickListener> listenerList = new List<IClickListener>();
  8. private Dictionary<IClickListener, Action> callBackDict = new Dictionary<IClickListener, Action>();
  9. public void OnPointerDown(PointerEventData eventData)
  10. {
  11. for (int i = listenerList.Count - 1; i >= 0; i--)
  12. {
  13. listenerList[i]?.OnPointerDown(eventData);
  14. }
  15. }
  16. public void OnPointerUp(PointerEventData eventData)
  17. {
  18. for (int i = listenerList.Count - 1; i >= 0; i--)
  19. {
  20. listenerList[i]?.OnPointerUp(eventData);
  21. }
  22. }
  23. public void OnPointerClick(PointerEventData eventData)
  24. {
  25. for (int i = listenerList.Count - 1; i >= 0; i--)
  26. {
  27. listenerList[i]?.OnPointerClick(eventData);
  28. }
  29. }
  30. private void Update()
  31. {
  32. for (int i = listenerList.Count - 1; i >= 0; i--)
  33. {
  34. listenerList[i]?.Update();
  35. }
  36. }
  37. public T Add<T>() where T : ClickListener, new()
  38. {
  39. T t = Get<T>();
  40. if (t == null)
  41. {
  42. t = new T();
  43. (t as IClickListener).OnCallBack((success) => OnReceive(success, t));
  44. if (listenerList.Count == 0 || t is ClickButton) listenerList.Add(t);
  45. else listenerList.Insert(listenerList.Count - 1, t);
  46. }
  47. return t;
  48. }
  49. public void Remove<T>() where T : ClickListener
  50. {
  51. if (!Contains<T>()) return;
  52. T t = Get<T>();
  53. if (callBackDict.ContainsKey(t)) callBackDict.Remove(t);
  54. listenerList.Remove(t);
  55. }
  56. public void RemoveAll()
  57. {
  58. listenerList.Clear();
  59. callBackDict.Clear();
  60. }
  61. public T Get<T>() where T : ClickListener
  62. {
  63. if (listenerList.Count == 0) return default;
  64. IClickListener listener = default;
  65. for (int i = listenerList.Count - 1; i >= 0; i--)
  66. {
  67. listener = listenerList[i];
  68. if (listener is T) return (T)listener;
  69. }
  70. return default;
  71. }
  72. public bool Contains<T>() where T : ClickListener
  73. {
  74. if (listenerList.Count == 0) return false;
  75. IClickListener listener = default;
  76. for (int i = listenerList.Count - 1; i >= 0; i--)
  77. {
  78. listener = listenerList[i];
  79. if (listener is T) return true;
  80. }
  81. return false;
  82. }
  83. public bool ContainsCallBack<T>() where T : ClickListener
  84. {
  85. T t = Get<T>();
  86. if (t == null) return false;
  87. if (callBackDict.ContainsKey(t))
  88. {
  89. if (callBackDict[t] == null)
  90. {
  91. callBackDict.Remove(t);
  92. return false;
  93. }
  94. return true;
  95. }
  96. else return false;
  97. }
  98. public Action GetCallBack<T>() where T : ClickListener
  99. {
  100. T t = Get<T>();
  101. if (t == null) return null;
  102. if (callBackDict.ContainsKey(t))
  103. {
  104. Action callBack = callBackDict[t];
  105. if (callBack == null)
  106. {
  107. callBackDict.Remove(t);
  108. return null;
  109. }
  110. return callBack;
  111. }
  112. else return null;
  113. }
  114. public bool HasRuning()
  115. {
  116. bool isRuning = false;
  117. foreach (var lis in listenerList)
  118. {
  119. if (lis.isRuning)
  120. {
  121. isRuning = true;
  122. break;
  123. }
  124. }
  125. return isRuning;
  126. }
  127. public T OnRegister<T>(Action callBack) where T : ClickListener, new()
  128. {
  129. T t = Add<T>();
  130. if (callBackDict.ContainsKey(t)) callBackDict[t] = callBack;
  131. else callBackDict.Add(t, callBack);
  132. return t;
  133. }
  134. private Action clickCallBack = null;
  135. void OnReceive(bool success, IClickListener listener)
  136. {
  137. if (success)
  138. {
  139. if (listener is ClickButton) //单击事件
  140. {
  141. Action cbk = GetCallBack<ClickButton>();
  142. if (cbk == null) return;
  143. if (HasRuning()) //有正在运行的事件检测单击事件滞后分发
  144. {
  145. clickCallBack = cbk;
  146. }
  147. else
  148. {
  149. clickCallBack = null;
  150. ResetOther();
  151. cbk.Invoke();
  152. }
  153. }
  154. else //其他事件
  155. {
  156. clickCallBack = null;
  157. ResetOther();
  158. if (callBackDict.ContainsKey(listener)) callBackDict[listener]?.Invoke();
  159. }
  160. }
  161. else
  162. {
  163. if (!HasRuning())
  164. {
  165. clickCallBack?.Invoke();
  166. clickCallBack = null;
  167. }
  168. }
  169. void ResetOther()
  170. {
  171. foreach (var btn in listenerList)
  172. {
  173. if (btn != listener) btn?.Reset();
  174. }
  175. }
  176. }
  177. #if UNITY_EDITOR
  178. [UnityEditor.CustomEditor(typeof(ClickEvent))]
  179. class ClickEventInspector : UnityEditor.Editor
  180. {
  181. private ClickEvent clickEvent;
  182. private void OnEnable()
  183. {
  184. clickEvent = target as ClickEvent;
  185. }
  186. public override void OnInspectorGUI()
  187. {
  188. base.OnInspectorGUI();
  189. GUILayout.Label("ClickListeners: ");
  190. IClickListener listener;
  191. for (int i = clickEvent.listenerList.Count - 1; i >= 0; i--)
  192. {
  193. listener = clickEvent.listenerList[i];
  194. GUILayout.Label(" " + listener);
  195. }
  196. }
  197. }
  198. #endif
  199. private interface IClickListener
  200. {
  201. bool isRuning { get; set; }
  202. void OnPointerDown(PointerEventData eventData);
  203. void OnPointerUp(PointerEventData eventData);
  204. void OnPointerClick(PointerEventData eventData);
  205. void Update();
  206. void OnCallBack(Action<bool> callBack);
  207. void Reset();
  208. void Dispose();
  209. }
  210. public abstract class ClickListener : IClickListener
  211. {
  212. bool IClickListener.isRuning
  213. {
  214. get => isRuning;
  215. set { isRuning = value; }
  216. }
  217. protected bool isRuning = false;
  218. protected Action<bool> callBack { get; private set; }
  219. void IClickListener.OnPointerDown(PointerEventData eventData) => OnPointerDown(eventData);
  220. void IClickListener.OnPointerUp(PointerEventData eventData) => OnPointerUp(eventData);
  221. void IClickListener.OnPointerClick(PointerEventData eventData) => OnPointerClick(eventData);
  222. void IClickListener.Update() => Update();
  223. void IClickListener.Reset() => Reset();
  224. void IClickListener.Dispose() => Dispose();
  225. void IClickListener.OnCallBack(Action<bool> callBack)
  226. {
  227. this.callBack = callBack;
  228. }
  229. protected virtual void OnPointerDown(PointerEventData eventData)
  230. {
  231. }
  232. protected virtual void OnPointerUp(PointerEventData eventData)
  233. {
  234. }
  235. protected virtual void OnPointerClick(PointerEventData eventData)
  236. {
  237. }
  238. protected virtual void Update()
  239. {
  240. }
  241. protected abstract void Reset();
  242. protected virtual void Dispose()
  243. {
  244. callBack = null;
  245. }
  246. }
  247. }