event handlers

Does Codea has any options to specify or create event handlers?

Reason I’m asking is: I wanted to create a Timer class. In order to work it has to update itself. The only way I found is to call it in the Main.lua inside the draw() function which gets updated every frame. So is there any option of having an equivalent (draw) inside a class (WITHOUT having to call it from inside the Main tab)? So I generally speaking of event handlers and callback functions.

cheers.

To my knowledge, this does not exist in Lua. The only object that works like an event handler is touch(touched). What do you want to do with your timer? For most uses i know of, the check by putting a call in draw() is enough. This limits the control rate to 60hz max. So yo have to create a timer class, with self.tStart and self.callback parameters that you set to what you want. You set self.tStart = ElapsedTime+ 1.5 if you want the timer to fire after 1.5s. When self.tStart > ElapsedTime then you run self.callback(). You also need a boolean self.done to run the callback only once. Or you can set self.tStart = ElapsedTime +100000 once it has fired.

thanks @Jmv38,

I have the timer working already. But it’s never wrong to have event handlers and listeners, e.g.

local function onEnterFrame(event)
     --equivalent to draw() in Codea
end
object:addEventListener("EnterFrame", onEnterFrame)

I think it would be much easiert to work through event programming, as for now with one “onEnterFrame” function, namely “draw()”. Somehow I think its messy. All the code, which needs to receive some changes, must go there and it results in a confusing code dump.

Has anyone further thoughts on this?

@se24vad, it should be feasible to use Lua coroutines to simulate event handlers using its multitasking capability. Havn’t seen much traffic on here regarding how to use them with Codea, but there’s a fair bit of info on the usual Lua wiki sites - probably worth a Google :wink:

.@andymac3d i have looked into coroutines for the IA of my ants, so i know a little bit about them now. My understanding is that it will not be a solution for event handling: they don’t do what is usually called multithreading: they do work like a independant thread, but they are completly managed by your lua program: they run only when you call them, in the draw() for instance, and then the rest of your program waits to have the contol back. It is not a parallel thead, but a concurrent thread.

Yes, I read yesterday something about coroutines. Unfortunately I’m not skilled eneugh to try it out myself, at least for now. But I think for best performance the events have to be build with C anyway, instead of Lua. Maybe @Simeon have any ideas… my last hope:)
Thank you all for the additional information and active discussion. Really a great community!

@Jmv38 , ah yes you’re correct - you’d have to write your own event scheduler (in the Draw loop) to manage each coroutine. A nice explanation and discussion regarding how they work is given here:

http://stackoverflow.com/questions/5128375/what-are-lua-coroutines-even-for-why-doesnt-this-code-work-as-i-expect-it

Also, @gunnar_z posted some excellent Codea examples of coroutines last year, which should help:

http://twolivesleft.com/Codea/Talk/discussion/818/coroutines-examples/p1

I may not understand fully the problem to which you are seeking a solution, but is the example code below relevant to it?



--# Main
--
-- Eventful
--

-- A handler for an event
function myHandler(sender)
    print("Sender was "..sender.name)
end

function setup()
    objects = {} -- Table of registered objects
    myButton1 = Button("Button 1", WIDTH / 2, HEIGHT / 2 + 40,
        100, 40, "Touch me!")
    -- Add an event and its handler
    myButton1.onTouched = myHandler
    myButton2 = Button("Button 2", WIDTH / 2, HEIGHT / 2 - 40,
        100, 40, "...Or me!")
    -- Add an event and its handler
    myButton2.onTouched = myHandler
end

function draw()
    background(0)
    for i, object in ipairs(objects) do
        object:draw()
    end
end

function touched(touch)
    for i, object in ipairs(objects) do
        object:touched(touch)  
    end
end
--# Button
Button = class()

function Button:init(name, x, y, w, h, title)
    self.name = name
    self.x = x
    self.y = y
    self.w = w
    self.h = h
    self.title = title
    -- Register object
    table.insert(objects, self)
end

function Button:draw()
    rectMode(CENTER)
    fill(255, 0, 0)
    rect(self.x, self.y, self.w, self.h)
    fill(255)
    textMode(CENTER)
    text(self.title, self.x, self.y)
end

function Button:touched(touch)
    if touch.x > self.x - self.w / 2 and
        touch.x < self.x + self.w / 2 and
        touch.y > self.y - self.h / 2 and
        touch.y < self.y + self.h / 2 then
        self.onTouched(self)
    end
end

The discussion was about a timeout event, not a touch event. Thanks anyhow.

yep, @Jmv38.
@mpilgrem I searched for a way of defining and dispatching custom events, similar to touch. I’m still not certain about how to go and whether it’s better to wait for codea 1.5.

Anyway, now, I’m not sure how an event dispatcher even works. Does anyone have an idea? I understand there has to be an event.register method, which stores all active events in, say, a table. But how does the rest work - how does a callback function know when the event was fired in order to run too?
Ideally I would want to have two functions: one for registering an event, say: registerEvent(“name”, callback), and one for removing events, like: removeEvent(“name”, callback). All other things should be tracked and fired automatically. Is that even possible? Can anyone describe how this should work?

If I understand right then I have some code for this in my User Interface class. In the class, I have the following snippets:

function UI:draw()
    self:checkTimers()

Then:

function UI:setTimer(t,f)
    table.insert(self.timers,{t + ElapsedTime,f})
end

function UI:checkTimers()
    for k,v in ipairs(self.timers) do
        if ElapsedTime > v[1] then
            if v[2]() then
                table.remove(self.timers,k)
            end
        end
    end
end

So the UI class does various things when its draw function is called and one of those is to check the timers. A timer is a time and a function. It fires if ElapsedTime is bigger than the registered time, and it deletes the timer if the callback returns true (giving the option of being called multiple times).

Though I’ve just noticed that it’s not good to alter a table when iterating over it so the code needs a little modification.