using System.Collections.Generic;
using System.Collections;
using UnityEngine;
namespace FairyGUI
{
public delegate void TimerCallback(object param);
///
///
///
public class Timers
{
public static int repeat;
public static float time;
public static bool catchCallbackExceptions = false;
Dictionary _items;
Dictionary _toAdd;
List _toRemove;
List _pool;
TimersEngine _engine;
GameObject gameObject;
private static Timers _inst;
public static Timers inst
{
get
{
if (_inst == null)
_inst = new Timers();
return _inst;
}
}
public Timers()
{
_inst = this;
gameObject = new GameObject("[FairyGUI.Timers]");
gameObject.hideFlags = HideFlags.HideInHierarchy;
gameObject.SetActive(true);
Object.DontDestroyOnLoad(gameObject);
_engine = gameObject.AddComponent();
_items = new Dictionary();
_toAdd = new Dictionary();
_toRemove = new List();
_pool = new List(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.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();
}
}
}