|
@@ -0,0 +1,292 @@
|
|
|
+using System.Collections.Generic;
|
|
|
+using System;
|
|
|
+using UnityEngine.EventSystems;
|
|
|
+using UnityEngine;
|
|
|
+
|
|
|
+public class ClickEvent : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
|
|
|
+{
|
|
|
+ private List<IClickListener> listenerList = new List<IClickListener>();
|
|
|
+ private Dictionary<IClickListener, Action> callBackDict = new Dictionary<IClickListener, Action>();
|
|
|
+
|
|
|
+ public void OnPointerDown(PointerEventData eventData)
|
|
|
+ {
|
|
|
+ for (int i = listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listenerList[i]?.OnPointerDown(eventData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnPointerUp(PointerEventData eventData)
|
|
|
+ {
|
|
|
+ for (int i = listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listenerList[i]?.OnPointerUp(eventData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnPointerClick(PointerEventData eventData)
|
|
|
+ {
|
|
|
+ for (int i = listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listenerList[i]?.OnPointerClick(eventData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Update()
|
|
|
+ {
|
|
|
+ for (int i = listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listenerList[i]?.Update();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public T Add<T>() where T : ClickListener, new()
|
|
|
+ {
|
|
|
+ T t = Get<T>();
|
|
|
+ if (t == null)
|
|
|
+ {
|
|
|
+ t = new T();
|
|
|
+ (t as IClickListener).OnCallBack((success) => OnReceive(success, t));
|
|
|
+ if (listenerList.Count == 0 || t is ClickButton) listenerList.Add(t);
|
|
|
+ else listenerList.Insert(listenerList.Count - 1, t);
|
|
|
+ }
|
|
|
+
|
|
|
+ return t;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Remove<T>() where T : ClickListener
|
|
|
+ {
|
|
|
+ if (!Contains<T>()) return;
|
|
|
+ T t = Get<T>();
|
|
|
+ if (callBackDict.ContainsKey(t)) callBackDict.Remove(t);
|
|
|
+ listenerList.Remove(t);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void RemoveAll()
|
|
|
+ {
|
|
|
+ listenerList.Clear();
|
|
|
+ callBackDict.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ public T Get<T>() where T : ClickListener
|
|
|
+ {
|
|
|
+ if (listenerList.Count == 0) return default;
|
|
|
+ IClickListener listener = default;
|
|
|
+ for (int i = listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listener = listenerList[i];
|
|
|
+ if (listener is T) return (T)listener;
|
|
|
+ }
|
|
|
+
|
|
|
+ return default;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool Contains<T>() where T : ClickListener
|
|
|
+ {
|
|
|
+ if (listenerList.Count == 0) return false;
|
|
|
+ IClickListener listener = default;
|
|
|
+ for (int i = listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listener = listenerList[i];
|
|
|
+ if (listener is T) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool ContainsCallBack<T>() where T : ClickListener
|
|
|
+ {
|
|
|
+ T t = Get<T>();
|
|
|
+ if (t == null) return false;
|
|
|
+ if (callBackDict.ContainsKey(t))
|
|
|
+ {
|
|
|
+ if (callBackDict[t] == null)
|
|
|
+ {
|
|
|
+ callBackDict.Remove(t);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Action GetCallBack<T>() where T : ClickListener
|
|
|
+ {
|
|
|
+ T t = Get<T>();
|
|
|
+ if (t == null) return null;
|
|
|
+ if (callBackDict.ContainsKey(t))
|
|
|
+ {
|
|
|
+ Action callBack = callBackDict[t];
|
|
|
+ if (callBack == null)
|
|
|
+ {
|
|
|
+ callBackDict.Remove(t);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return callBack;
|
|
|
+ }
|
|
|
+ else return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool HasRuning()
|
|
|
+ {
|
|
|
+ bool isRuning = false;
|
|
|
+ foreach (var lis in listenerList)
|
|
|
+ {
|
|
|
+ if (lis.isRuning)
|
|
|
+ {
|
|
|
+ isRuning = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return isRuning;
|
|
|
+ }
|
|
|
+
|
|
|
+ public T OnRegister<T>(Action callBack) where T : ClickListener, new()
|
|
|
+ {
|
|
|
+ T t = Add<T>();
|
|
|
+ if (callBackDict.ContainsKey(t)) callBackDict[t] = callBack;
|
|
|
+ else callBackDict.Add(t, callBack);
|
|
|
+ return t;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Action clickCallBack = null;
|
|
|
+
|
|
|
+ void OnReceive(bool success, IClickListener listener)
|
|
|
+ {
|
|
|
+ if (success)
|
|
|
+ {
|
|
|
+ if (listener is ClickButton) //单击事件
|
|
|
+ {
|
|
|
+ Action cbk = GetCallBack<ClickButton>();
|
|
|
+ if (cbk == null) return;
|
|
|
+ if (HasRuning()) //有正在运行的事件检测单击事件滞后分发
|
|
|
+ {
|
|
|
+ clickCallBack = cbk;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ clickCallBack = null;
|
|
|
+ ResetOther();
|
|
|
+ cbk.Invoke();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else //其他事件
|
|
|
+ {
|
|
|
+ clickCallBack = null;
|
|
|
+ ResetOther();
|
|
|
+ if (callBackDict.ContainsKey(listener)) callBackDict[listener]?.Invoke();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (!HasRuning())
|
|
|
+ {
|
|
|
+ clickCallBack?.Invoke();
|
|
|
+ clickCallBack = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void ResetOther()
|
|
|
+ {
|
|
|
+ foreach (var btn in listenerList)
|
|
|
+ {
|
|
|
+ if (btn != listener) btn?.Reset();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#if UNITY_EDITOR
|
|
|
+
|
|
|
+ [UnityEditor.CustomEditor(typeof(ClickEvent))]
|
|
|
+ class ClickEventInspector : UnityEditor.Editor
|
|
|
+ {
|
|
|
+ private ClickEvent clickEvent;
|
|
|
+
|
|
|
+ private void OnEnable()
|
|
|
+ {
|
|
|
+ clickEvent = target as ClickEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void OnInspectorGUI()
|
|
|
+ {
|
|
|
+ base.OnInspectorGUI();
|
|
|
+ GUILayout.Label("ClickListeners: ");
|
|
|
+ IClickListener listener;
|
|
|
+ for (int i = clickEvent.listenerList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ listener = clickEvent.listenerList[i];
|
|
|
+ GUILayout.Label(" " + listener);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+ private interface IClickListener
|
|
|
+ {
|
|
|
+ bool isRuning { get; set; }
|
|
|
+ void OnPointerDown(PointerEventData eventData);
|
|
|
+ void OnPointerUp(PointerEventData eventData);
|
|
|
+
|
|
|
+ void OnPointerClick(PointerEventData eventData);
|
|
|
+
|
|
|
+ void Update();
|
|
|
+
|
|
|
+ void OnCallBack(Action<bool> callBack);
|
|
|
+
|
|
|
+ void Reset();
|
|
|
+
|
|
|
+ void Dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ public abstract class ClickListener : IClickListener
|
|
|
+ {
|
|
|
+ bool IClickListener.isRuning
|
|
|
+ {
|
|
|
+ get => isRuning;
|
|
|
+ set { isRuning = value; }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected bool isRuning = false;
|
|
|
+
|
|
|
+ protected Action<bool> callBack { get; private set; }
|
|
|
+ void IClickListener.OnPointerDown(PointerEventData eventData) => OnPointerDown(eventData);
|
|
|
+ void IClickListener.OnPointerUp(PointerEventData eventData) => OnPointerUp(eventData);
|
|
|
+ void IClickListener.OnPointerClick(PointerEventData eventData) => OnPointerClick(eventData);
|
|
|
+ void IClickListener.Update() => Update();
|
|
|
+ void IClickListener.Reset() => Reset();
|
|
|
+ void IClickListener.Dispose() => Dispose();
|
|
|
+
|
|
|
+ void IClickListener.OnCallBack(Action<bool> callBack)
|
|
|
+ {
|
|
|
+ this.callBack = callBack;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void OnPointerDown(PointerEventData eventData)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void OnPointerUp(PointerEventData eventData)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void OnPointerClick(PointerEventData eventData)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ protected virtual void Update()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ protected abstract void Reset();
|
|
|
+
|
|
|
+ protected virtual void Dispose()
|
|
|
+ {
|
|
|
+ callBack = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|