Page 1 of 1

[Library] modrun - an alternative plug&play love.run with callbacks, custom events, and more.

Posted: Mon Jul 11, 2016 10:51 am
by asmageddon
Just something I've written for an older project of mine, and polished up recently. It doesn't modify any existing behavior, which means it's 100% safe to plug into any love project that doesn't replace love.run.

Its featureset is fairly simple: The primary features are:
  • Callbacks - The ability to attach any amount of handlers to events, along with error handlers, and "self objects", which will pass a given object as first argument to both the callback, and the error handler
  • Short circuiting - If a callback(including defaults, e.g. love.update) returns true, further callbacks will not be executed. Useful for, for example, UI capturing input
  • New events:
    • pre_update, post_update, for when you need to do things before/after the frame.
    • postprocess - For nonintrusive overlays, FPS counters, or postprocessing, when you can't rely on callback registration order
    • pre_quit - An event executed before quitting, allows for canceling it, to, say, display an "Are you sure?" dialog
    • dispatch - A catch-all event, to which all events(except itself, of course) are sent, can be used to dispatch all events to a library
    • And more! - modrun supports custom events, just register your event type, and use either modrun.push or love.event.push!
  • Support for FPS throttling that takes in mind all events, and automatically turns off when vsync is enabled
  • 100% plug and play - it won't even conflict with other copies of this module!
As a demonstration, here's a demo library for handling gamestates:

Code: Select all

local eventman = {}
local noop = function() end

function eventman:dispatch(event, ...)
    if eventman.state == nil then return end
    local handler = (eventman.state[event] or noop)
    handler(...)
end

function eventman:setState(state)
    love.event.push("exit_state", state)
    eventman.state = state
    love.event.push("enter_state", state)
end

function eventman:setup()
    runman.registerEventType("enter_state")
    runman.registerEventType("exit_state")
    runman.addCallback("dispatch", eventman.dispatch, eventman)
    
    return eventman
end

return eventman
And that's it folks! Any event callbacks you put on the state table will be called, including the custom enter/exit events and all love events. Similar scaffolding code can be written for various libraries which typically require manually calling their callbacks, including special cases for when you want to, say, feed them fabricated info, or short-circuit if your UI lib handled input already.

I've tested all of its features, and I believe that it should work without problems. The library is mostly complete, the only additions I'm debating are making base handlers callbacks like all others, adding support for "pre_" and "post_" variants of all events, for rudimentary event ordering or profiling, or priority numbers for callbacks, but I don't know if it'd actually be a worthwhile addition - in the end, you need to handle a lot of the event flow manually, as a part of your "framework", and at least with how I used it - handling most stuff with the dispatch event - callback priorities don't seem like something so important...

Well, either way, thanks for reading, I'd appreciate any input or code review :)

Links:

Re: [Library] modrun - an alternative plug&play love.run with callbacks, custom events, and more.

Posted: Mon Jul 11, 2016 2:48 pm
by bartbes
It's good to see an alternative implementation, we've had a long-standing issue on the tracker regarding our callbacks, and it'll be interesting to see how people react to this library.

I do have some comments though:
  • I think, if you cancel the quit event, either in pre_quit, or in quit itself, the quit event gets triggered. Yes, this means it gets triggered twice if cancelled in quit.
  • I wonder why you get the delta time 3 times, as they should all return the same value (lines 240, 247 and 249 as of commit 2de93ea).
  • You call love.graphics.present twice, once after draw, and once after postprocess, that does not work properly with double (or triple) buffering. In this case the easiest solution is to simply remove the first present call.

Re: [Library] modrun - an alternative plug&play love.run with callbacks, custom events, and more.

Posted: Tue Jul 12, 2016 8:41 am
by asmageddon
Oh. You're right, of course. I fixed them and pushed. I haven't removed pre_quit for now, although I feel like I should... I'm bad at decisions, sigh.

Regarding callbacks, what do you think about the dispatch callback? I thought about adding "callback groups", where it's possible to register a table instead of a single function, and dispatch various callbacks to it... but again, I'm just not sure. In my own projects, I always end up manually dispatching everything around with a single main dispatch callback, to get as tight of a grip on ordering and various quirks as possible. Same doubt as I have with priority numbers, really...

Either way, thanks for the feedback. More is always welcome.

Re: [Library] modrun - an alternative plug&play love.run with callbacks, custom events, and more.

Posted: Mon Jul 18, 2016 4:37 pm
by EntranceJew
I dig the idea. I don't really know what I would do with a library like this, though. Something that would be useful would be a fixedupdate implementation. (here's my fork of the linked library that merges in another fixedupdate implementation so that timescale works.)

Whenever I think of ways to improve love.run or events, I keep thinking of just implementing the behavior of hooker.lua which is simple enough to do in the existing event functions.