256 lines
6.0 KiB
Lua
256 lines
6.0 KiB
Lua
local create = coroutine.create
|
|
local running = coroutine.running
|
|
local resume = coroutine.resume
|
|
local yield = coroutine.yield
|
|
local getinfo = debug.getinfo
|
|
local corTimers = {}
|
|
local corUpdates = {}
|
|
local corInRequest = {}
|
|
local stoppedCor = {}
|
|
local waitStepCors = {}
|
|
local waitStepCorCount = 0
|
|
|
|
local corToDebugInfo = {}
|
|
setmetatable(corToDebugInfo, {
|
|
__mode = "kv"
|
|
})
|
|
|
|
setmetatable(stoppedCor, {
|
|
__mode = "k"
|
|
})
|
|
|
|
local emptyFun = function() end
|
|
local begin_unity_sample = emptyFun
|
|
local end_unity_sample = emptyFun
|
|
local getFileInfo = emptyFun
|
|
|
|
if unity_sample and unity_sample.begin_unity_sample then
|
|
|
|
if DEVELOPMENT_BUILD or UNITY_EDITOR then
|
|
getFileInfo = function (co)
|
|
local info = getinfo(4,"Sl")
|
|
corToDebugInfo[co] = (info.short_src..":"..info.currentline):match("([^\\/]+)$")
|
|
end
|
|
|
|
begin_unity_sample = unity_sample.begin_unity_sample
|
|
end_unity_sample = unity_sample.end_unity_sample
|
|
end
|
|
end
|
|
function coroutine.start(f)
|
|
local co = create(f)
|
|
getFileInfo(co)
|
|
if running() == nil then
|
|
|
|
begin_unity_sample(corToDebugInfo[co])
|
|
local flag, msg = resume(co)
|
|
end_unity_sample()
|
|
if not flag then
|
|
logger.error(debug.traceback(co, msg), corToDebugInfo[co])
|
|
end
|
|
else
|
|
|
|
local action = function()
|
|
if not corTimers[co] then
|
|
|
|
return
|
|
end
|
|
corTimers[co] = nil
|
|
begin_unity_sample(corToDebugInfo[co])
|
|
local flag, msg = resume(co)
|
|
end_unity_sample()
|
|
if not flag then
|
|
logger.error(debug.traceback(co, msg), corToDebugInfo[co])
|
|
end
|
|
end
|
|
|
|
local timer = TimerManager:StartFrameTimer(0, action)
|
|
corTimers[co] = timer
|
|
end
|
|
|
|
return co
|
|
end
|
|
|
|
function coroutine.wait(t, co)
|
|
co = co or running()
|
|
if stoppedCor[co] then
|
|
return yield()
|
|
end
|
|
|
|
local action = function()
|
|
if not corTimers[co] then
|
|
|
|
return
|
|
end
|
|
corTimers[co] = nil
|
|
begin_unity_sample(corToDebugInfo[co])
|
|
local flag, msg = resume(co)
|
|
end_unity_sample()
|
|
if not flag then
|
|
logger.error(debug.traceback(co, msg), corToDebugInfo[co])
|
|
return
|
|
end
|
|
end
|
|
|
|
local timer = TimerManager:StartTimer(t, action)
|
|
corTimers[co] = timer
|
|
return yield()
|
|
end
|
|
|
|
local stepUpdateKey
|
|
|
|
function coroutine.step(co)
|
|
co = co or running()
|
|
if stoppedCor[co] then
|
|
return yield()
|
|
end
|
|
|
|
if not stepUpdateKey then
|
|
stepUpdateKey = LuaUpdate:Add("Tick", coroutine._stepUpdate)
|
|
end
|
|
|
|
waitStepCorCount = waitStepCorCount + 1
|
|
waitStepCors[waitStepCorCount] = co
|
|
return yield()
|
|
end
|
|
|
|
function coroutine.waitForRenderDone(co)
|
|
|
|
|
|
|
|
|
|
co = co or running()
|
|
if stoppedCor[co] then
|
|
return yield()
|
|
end
|
|
|
|
local key = LuaUpdate:Add("RenderDone", function()
|
|
LuaUpdate:Remove(corUpdates[co])
|
|
corUpdates[co] = nil
|
|
|
|
begin_unity_sample(corToDebugInfo[co])
|
|
local flag, msg = resume(co)
|
|
end_unity_sample()
|
|
if not flag then
|
|
logger.error(debug.traceback(co, msg), corToDebugInfo[co])
|
|
end
|
|
|
|
return true
|
|
end)
|
|
corUpdates[co] = key
|
|
|
|
return yield()
|
|
end
|
|
|
|
function coroutine._stepUpdate()
|
|
|
|
local count = waitStepCorCount
|
|
waitStepCorCount = 0
|
|
local cors = waitStepCors
|
|
waitStepCors = {}
|
|
for k = 1, count do
|
|
local stepCo = cors[k]
|
|
if stepCo and not stoppedCor[stepCo] then
|
|
begin_unity_sample(corToDebugInfo[stepCo])
|
|
local flag, msg = resume(stepCo)
|
|
end_unity_sample()
|
|
if not flag then
|
|
logger.error(debug.traceback(stepCo, msg), corToDebugInfo[stepCo])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function coroutine.stop(co)
|
|
stoppedCor[co] = true
|
|
local timer = corTimers[co]
|
|
if timer ~= nil then
|
|
TimerManager:ClearTimer(timer)
|
|
corTimers[co] = nil
|
|
end
|
|
corInRequest[co] = nil
|
|
local updateKey = corUpdates[co]
|
|
if updateKey then
|
|
LuaUpdate:Remove(updateKey)
|
|
end
|
|
for k = 1, waitStepCorCount do
|
|
if waitStepCors[k] == co then
|
|
waitStepCors[k] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function coroutine.waitAsyncRequest(request, co)
|
|
co = co or running()
|
|
if stoppedCor[co] then
|
|
return yield()
|
|
end
|
|
|
|
corInRequest[co] = true
|
|
|
|
local action = function()
|
|
if not corInRequest[co] then
|
|
|
|
return
|
|
end
|
|
|
|
corInRequest[co] = nil
|
|
corTimers[co] = nil
|
|
|
|
begin_unity_sample(corToDebugInfo[co])
|
|
local flag, msg = resume(co)
|
|
end_unity_sample()
|
|
|
|
if not flag then
|
|
logger.error(debug.traceback(co, msg), corToDebugInfo[co])
|
|
return
|
|
end
|
|
end
|
|
|
|
local timer = TimerManager:StartFrameTimer(0, function()
|
|
request(action)
|
|
end)
|
|
corTimers[co] = timer
|
|
return yield()
|
|
end
|
|
|
|
coroutine.Tick = -1
|
|
coroutine.LateTick = -2
|
|
coroutine.TailTick = -3
|
|
|
|
function coroutine.waitCondition(condition, checkInterval, co)
|
|
co = co or running()
|
|
if stoppedCor[co] then
|
|
return yield()
|
|
end
|
|
|
|
checkInterval = checkInterval or coroutine.Tick
|
|
local tickName
|
|
if checkInterval == coroutine.Tick then
|
|
tickName = "Tick"
|
|
elseif checkInterval == coroutine.LateTick then
|
|
tickName = "LateTick"
|
|
elseif checkInterval == coroutine.TailTick then
|
|
tickName = "TailTick"
|
|
end
|
|
|
|
local key = LuaUpdate:Add(tickName, function()
|
|
if condition() then
|
|
LuaUpdate:Remove(corUpdates[co])
|
|
corUpdates[co] = nil
|
|
|
|
begin_unity_sample(corToDebugInfo[co])
|
|
local flag, msg = resume(co)
|
|
end_unity_sample()
|
|
if not flag then
|
|
logger.error(debug.traceback(co, msg), corToDebugInfo[co])
|
|
end
|
|
|
|
return true
|
|
end
|
|
end)
|
|
corUpdates[co] = key
|
|
|
|
return yield()
|
|
end
|