Posted 30 December 2012 - 04:22 AM
Event System 1.0
This API is simply a tool that makes concurrent event handlers easier. It allows you to create and remove event handlers, pause execution until a certain event occurs, and toggle termination.
Here's an example:
Function Listing:
es.addHandler([eventType,]function) - Adds a function as a handler for the specified event type. If no type is provided, it will be set to "general," which is triggered by all "vanilla" events.
es.removeHandler(function) - Removes an event handler.
es.setTerminate(boolean) - Sets whether the program should terminate on CTRL-T.
es.waitForEvent(eventType, [arg1,[arg2,[arg3]]]) - Freezes all event handling until the specified event occurs. This can be used to pause execution of a game until a user presses the space bar.
es.start() - Begin running the event system. Note that code following this call (except in event handler functions) will not be run until exit() has been called.
es.exit() - Terminate the event system.
Besides all the "vanilla" events, there are three new events: tick, begin, and end. "Tick" is called on every in-game tick. "Begin" is called when the event system starts (useful for running code only after it has started), and "end" is called then the program is terminated. This can be either by using CTRL-T (if termination is enabled) or by calling es.exit().
It is also possible to create your own events, and then call them with es.triggerEvent().
Code:
Pastebin
Changelog
V 1.0 :
Initial release.
This API is simply a tool that makes concurrent event handlers easier. It allows you to create and remove event handlers, pause execution until a certain event occurs, and toggle termination.
Here's an example:
Spoiler
os.loadAPI('es')
local ox = -1
local oy = -1
local function onClick(_,_,x,y)
ox = x
oy = y
end
local function onDrag(_,_,x,y)
paintutils.drawLine(ox,oy,x,y,2^14)
ox = x
oy = y
end
local function onEnd()
term.setBackgroundColor(2^15)
term.clear()
term.setCursorPos(1,1)
end
term.clear()
es.setTerminate(true)
es.addHandler('mouse_drag',onDrag)
es.addHandler('mouse_click',onClick)
es.addHandler('end',onEnd)
es.start()
Function Listing:
Spoiler
es.triggerEvent(eventType,[arg1,[arg2,[arg3]]]) - Trigger all functions registered as event handlers for that event type, passing the optional parameters to said function.es.addHandler([eventType,]function) - Adds a function as a handler for the specified event type. If no type is provided, it will be set to "general," which is triggered by all "vanilla" events.
es.removeHandler(function) - Removes an event handler.
es.setTerminate(boolean) - Sets whether the program should terminate on CTRL-T.
es.waitForEvent(eventType, [arg1,[arg2,[arg3]]]) - Freezes all event handling until the specified event occurs. This can be used to pause execution of a game until a user presses the space bar.
es.start() - Begin running the event system. Note that code following this call (except in event handler functions) will not be run until exit() has been called.
es.exit() - Terminate the event system.
Besides all the "vanilla" events, there are three new events: tick, begin, and end. "Tick" is called on every in-game tick. "Begin" is called when the event system starts (useful for running code only after it has started), and "end" is called then the program is terminated. This can be either by using CTRL-T (if termination is enabled) or by calling es.exit().
It is also possible to create your own events, and then call them with es.triggerEvent().
Code:
Spoiler
os.pullEvent = os.pullEventRaw
local running = false
local handlers = {}
local handlerkeys = {}
local eventWaiting = {}
local terminate = true
local function tickloop()
while true do
triggerEvent('tick')
sleep(0.05)
end
end
local function eventloop()
while true do
local ev, a, b, c = os.pullEventRaw()
if (ev == 'terminate' and terminate) or ev == 'internal-terminate' then
triggerEvent('end')
exit()
return
else
triggerEvent(ev,a,b,c)
triggerEvent('general',a,b,c)
end
end
end
function triggerEvent(ev,a,b,c)
if eventWaiting[1] ~= nil then
if ev ~= eventWaiting[1] then return false end
local argtable = {a,b,c}
for i = 2,#eventWaiting do
if eventWaiting[i] == nil then break end
if eventWaiting[i] ~= argtable[i-1] then
return false
end
end
eventWaiting = {}
end
if ev == nil or handlers == nil then return false end
if handlers[ev] == nil then return false end
if type(handlers[ev]) ~= 'table' and handlers[ev] ~= nil then
handlers[ev] = nil
end
if #handlers[ev] == 0 then return false end
for i = 1,#handlers[ev] do
handlers[ev][i](ev,a,b,c)
end
return true
end
function addHandler(etype, func)
if func == nil then
func = etype
etype = "general"
end
if type(func) ~= 'function' or type(etype) ~= 'string' then
if (not type(func) == 'string') and (not type(etype) == 'function') then
return false
end
if type(func) == 'string' and type(etype) == 'function' then
local inter = func
func = etype
etype = inter
end
end
if handlers[etype] == nil then
handlers[etype] = {}
table.insert(handlerkeys,etype)
end
for i = 1,#handlers[etype] do
if func == handlers[etype][i] then
return false
end
end
table.insert(handlers[etype],func)
return true
end
function removeHandler(func)
while true do
local found = false
for i = 1,#handlerkeys do
local k = handlerkeys[i]
for j = 1,#handlers[k] do
if handlers[k][j] == func then
handlers[k][j] = nil
found = true
break
end
end
if found then break end
end
if not found then return false end
end
local rmi = {}
for i = 1,#handlerkeys do
local k = handlerkeys[i]
if #handlers[k] == 0 then
handlers[k] = nil
table.insert(rmi,i)
end
end
for i = 1,#rmi do
table.remove(handlerkeys,rmi[i])
end
end
function exit()
handlers = nil
os.queueEvent('internal-terminate')
end
function waitForEvent(ev,a,b,c)
if ev == nil then return false end
eventWaiting = {ev,a,b,c}
return true
end
function start()
if not running then
running = true
triggerEvent('begin')
parallel.waitForAny(eventloop,tickloop)
end
end
function setTerminate(bool)
if type(bool) ~= 'boolean' then
return false
end
terminate = bool
end
Pastebin
Changelog
V 1.0 :
Initial release.