One unused set of abstractions for animations is enough.
N2TXVDIYJWHD2CA4MA4O6P74FBAA5CLNCMZNOXRSQH5R24RH7Q2QC
2NEL7TGNFKBDFSJMCHLI5UQ65UWYSMDZPG3ZV24TOFRPJK2NQBLAC
R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC
2Q437U4FVEYO3Y22OC3NC5MAYVEDTTCWCRJHBKHKWA4WZSPWYUDQC
PFSJMMNJSMEYMQLHDXXNUT2DULCLKWIPEICMVBEYY6E4OSCBJWGAC
SW5GN5LPJX6DBQ7IEE4WYZ6XZLLHXNO7BENCQ6LRCYMIBKNZQFMQC
ZM7NOBRMD5HHA35Y4JDC76EOA2RD4KQOQCPURXYKXA6ABMKOJIGQC
5RUFNRJOK3PXQKJTPDEN5K5PI67MGB25QUA44WOCCH2O5KHXT45QC
UEG224LHBOPWSKOVXTKVAUEL47HET566LJF7ZSWVKMMLBSJWUHFAC
-- update any in-progress animations
-- return whether any work remains
draw_next_frames_of_animations = function()
local a = Animations_in_progress
for i=#a,1,-1 do
if coroutine.status(a[i].co) == 'dead' then
table.remove(a, i)
else
local status, err = coroutine.resume(a[i].co)
if status == false then error(err) end
end
end
return #a > 0
end
-- A debugging aid to help animate intermediate results within f.
-- Pause animation in the current frame using loiter().
-- Try to only have one such call in your program.
-- You can have multiple, but things might get confusing if one of them indirectly calls the other,
-- or more generally if a single function ever loiters sometimes under the call tree of one and sometimes under the other.
enable_loiter = function(f, ...)
local args = {...}
Error_with_callstack = nil
local co = coroutine.create(
function()
xpcall(function()
f(unpack(args))
end,
save_callstack)
end)
coroutine.resume(co, ...)
if Error_with_callstack then
error(Error_with_callstack)
end
table.insert(Debug_animations_in_progress, {co=co, next_run=Current_time+0.3})
end