Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

event handlers

edited January 2013 in Questions Posts: 505

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.

Comments

  • Jmv38Jmv38 Mod
    Posts: 3,297

    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.

  • edited January 2013 Posts: 505

    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?

  • Posts: 398

    @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 ;-)

  • Jmv38Jmv38 Mod
    Posts: 3,297

    .@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.

  • edited January 2013 Posts: 505

    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!

  • edited January 2013 Posts: 398

    @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

  • Posts: 398

    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

  • Posts: 489

    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
    
  • Jmv38Jmv38 Mod
    Posts: 3,297

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

  • Posts: 505

    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?

  • Posts: 2,161

    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.

Sign In or Register to comment.