283 lines
7.7 KiB
C#
283 lines
7.7 KiB
C#
|
using System.Collections.Generic;
|
|||
|
using System.Collections;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace FairyGUI
|
|||
|
{
|
|||
|
public delegate void TimerCallback(object param);
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
public class Timers
|
|||
|
{
|
|||
|
public static int repeat;
|
|||
|
public static float time;
|
|||
|
|
|||
|
public static bool catchCallbackExceptions = false;
|
|||
|
|
|||
|
Dictionary<TimerCallback, Anymous_T> _items;
|
|||
|
Dictionary<TimerCallback, Anymous_T> _toAdd;
|
|||
|
List<Anymous_T> _toRemove;
|
|||
|
List<Anymous_T> _pool;
|
|||
|
|
|||
|
TimersEngine _engine;
|
|||
|
GameObject gameObject;
|
|||
|
|
|||
|
private static Timers _inst;
|
|||
|
public static Timers inst
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_inst == null)
|
|||
|
_inst = new Timers();
|
|||
|
return _inst;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if UNITY_2019_3_OR_NEWER
|
|||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
|||
|
static void InitializeOnLoad()
|
|||
|
{
|
|||
|
_inst = null;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
public Timers()
|
|||
|
{
|
|||
|
_inst = this;
|
|||
|
gameObject = new GameObject("[FairyGUI.Timers]");
|
|||
|
gameObject.hideFlags = HideFlags.HideInHierarchy;
|
|||
|
gameObject.SetActive(true);
|
|||
|
Object.DontDestroyOnLoad(gameObject);
|
|||
|
|
|||
|
_engine = gameObject.AddComponent<TimersEngine>();
|
|||
|
|
|||
|
_items = new Dictionary<TimerCallback, Anymous_T>();
|
|||
|
_toAdd = new Dictionary<TimerCallback, Anymous_T>();
|
|||
|
_toRemove = new List<Anymous_T>();
|
|||
|
_pool = new List<Anymous_T>(100);
|
|||
|
}
|
|||
|
|
|||
|
public void Add(float interval, int repeat, TimerCallback callback)
|
|||
|
{
|
|||
|
Add(interval, repeat, callback, null);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @interval in seconds
|
|||
|
* @repeat 0 indicate loop infinitely, otherwise the run count
|
|||
|
**/
|
|||
|
public void Add(float interval, int repeat, TimerCallback callback, object callbackParam)
|
|||
|
{
|
|||
|
if (callback == null)
|
|||
|
{
|
|||
|
Debug.LogWarning("timer callback is null, " + interval + "," + repeat);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Anymous_T t;
|
|||
|
if (_items.TryGetValue(callback, out t))
|
|||
|
{
|
|||
|
t.set(interval, repeat, callback, callbackParam);
|
|||
|
t.elapsed = 0;
|
|||
|
t.deleted = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (_toAdd.TryGetValue(callback, out t))
|
|||
|
{
|
|||
|
t.set(interval, repeat, callback, callbackParam);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
t = GetFromPool();
|
|||
|
t.interval = interval;
|
|||
|
t.repeat = repeat;
|
|||
|
t.callback = callback;
|
|||
|
t.param = callbackParam;
|
|||
|
_toAdd[callback] = t;
|
|||
|
}
|
|||
|
|
|||
|
public void CallLater(TimerCallback callback)
|
|||
|
{
|
|||
|
Add(0.001f, 1, callback);
|
|||
|
}
|
|||
|
|
|||
|
public void CallLater(TimerCallback callback, object callbackParam)
|
|||
|
{
|
|||
|
Add(0.001f, 1, callback, callbackParam);
|
|||
|
}
|
|||
|
|
|||
|
public void AddUpdate(TimerCallback callback)
|
|||
|
{
|
|||
|
Add(0.001f, 0, callback);
|
|||
|
}
|
|||
|
|
|||
|
public void AddUpdate(TimerCallback callback, object callbackParam)
|
|||
|
{
|
|||
|
Add(0.001f, 0, callback, callbackParam);
|
|||
|
}
|
|||
|
|
|||
|
public void StartCoroutine(IEnumerator routine)
|
|||
|
{
|
|||
|
_engine.StartCoroutine(routine);
|
|||
|
}
|
|||
|
|
|||
|
public bool Exists(TimerCallback callback)
|
|||
|
{
|
|||
|
if (_toAdd.ContainsKey(callback))
|
|||
|
return true;
|
|||
|
|
|||
|
Anymous_T at;
|
|||
|
if (_items.TryGetValue(callback, out at))
|
|||
|
return !at.deleted;
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public void Remove(TimerCallback callback)
|
|||
|
{
|
|||
|
Anymous_T t;
|
|||
|
if (_toAdd.TryGetValue(callback, out t))
|
|||
|
{
|
|||
|
_toAdd.Remove(callback);
|
|||
|
ReturnToPool(t);
|
|||
|
}
|
|||
|
|
|||
|
if (_items.TryGetValue(callback, out t))
|
|||
|
t.deleted = true;
|
|||
|
}
|
|||
|
|
|||
|
private Anymous_T GetFromPool()
|
|||
|
{
|
|||
|
Anymous_T t;
|
|||
|
int cnt = _pool.Count;
|
|||
|
if (cnt > 0)
|
|||
|
{
|
|||
|
t = _pool[cnt - 1];
|
|||
|
_pool.RemoveAt(cnt - 1);
|
|||
|
t.deleted = false;
|
|||
|
t.elapsed = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
t = new Anymous_T();
|
|||
|
return t;
|
|||
|
}
|
|||
|
|
|||
|
private void ReturnToPool(Anymous_T t)
|
|||
|
{
|
|||
|
t.callback = null;
|
|||
|
_pool.Add(t);
|
|||
|
}
|
|||
|
|
|||
|
public void Update()
|
|||
|
{
|
|||
|
float dt = Time.unscaledDeltaTime;
|
|||
|
Dictionary<TimerCallback, Anymous_T>.Enumerator iter;
|
|||
|
|
|||
|
if (_items.Count > 0)
|
|||
|
{
|
|||
|
iter = _items.GetEnumerator();
|
|||
|
while (iter.MoveNext())
|
|||
|
{
|
|||
|
Anymous_T i = iter.Current.Value;
|
|||
|
if (i.deleted)
|
|||
|
{
|
|||
|
_toRemove.Add(i);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
i.elapsed += dt;
|
|||
|
if (i.elapsed < i.interval)
|
|||
|
continue;
|
|||
|
|
|||
|
i.elapsed -= i.interval;
|
|||
|
if (i.elapsed < 0 || i.elapsed > 0.03f)
|
|||
|
i.elapsed = 0;
|
|||
|
|
|||
|
if (i.repeat > 0)
|
|||
|
{
|
|||
|
i.repeat--;
|
|||
|
if (i.repeat == 0)
|
|||
|
{
|
|||
|
i.deleted = true;
|
|||
|
_toRemove.Add(i);
|
|||
|
}
|
|||
|
}
|
|||
|
repeat = i.repeat;
|
|||
|
if (i.callback != null)
|
|||
|
{
|
|||
|
if (catchCallbackExceptions)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
i.callback(i.param);
|
|||
|
}
|
|||
|
catch (System.Exception e)
|
|||
|
{
|
|||
|
i.deleted = true;
|
|||
|
Debug.LogWarning("FairyGUI: timer(internal=" + i.interval + ", repeat=" + i.repeat + ") callback error > " + e.Message);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
i.callback(i.param);
|
|||
|
}
|
|||
|
}
|
|||
|
iter.Dispose();
|
|||
|
}
|
|||
|
|
|||
|
int len = _toRemove.Count;
|
|||
|
if (len > 0)
|
|||
|
{
|
|||
|
for (int k = 0; k < len; k++)
|
|||
|
{
|
|||
|
Anymous_T i = _toRemove[k];
|
|||
|
if (i.deleted && i.callback != null)
|
|||
|
{
|
|||
|
_items.Remove(i.callback);
|
|||
|
ReturnToPool(i);
|
|||
|
}
|
|||
|
}
|
|||
|
_toRemove.Clear();
|
|||
|
}
|
|||
|
|
|||
|
if (_toAdd.Count > 0)
|
|||
|
{
|
|||
|
iter = _toAdd.GetEnumerator();
|
|||
|
while (iter.MoveNext())
|
|||
|
_items.Add(iter.Current.Key, iter.Current.Value);
|
|||
|
iter.Dispose();
|
|||
|
_toAdd.Clear();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
class Anymous_T
|
|||
|
{
|
|||
|
public float interval;
|
|||
|
public int repeat;
|
|||
|
public TimerCallback callback;
|
|||
|
public object param;
|
|||
|
|
|||
|
public float elapsed;
|
|||
|
public bool deleted;
|
|||
|
|
|||
|
public void set(float interval, int repeat, TimerCallback callback, object param)
|
|||
|
{
|
|||
|
this.interval = interval;
|
|||
|
this.repeat = repeat;
|
|||
|
this.callback = callback;
|
|||
|
this.param = param;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
class TimersEngine : MonoBehaviour
|
|||
|
{
|
|||
|
void Update()
|
|||
|
{
|
|||
|
Timers.inst.Update();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|