500 lines
13 KiB
C#
500 lines
13 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using XLua;
|
||
|
||
namespace Coolape
|
||
{
|
||
public class InvokeEx : MonoBehaviour
|
||
{
|
||
public bool canFixedUpdate = false;
|
||
public bool canUpdate = false;
|
||
public static InvokeEx self;
|
||
|
||
public InvokeEx ()
|
||
{
|
||
self = this;
|
||
}
|
||
|
||
Hashtable coroutineMap = Hashtable.Synchronized (new Hashtable ());
|
||
Hashtable coroutineIndex = Hashtable.Synchronized (new Hashtable ());
|
||
|
||
/// <summary>
|
||
/// Invoke4s the lua.回调lua函数, 等待时间
|
||
/// </summary>
|
||
/// <param name='callbakFunc'> only support Luafunction or Callback
|
||
/// Callbak func.
|
||
/// </param>
|
||
/// <param name='sec'>
|
||
/// Sec.
|
||
/// </param>
|
||
|
||
public static UnityEngine.Coroutine invoke (object callbakFunc, float sec)
|
||
{
|
||
return self.invoke4Lua (callbakFunc, sec);
|
||
}
|
||
|
||
public static UnityEngine.Coroutine invoke (object callbakFunc, object orgs, float sec)
|
||
{
|
||
return self.invoke4Lua (callbakFunc, orgs, sec);
|
||
}
|
||
|
||
public static UnityEngine.Coroutine invoke (object callbakFunc, object orgs, float sec, bool onlyOneCoroutine)
|
||
{
|
||
return self.invoke4Lua (callbakFunc, orgs, sec, onlyOneCoroutine);
|
||
}
|
||
|
||
public UnityEngine.Coroutine invoke4Lua (object callbakFunc, float sec)
|
||
{
|
||
return invoke4Lua (callbakFunc, "", sec);
|
||
}
|
||
|
||
public UnityEngine.Coroutine invoke4Lua (object callbakFunc, object orgs, float sec)
|
||
{
|
||
return invoke4Lua (callbakFunc, orgs, sec, false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Invoke4s the lua.
|
||
/// </summary>
|
||
/// <param name="callbakFunc">Callbak func.lua函数</param>
|
||
/// <param name="orgs">Orgs.参数</param>
|
||
/// <param name="sec">Sec.等待时间</param>
|
||
public UnityEngine.Coroutine invoke4Lua (object callbakFunc, object orgs, float sec, bool onlyOneCoroutine)
|
||
{
|
||
if (!gameObject.activeInHierarchy)
|
||
return null;
|
||
if (callbakFunc == null) {
|
||
Debug.LogError ("callbakFunc is null ......");
|
||
return null;
|
||
}
|
||
try {
|
||
UnityEngine.Coroutine ct = null;
|
||
if (onlyOneCoroutine) {
|
||
cleanCoroutines (callbakFunc);
|
||
}
|
||
int index = getCoroutineIndex (callbakFunc);
|
||
ct = StartCoroutine (doInvoke4Lua (callbakFunc, sec, orgs, index));
|
||
setCoroutine (callbakFunc, ct, index);
|
||
return ct;
|
||
} catch (System.Exception e) {
|
||
Debug.LogError (callbakFunc + ":" + e);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public int getCoroutineIndex (object callbakFunc)
|
||
{
|
||
object key = getKey4InvokeMap (callbakFunc, coroutineIndex);
|
||
int ret = MapEx.getInt (coroutineIndex, key);
|
||
coroutineIndex [key] = ret + 1;
|
||
return ret;
|
||
}
|
||
|
||
public void setCoroutineIndex (object callbakFunc, int val)
|
||
{
|
||
object key = getKey4InvokeMap (callbakFunc, coroutineIndex);
|
||
coroutineIndex [key] = val;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets the key4 invoke map.当直接传luafunction时,不能直接用,用Equals查找一下key
|
||
/// </summary>
|
||
/// <returns>The key4 invoke map.</returns>
|
||
/// <param name="callbakFunc">Callbak func.</param>
|
||
/// <param name="map">Map.</param>
|
||
public object getKey4InvokeMap (object callbakFunc, Hashtable map)
|
||
{
|
||
if (callbakFunc == null || map == null)
|
||
return callbakFunc;
|
||
object key = callbakFunc;
|
||
if (callbakFunc != null) {
|
||
NewList keys = ObjPool.listPool.borrowObject ();
|
||
keys.AddRange (map.Keys);
|
||
for (int i = 0; i < keys.Count; i++) {
|
||
if ((callbakFunc).Equals ((keys [i]))) {
|
||
key = keys [i];
|
||
break;
|
||
}
|
||
}
|
||
ObjPool.listPool.returnObject (keys);
|
||
keys = null;
|
||
}
|
||
return key;
|
||
}
|
||
|
||
public Hashtable getCoroutines (object callbakFunc)
|
||
{
|
||
object key = getKey4InvokeMap (callbakFunc, coroutineMap);
|
||
Hashtable ret = MapEx.getMap(coroutineMap, key);
|
||
ret = ret == null ? new Hashtable() : ret;
|
||
coroutineMap[key] = ret;
|
||
return ret;
|
||
}
|
||
|
||
public void setCoroutine (object callbakFunc, UnityEngine.Coroutine ct, int index)
|
||
{
|
||
object key = getKey4InvokeMap (callbakFunc, coroutineMap);
|
||
Hashtable map = getCoroutines (callbakFunc);
|
||
map [index] = ct;
|
||
coroutineMap [key] = map;
|
||
}
|
||
|
||
public void cleanCoroutines (object callbakFunc)
|
||
{
|
||
object key = getKey4InvokeMap (callbakFunc, coroutineMap);
|
||
Hashtable list = getCoroutines (callbakFunc);
|
||
foreach (DictionaryEntry cell in list) {
|
||
StopCoroutine ((UnityEngine.Coroutine)(cell.Value));
|
||
}
|
||
list.Clear ();
|
||
setCoroutineIndex (callbakFunc, 0);
|
||
coroutineMap.Remove (key);
|
||
}
|
||
|
||
public void rmCoroutine (object callbakFunc, int index)
|
||
{
|
||
object key = getKey4InvokeMap (callbakFunc, coroutineMap);
|
||
Hashtable list = getCoroutines (callbakFunc);
|
||
list.Remove (index);
|
||
coroutineMap [key] = list;
|
||
}
|
||
|
||
public static void cancelInvoke ()
|
||
{
|
||
self.cancelInvoke4Lua ();
|
||
}
|
||
|
||
public static void cancelInvoke (object callbakFunc)
|
||
{
|
||
self.cancelInvoke4Lua (callbakFunc);
|
||
}
|
||
|
||
public void cancelInvoke4Lua ()
|
||
{
|
||
cancelInvoke4Lua (null);
|
||
}
|
||
|
||
public void cancelInvoke4Lua (object callbakFunc)
|
||
{
|
||
if (callbakFunc == null) {
|
||
Hashtable list = null;
|
||
NewList keys = ObjPool.listPool.borrowObject();
|
||
keys.AddRange(coroutineMap.Keys);
|
||
object key = null;
|
||
for (int i = 0; i < keys.Count; i++) {
|
||
key = keys[i];
|
||
if (key != null)
|
||
{
|
||
list = getCoroutines(key);
|
||
foreach (DictionaryEntry cell in list)
|
||
{
|
||
StopCoroutine((UnityEngine.Coroutine)(cell.Value));
|
||
}
|
||
list.Clear();
|
||
}
|
||
}
|
||
coroutineMap.Clear ();
|
||
coroutineIndex.Clear ();
|
||
ObjPool.listPool.returnObject(keys);
|
||
} else {
|
||
cleanCoroutines (callbakFunc);
|
||
}
|
||
}
|
||
|
||
Queue invokeFuncs = new Queue ();
|
||
|
||
IEnumerator doInvoke4Lua (object callbakFunc, float sec, object orgs, int index)
|
||
{
|
||
yield return new WaitForSeconds (sec);
|
||
try {
|
||
rmCoroutine (callbakFunc, index);
|
||
Utl.doCallback (callbakFunc, orgs);
|
||
} catch (System.Exception e) {
|
||
string msg = "call err:doInvoke4Lua" + ",callbakFunc=[" + callbakFunc + "]";
|
||
Debug.LogError (msg);
|
||
Debug.LogError (e);
|
||
}
|
||
}
|
||
|
||
//================================================
|
||
// Fixed invoke 4 lua
|
||
//================================================
|
||
long _frameCounter = 0;
|
||
object locker=new object();
|
||
|
||
public long frameCounter {
|
||
get {
|
||
lock (locker) {
|
||
return _frameCounter;
|
||
}
|
||
}
|
||
set {
|
||
lock (locker) {
|
||
_frameCounter = value;
|
||
}
|
||
}
|
||
}
|
||
|
||
Hashtable _fixedInvokeMap = new Hashtable ();
|
||
|
||
public Hashtable fixedInvokeMap {
|
||
get {
|
||
if (_fixedInvokeMap == null) {
|
||
_fixedInvokeMap = Hashtable.Synchronized (new Hashtable ());
|
||
}
|
||
return _fixedInvokeMap;
|
||
}
|
||
}
|
||
|
||
public static void invokeByFixedUpdate (object luaFunc, float waitSec)
|
||
{
|
||
if (self == null) {
|
||
Debug.LogError ("Must attach InvokeEx on some gameObject!");
|
||
return;
|
||
}
|
||
self._fixedInvoke (luaFunc, null, waitSec);
|
||
}
|
||
|
||
public static void invokeByFixedUpdate (object luaFunc, object paras, float waitSec)
|
||
{
|
||
if (self == null) {
|
||
Debug.LogError ("Must attach InvokeEx on some gameObject!");
|
||
return;
|
||
}
|
||
self._fixedInvoke (luaFunc, paras, waitSec);
|
||
}
|
||
|
||
public void fixedInvoke4Lua (object luaFunc, float waitSec)
|
||
{
|
||
_fixedInvoke (luaFunc, null, waitSec);
|
||
}
|
||
|
||
public void fixedInvoke4Lua (object luaFunc, object paras, float waitSec)
|
||
{
|
||
_fixedInvoke (luaFunc, paras, waitSec);
|
||
}
|
||
|
||
void _fixedInvoke (object callback, object paras, float waitSec)
|
||
{
|
||
int waiteFrame = Mathf.CeilToInt (waitSec / Time.fixedDeltaTime);
|
||
waiteFrame = waiteFrame <= 0 ? 1 : waiteFrame; //至少有帧
|
||
long key = frameCounter + waiteFrame;
|
||
object[] content = new object[2];
|
||
// print (waiteFrame + "===" + key +"====" + luaFunc);
|
||
List<object[]> funcList = (List<object[]>)(fixedInvokeMap [key]);
|
||
if (funcList == null) {
|
||
funcList = new List<object[]> ();
|
||
}
|
||
content [0] = callback;
|
||
content [1] = paras;
|
||
funcList.Add (content);
|
||
fixedInvokeMap [key] = funcList;
|
||
if(!canFixedUpdate) {
|
||
canFixedUpdate = true;
|
||
}
|
||
}
|
||
|
||
public static void cancelInvokeByFixedUpdate ()
|
||
{
|
||
cancelInvokeByFixedUpdate (null);
|
||
}
|
||
|
||
public static void cancelInvokeByFixedUpdate (object func)
|
||
{
|
||
self.cancelFixedInvoke4Lua (func);
|
||
}
|
||
|
||
public void cancelFixedInvoke4Lua ()
|
||
{
|
||
cancelFixedInvoke4Lua (null);
|
||
}
|
||
|
||
public void cancelFixedInvoke4Lua (object func)
|
||
{
|
||
if (func == null) {
|
||
if (fixedInvokeMap != null) {
|
||
fixedInvokeMap.Clear ();
|
||
}
|
||
return;
|
||
}
|
||
List<object[]> list = null;
|
||
int count = 0;
|
||
object[] content = null;
|
||
foreach (DictionaryEntry item in fixedInvokeMap) {
|
||
list = (List<object[]>)(item.Value);
|
||
count = list.Count;
|
||
for (int i = count - 1; i >= 0; i--) {
|
||
content = list [i];
|
||
if (func.Equals (content [0])) {
|
||
list.RemoveAt (i);
|
||
}
|
||
}
|
||
|
||
if(list.Count == 0) {
|
||
fixedInvokeMap.Remove (item);
|
||
}
|
||
}
|
||
}
|
||
|
||
void doFixedInvoke (long key)
|
||
{
|
||
if (fixedInvokeMap == null && fixedInvokeMap.Count <= 0)
|
||
return;
|
||
if (fixedInvokeMap [key] == null)
|
||
return;
|
||
object[] content = null;
|
||
List<object[]> funcList = (List<object[]>)(fixedInvokeMap [key]);
|
||
object callback = null;
|
||
if (funcList != null) {
|
||
for (int i = 0; i < funcList.Count; i++) {
|
||
content = funcList [i];
|
||
callback = content [0];
|
||
Utl.doCallback (callback, content [1]);
|
||
}
|
||
funcList.Clear ();
|
||
funcList = null;
|
||
fixedInvokeMap.Remove (key);
|
||
}
|
||
}
|
||
|
||
//================================================
|
||
// FixedUpdate
|
||
//================================================
|
||
//帧统计
|
||
public virtual void FixedUpdate ()
|
||
{
|
||
if (!canFixedUpdate)
|
||
return;
|
||
frameCounter++;
|
||
if (fixedInvokeMap != null && fixedInvokeMap.Count > 0) {
|
||
doFixedInvoke (frameCounter);
|
||
} else {
|
||
canFixedUpdate = false;
|
||
frameCounter = 0;
|
||
}
|
||
}
|
||
|
||
//================================================
|
||
// Update
|
||
//================================================
|
||
ArrayList _invokeByUpdateList = null;
|
||
|
||
ArrayList invokeByUpdateList {
|
||
get {
|
||
if (_invokeByUpdateList == null) {
|
||
_invokeByUpdateList = ArrayList.Synchronized (new ArrayList ());
|
||
}
|
||
return _invokeByUpdateList;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Invoke4s the lua.
|
||
/// </summary>
|
||
/// <param name="callbakFunc">Callbak func.lua函数</param>
|
||
/// <param name="orgs">Orgs.参数</param>
|
||
/// <param name="sec">Sec.等待时间</param>
|
||
public static void invokeByUpdate (object callbakFunc, float sec)
|
||
{
|
||
self.updateInvoke (callbakFunc, sec);
|
||
}
|
||
|
||
public static void invokeByUpdate (object callbakFunc, object orgs, float sec)
|
||
{
|
||
self.updateInvoke (callbakFunc, orgs, sec);
|
||
}
|
||
|
||
public void updateInvoke (object callbakFunc, float sec)
|
||
{
|
||
updateInvoke (callbakFunc, null, sec);
|
||
}
|
||
|
||
public void updateInvoke (object callbakFunc, object orgs, float sec)
|
||
{
|
||
if (callbakFunc == null)
|
||
return;
|
||
NewList list = ObjPool.listPool.borrowObject ();
|
||
list.Add (callbakFunc);
|
||
list.Add (orgs);
|
||
list.Add (Time.unscaledTime + sec);
|
||
invokeByUpdateList.Add (list);
|
||
canUpdate = true;
|
||
}
|
||
|
||
public static void cancelInvokeByUpdate ()
|
||
{
|
||
self.cancelUpdateInvoke ();
|
||
}
|
||
|
||
public static void cancelInvokeByUpdate (object callbakFunc)
|
||
{
|
||
self.cancelUpdateInvoke (callbakFunc);
|
||
}
|
||
|
||
public void cancelUpdateInvoke ()
|
||
{
|
||
cancelUpdateInvoke (null);
|
||
}
|
||
|
||
public void cancelUpdateInvoke (object callbakFunc)
|
||
{
|
||
NewList list = null;
|
||
int count = invokeByUpdateList.Count;
|
||
if (callbakFunc == null) {
|
||
for (int i = 0; i < count; i++) {
|
||
list = (NewList)(invokeByUpdateList [i]);
|
||
ObjPool.listPool.returnObject (list);
|
||
}
|
||
list = null;
|
||
invokeByUpdateList.Clear ();
|
||
return;
|
||
}
|
||
for (int i = count - 1; i >= 0; i--) {
|
||
list = (NewList)(invokeByUpdateList [i]);
|
||
if (callbakFunc.Equals (list [0])) {
|
||
invokeByUpdateList.RemoveAt (i);
|
||
ObjPool.listPool.returnObject (list);
|
||
}
|
||
}
|
||
list = null;
|
||
}
|
||
|
||
void doInvokeByUpdate ()
|
||
{
|
||
int count = invokeByUpdateList.Count;
|
||
NewList list = null;
|
||
object callbakFunc;
|
||
object orgs;
|
||
float sec;
|
||
int index = 0;
|
||
while (index < invokeByUpdateList.Count) {
|
||
list = (NewList)(invokeByUpdateList [index]);
|
||
callbakFunc = list [0];
|
||
orgs = list [1];
|
||
sec = (float)(list [2]);
|
||
if (sec <= Time.unscaledTime)
|
||
{
|
||
invokeByUpdateList.RemoveAt(index);
|
||
Utl.doCallback (callbakFunc, orgs);
|
||
ObjPool.listPool.returnObject (list);
|
||
} else {
|
||
index++;
|
||
}
|
||
}
|
||
list = null;
|
||
}
|
||
|
||
public virtual void Update ()
|
||
{
|
||
if (!canUpdate)
|
||
return;
|
||
if (invokeByUpdateList.Count > 0) {
|
||
doInvokeByUpdate ();
|
||
} else {
|
||
canUpdate = false;
|
||
}
|
||
}
|
||
}
|
||
}
|