291 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			291 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C#
		
	
/*
 | 
						||
Copyright (c) 2015-2017 topameng(topameng@qq.com)
 | 
						||
 | 
						||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
						||
of this software and associated documentation files (the "Software"), to deal
 | 
						||
in the Software without restriction, including without limitation the rights
 | 
						||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
						||
copies of the Software, and to permit persons to whom the Software is
 | 
						||
furnished to do so, subject to the following conditions:
 | 
						||
 | 
						||
The above copyright notice and this permission notice shall be included in all
 | 
						||
copies or substantial portions of the Software.
 | 
						||
 | 
						||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
						||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
						||
SOFTWARE.
 | 
						||
*/
 | 
						||
using UnityEngine;
 | 
						||
using LuaInterface;
 | 
						||
using System;
 | 
						||
using System.Collections;
 | 
						||
 | 
						||
public static class LuaCoroutine
 | 
						||
{
 | 
						||
	private static MonoBehaviour mb = null;
 | 
						||
	private static string strCo =
 | 
						||
        @"
 | 
						||
        local _WaitForSeconds, _WaitForFixedUpdate, _WaitForEndOfFrame, _Yield, _StopCoroutine = WaitForSeconds, WaitForFixedUpdate, WaitForEndOfFrame, Yield, StopCoroutine        
 | 
						||
        local error = error
 | 
						||
        local debug = debug
 | 
						||
        local coroutine = coroutine
 | 
						||
        local comap = {}
 | 
						||
        setmetatable(comap, {__mode = 'k'})
 | 
						||
 | 
						||
        function _resume(co)
 | 
						||
            if comap[co] then
 | 
						||
                comap[co] = nil
 | 
						||
                local flag, msg = coroutine.resume(co)
 | 
						||
                    
 | 
						||
                if not flag then
 | 
						||
                    msg = debug.traceback(co, msg)
 | 
						||
                    error(msg)
 | 
						||
                end
 | 
						||
            end        
 | 
						||
        end
 | 
						||
 | 
						||
        function WaitForSeconds(t)
 | 
						||
            local co = coroutine.running()
 | 
						||
            local resume = function()                    
 | 
						||
                _resume(co)                     
 | 
						||
            end
 | 
						||
            
 | 
						||
            comap[co] = _WaitForSeconds(t, resume)
 | 
						||
            return coroutine.yield()
 | 
						||
        end
 | 
						||
 | 
						||
        function WaitForFixedUpdate()
 | 
						||
            local co = coroutine.running()
 | 
						||
            local resume = function()          
 | 
						||
                _resume(co)     
 | 
						||
            end
 | 
						||
        
 | 
						||
            comap[co] = _WaitForFixedUpdate(resume)
 | 
						||
            return coroutine.yield()
 | 
						||
        end
 | 
						||
 | 
						||
        function WaitForEndOfFrame()
 | 
						||
            local co = coroutine.running()
 | 
						||
            local resume = function()        
 | 
						||
                _resume(co)     
 | 
						||
            end
 | 
						||
        
 | 
						||
            comap[co] = _WaitForEndOfFrame(resume)
 | 
						||
            return coroutine.yield()
 | 
						||
        end
 | 
						||
 | 
						||
        function Yield(o)
 | 
						||
            local co = coroutine.running()
 | 
						||
            local resume = function()        
 | 
						||
                _resume(co)     
 | 
						||
            end
 | 
						||
        
 | 
						||
            comap[co] = _Yield(o, resume)
 | 
						||
            return coroutine.yield()
 | 
						||
        end
 | 
						||
 | 
						||
        function StartCoroutine(func)
 | 
						||
            local co = coroutine.create(func)                       
 | 
						||
            local flag, msg = coroutine.resume(co)
 | 
						||
 | 
						||
            if not flag then
 | 
						||
                msg = debug.traceback(co, msg)
 | 
						||
                error(msg)
 | 
						||
            end
 | 
						||
 | 
						||
            return co
 | 
						||
        end
 | 
						||
 | 
						||
        function StopCoroutine(co)
 | 
						||
            local _co = comap[co]
 | 
						||
 | 
						||
            if _co == nil then
 | 
						||
                return
 | 
						||
            end
 | 
						||
 | 
						||
            comap[co] = nil
 | 
						||
            _StopCoroutine(_co)
 | 
						||
        end
 | 
						||
        ";
 | 
						||
 | 
						||
    public static void Register(LuaState state, MonoBehaviour behaviour)
 | 
						||
    {
 | 
						||
        state.BeginModule(null);
 | 
						||
        state.RegFunction("WaitForSeconds", _WaitForSeconds);
 | 
						||
        state.RegFunction("WaitForFixedUpdate", WaitForFixedUpdate);
 | 
						||
        state.RegFunction("WaitForEndOfFrame", WaitForEndOfFrame);
 | 
						||
        state.RegFunction("Yield", Yield);
 | 
						||
        state.RegFunction("StopCoroutine", StopCoroutine);
 | 
						||
        state.RegFunction("WrapLuaCoroutine", WrapLuaCoroutine);
 | 
						||
        state.EndModule();
 | 
						||
 | 
						||
        state.LuaDoString(strCo, "LuaCoroutine.cs");
 | 
						||
        mb = behaviour;
 | 
						||
    }
 | 
						||
 | 
						||
    //另一种方式,非脚本回调方式(用脚本方式更好,可避免lua_yield异常出现在c#函数中)
 | 
						||
    /*[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
    static int WaitForSeconds(IntPtr L)
 | 
						||
    {
 | 
						||
        try
 | 
						||
        {
 | 
						||
            LuaState state = LuaState.Get(L);
 | 
						||
            LuaDLL.lua_pushthread(L);
 | 
						||
            LuaThread thread = ToLua.ToLuaThread(L, -1);
 | 
						||
            float sec = (float)LuaDLL.luaL_checknumber(L, 1);
 | 
						||
            mb.StartCoroutine(CoWaitForSeconds(sec, thread));
 | 
						||
            return LuaDLL.lua_yield(L, 0);
 | 
						||
        }
 | 
						||
        catch (Exception e)
 | 
						||
        {
 | 
						||
            return LuaDLL.toluaL_exception(L, e);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    static IEnumerator CoWaitForSeconds(float sec, LuaThread thread)
 | 
						||
    {
 | 
						||
        yield return new WaitForSeconds(sec);
 | 
						||
        thread.Resume();
 | 
						||
    }*/
 | 
						||
 | 
						||
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
	private static int _WaitForSeconds(IntPtr L)
 | 
						||
    {
 | 
						||
        try
 | 
						||
        {
 | 
						||
            float sec = (float)LuaDLL.luaL_checknumber(L, 1);
 | 
						||
            LuaFunction func = ToLua.ToLuaFunction(L, 2);
 | 
						||
            Coroutine co = mb.StartCoroutine(CoWaitForSeconds(sec, func));
 | 
						||
            ToLua.PushSealed(L, co);
 | 
						||
            return 1;
 | 
						||
        }
 | 
						||
        catch (Exception e)
 | 
						||
        {
 | 
						||
            return LuaDLL.toluaL_exception(L, e);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
	private static IEnumerator CoWaitForSeconds(float sec, LuaFunction func)
 | 
						||
    {
 | 
						||
        yield return new WaitForSeconds(sec);
 | 
						||
        func.Call();
 | 
						||
    }
 | 
						||
 | 
						||
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
	private static int WaitForFixedUpdate(IntPtr L)
 | 
						||
    {
 | 
						||
        try
 | 
						||
        {
 | 
						||
            LuaFunction func = ToLua.ToLuaFunction(L, 1);
 | 
						||
            Coroutine co = mb.StartCoroutine(CoWaitForFixedUpdate(func));
 | 
						||
            ToLua.PushSealed(L, co);
 | 
						||
            return 1;
 | 
						||
        }
 | 
						||
        catch (Exception e)
 | 
						||
        {
 | 
						||
            return LuaDLL.toluaL_exception(L, e);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
	private static IEnumerator CoWaitForFixedUpdate(LuaFunction func)
 | 
						||
    {
 | 
						||
        yield return new WaitForFixedUpdate();
 | 
						||
        func.Call();
 | 
						||
    }
 | 
						||
 | 
						||
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
	private static int WaitForEndOfFrame(IntPtr L)
 | 
						||
    {
 | 
						||
        try
 | 
						||
        {
 | 
						||
            LuaFunction func = ToLua.ToLuaFunction(L, 1);
 | 
						||
            Coroutine co = mb.StartCoroutine(CoWaitForEndOfFrame(func));
 | 
						||
            ToLua.PushSealed(L, co);
 | 
						||
            return 1;
 | 
						||
        }
 | 
						||
        catch (Exception e)
 | 
						||
        {
 | 
						||
            return LuaDLL.toluaL_exception(L, e);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
	private static IEnumerator CoWaitForEndOfFrame(LuaFunction func)
 | 
						||
    {
 | 
						||
        yield return new WaitForEndOfFrame();
 | 
						||
        func.Call();
 | 
						||
    }
 | 
						||
 | 
						||
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
	private static int Yield(IntPtr L)
 | 
						||
    {
 | 
						||
        try
 | 
						||
        {
 | 
						||
            object o = ToLua.ToVarObject(L, 1);
 | 
						||
            LuaFunction func = ToLua.ToLuaFunction(L, 2);
 | 
						||
            Coroutine co = mb.StartCoroutine(CoYield(o, func));
 | 
						||
            ToLua.PushSealed(L, co);
 | 
						||
            return 1;
 | 
						||
        }
 | 
						||
        catch (Exception e)
 | 
						||
        {
 | 
						||
            return LuaDLL.toluaL_exception(L, e);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
	private static IEnumerator CoYield(object o, LuaFunction func)
 | 
						||
    {
 | 
						||
        if (o is IEnumerator)
 | 
						||
        {
 | 
						||
            yield return mb.StartCoroutine((IEnumerator)o);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            yield return o;
 | 
						||
        }
 | 
						||
 | 
						||
        func.Call();
 | 
						||
    }
 | 
						||
 | 
						||
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
	private static int StopCoroutine(IntPtr L)
 | 
						||
    {
 | 
						||
        try
 | 
						||
        {
 | 
						||
            Coroutine co = (Coroutine)ToLua.CheckObject(L, 1, typeof(Coroutine));
 | 
						||
            mb.StopCoroutine(co);
 | 
						||
            return 0;
 | 
						||
        }
 | 
						||
        catch (Exception e)
 | 
						||
        {
 | 
						||
            return LuaDLL.toluaL_exception(L, e);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
 | 
						||
    private static int WrapLuaCoroutine(IntPtr L)
 | 
						||
    {
 | 
						||
        LuaFunction func = ToLua.ToLuaFunction(L, 1);
 | 
						||
        IEnumerator enumerator = CoWrap(func);
 | 
						||
        ToLua.Push(L, enumerator);
 | 
						||
        return 1;
 | 
						||
    }
 | 
						||
 | 
						||
    private static IEnumerator CoWrap(LuaFunction func)
 | 
						||
    {
 | 
						||
        if (func == null)
 | 
						||
        {
 | 
						||
            yield break;
 | 
						||
        }
 | 
						||
 | 
						||
        while (func.Invoke<bool>())
 | 
						||
        {
 | 
						||
            yield return null;
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 |