addListener only handled events pushed through love.event – so love.draw, love.update, love.load, and love.errhand could not be 'listened to' with addListener.airstruck wrote:It would have been possible with addListener, of course.
I LÖVE callbacks
- slime
- Solid Snayke
- Posts: 3161
- Joined: Mon Aug 23, 2010 6:45 am
- Location: Nova Scotia, Canada
- Contact:
Re: I LÖVE callbacks
Re: I LÖVE callbacks
I rememberslime wrote:addListener only handled events pushed through love.event – so love.draw, love.update, love.load, and love.errhand could not be 'listened to' with addListener.airstruck wrote:It would have been possible with addListener, of course.
I thought it was a step in the right direction, anyway. Library code requiring the user to do something in draw and update isn't nearly as gruesome as requiring them to do stuff in the 20-odd handlers that were covered by addListener (I'm assuming most library code doesn't want to do anything with errhand).
Re: I LÖVE callbacks
I would probably ask that they standardized on the names to match the event they are intended to be called from, and take the parameters that the event is provided. At the very least this would make it so we could write a standard wrapper, which I'm going to spitball here:airstruck wrote:I think it is. Doesn't mean it's a great standard. Consider this code:
Code: Select all
function love.draw (...) somelibrary.handledraw(...) end function love.resize (...) somelibrary.handleresize(...) end function love.mousepressed (...) somelibrary.handlemousepressed(...) end function love.mousereleased (...) somelibrary.handlemousereleased(...) end function love.mousemoved (...) somelibrary.handlemousemoved(...) end function love.keypressed (...) somelibrary.handlekeypressed(...) end function love.keyreleased (...) somelibrary.handlekeyreleased(...) end function love.textinput (...) somelibrary.handletextinput(...) end -- and so on
Code: Select all
StandardHandler = {}
function StandardHandler.AddLibrary(lib)
local wrapper = {}
for _, v in ipairs { 'update', 'draw', 'keypressed' } do -- you can fill in the rest
wrapper[v] = lib[v] or function() end
end
StandardHandler[#StandardHandler+1] = wrapper
end
function StandardHandler.call(event, ...)
for _, wrapper in ipairs(StandardHandler) do
wrapper[event](...)
end
end
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: I LÖVE callbacks
Consider that if a library needs to be wired to many different subsystems, the problem might be that the library is trying to do too many things. A library must encapsulate, but it must also have focus. When possible, split big libraries into several smaller ones (or simply ignore libraries which require too much wiring, as they are probably doing too much stuff).airstruck wrote:Consider this code:
Code: Select all
function love.draw (...) somelibrary.handledraw(...) end function love.resize (...) somelibrary.handleresize(...) end ... -- and so on
In my view that's annoying and borderline unacceptable. The point of library code is to encapsulate functionality. When you have to wire up a shit ton of events by hand like this, that's the opposite of encapsulating functionality.
When I write def I mean function.
Re: I LÖVE callbacks
You can sort of do this already with pairs(love.handlers). That leaves out the callbacks that aren't event handlers, but I think that's only update, draw and errhand. That still leaves library authors to choose between having the user wire up a bunch of events or destructively hooking everything in library code.Inny wrote:I would probably ask that they standardized on the names to match the event they are intended to be called from, and take the parameters that the event is provided. At the very least this would make it so we could write a standard wrapper
That example draws from some code in a UI library I'm working on. It does need to use all of those events; it also uses wheelmoved which I forgot to add to that example, and will likely use one or two more window-related events in the future.kikito wrote:Consider that if a library needs to be wired to many different subsystems, the problem might be that the library is trying to do too many things.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: I LÖVE callbacks
Please realize that what I am going to say is not in any way a personal attack and I don't mean to discourage a fellow library developer from working on their own library. But it seems to me that your quote proves my point more than counter it. My opinion is that your library seems to be doing more stuff than it should (as a single library).airstruck wrote:some code in a UI library I'm working on. It does need to use all of those events; it also uses wheelmoved which I forgot to add to that example, and will likely use one or two more window-related events in the future.
When I write def I mean function.
Re: I LÖVE callbacks
I'd be interested to hear your thoughts on how that could be improved.kikito wrote:My opinion is that your library seems to be doing more stuff than it should (as a single library).
As a UI library, it needs to draw stuff to the screen, so it needs love.draw. It captures mouse input events, because it's focused on primarily mouse-driven UIs (I'll add better touch support in the future). It provides easy integration of keyboard shortcuts, for example you can give a widget a property like `shortcut = "ctrl-s"`, so it captures keyboard input events. It captures text events so the user can type in the text box widget. And it provides a responsive layout manager that reshapes the UI when the shape of the window changes, so it captures the window resize event. That pretty much only leaves out gamepad events, which I don't care about at the moment.
Are you suggesting that the stuff that captures user input (from mouse, keyboard, window manager) should be moved into a separate library? If it were, would that solve the problem with the user having to wire up events or the library having to hook them?
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: I LÖVE callbacks
Not necessarily. All I have said is that they should not be on the GUI but somewhere else. Where this is, exactly, depends on the particular game we're talking about.airstruck wrote:Are you suggesting that the stuff that captures user input (from mouse, keyboard, window manager) should be moved into a separate library?
What I am saying is that your GUI library should not be concerned about how the mouse, the keyboard, and the pads work, because that is not its job. It should not be doing that.
Let's talk about what GUI needs, as inputs:
- 4 directional inputs related to the "currently highlighted control" (move the selection up, down, left, right). These are usually the arrow keys in the keyboard and the d-pad in a joystick. But a GUI library should not know that. It just needs someone to tell it "move the highlighted item up". Maybe the programmer wants to simulate that the player is drunk, and changes the inputs on purpose. The GUI can't know that.
- If there is a pointing devise (like a mouse), then the library needs to interact with it. But there might be screen transformations at play (cameras, resolution changes, retina display corrections, etc). So the GUI should not "take over the mouse". It needs someone to tell it "for you, the mouse is here". Maybe in the current game state the GUI does not need to know about the mouse, even if it's there. Maybe the programmer is simulating a software mouse in a tutorial. It is not up to the gui to know that.
- The library needs a way to tell when the currently highlighted control is activated. This could be the "enter key", or the "joystick A button", or the mouse button, or a touch in a touch screen. But again, the library does not need to know this. It just needs someone to tell it "activate the highlighted control now".
- In some particular cases, when dealing with text fields, it also needs to know the keys the user presses. Even in that case, it is not ok that it simply "takes control of the global keyboard". There are scenarios for this: maybe the programmer using the library wants to simulate an NPC using the GUI to perform some action. Maybe there is some sort of "macro" in place by which pressing a button, several controls change, and some input fields are automatically filled up. The point again is that the gui should "present the input for key presses" and allow the programmer to use it, as opposed to "grabbing the global keyboard".
Output-wise, there are two main thing a GUI does:
- The first thing is changing game state. This can be done with Lua functions, and I think is not relevant for this particular conversation.
- The second one is drawing itself. But this does not mean that all that love.draw needs to do is drawing the GUI. In games GUIs are quite often drawn along something else. Maybe the gui is a minimap with buttons on the side, like the bottom of a Starcraft game. Maybe the user wants to apply filters to the whole screen (i.e. a screenshake) before drawing the GUI. The GUI must not know about this. It just needs to draw itself when it is told to.
This said, it's desirable to include examples about how to hook things up in the docs and demos. You might even provide "default hooking mechanisms for the most obvious options"; but these should be opt-in and easily deactivable.
I am not sure I would characterize that as a "problem". To me it sounds like ... programming. It is on the same category as "The user needs to write a for loop every time he wants to iterate over a table". Maybe I am not understanding your concern correctly.airstruck wrote:If it were, would that solve the problem with the user having to wire up events or the library having to hook them?
When I write def I mean function.
Re: I LÖVE callbacks
I think we have two very different views on what a GUI library can/should be. In my opinion a GUI library is primarily concerned with receiving user input, and should be able to do that "on its own" without having to be explicitly told to do so. The programmer shouldn't have to say "hey GUI library, there was a mouse press at these coordinates" when that information is already available to the library and is accurate in 99% of cases. The programmer shouldn't have to rig up a zillion common keyboard behaviors like tab navigation, arrows to move things around, ctrl-x/c/v to cut/copy/paste, etc.
The point of a high-level library is to let the programmer to get things done without screwing with a bunch of lower-level behavior. This includes wiring up a bunch of events by copying some boilerplate from an example somewhere. Sure, there's a cost associated with that; if you have a weird coordinate system or are scaling everything someplace else, mouse input won't work. You sacrifice some of that low-level control, and in exchange you get the behavior you're going to want 99% of the time with very little hassle (an API that's expressive and easy to remember, a lot of canned functionality to speed up development for the usual cases, not having to write much boilerplate, etc.).
Still, the library does provide most of the lower-level things you mention. For example, there are methods to change the focused control. That's something I consider to be a low-level part of the API and something that users shouldn't have to use in most cases. On top of that layer, there's another layer that does listen for specific keyboard input (tab advances the focused control, shift-tab goes in the other direction, enter activates it). The library is written with the usual desktop UI toolkit keyboard input metaphors in mind, and I want things like that to "just work." If you're using the library, you're using it because you also want stuff like this to "just work."
And in order for that to work, at some point the library actually has to check for keyboard input, which brings us back to the problem as I see it: there's no way for it to check that keyboard input that is not destructive and does not require the user to wire all that shit up by hand.
The point of a high-level library is to let the programmer to get things done without screwing with a bunch of lower-level behavior. This includes wiring up a bunch of events by copying some boilerplate from an example somewhere. Sure, there's a cost associated with that; if you have a weird coordinate system or are scaling everything someplace else, mouse input won't work. You sacrifice some of that low-level control, and in exchange you get the behavior you're going to want 99% of the time with very little hassle (an API that's expressive and easy to remember, a lot of canned functionality to speed up development for the usual cases, not having to write much boilerplate, etc.).
Why should they be opt-in? For that matter, why should they be easy to deactivate? If someone else wants to design their own libraries like that, it's not unreasonable, but it's certainly not the only reasonable approach and I think our views differ here. I want common behavior (stuff that you do without thinking about it, like ctrl-x to cut text) to be ready to go out-of-the-box without the programmer having to do anything at all. No reading the manual, no copying from examples, no remembering obscure parts of the API, just ready to go. If they want to disable something like ctrl-x in text widgets, they have a different vision for the project and can write their own text widget, fork the project, or use some other library.You might even provide "default hooking mechanisms for the most obvious options"; but these should be opt-in and easily deactivable.
Still, the library does provide most of the lower-level things you mention. For example, there are methods to change the focused control. That's something I consider to be a low-level part of the API and something that users shouldn't have to use in most cases. On top of that layer, there's another layer that does listen for specific keyboard input (tab advances the focused control, shift-tab goes in the other direction, enter activates it). The library is written with the usual desktop UI toolkit keyboard input metaphors in mind, and I want things like that to "just work." If you're using the library, you're using it because you also want stuff like this to "just work."
And in order for that to work, at some point the library actually has to check for keyboard input, which brings us back to the problem as I see it: there's no way for it to check that keyboard input that is not destructive and does not require the user to wire all that shit up by hand.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: I LÖVE callbacks
I have said everything I wanted to say and I don't wish to continue discussing this. Good luck with your library.
When I write def I mean function.
Who is online
Users browsing this forum: No registered users and 1 guest