I didn't expect you to continue discussing it. Then you'd either have to maintain your position that library code never needs direct access to user input (that ship's going to sink pretty fast), or concede that sometimes it is reasonable for library code to have direct access to user input (and who wants to change their position, right?).kikito wrote:I have said everything I wanted to say and I don't wish to continue discussing this.
I LÖVE callbacks
Re: I LÖVE callbacks
Re: I LÖVE callbacks
I guess you're not convinced. I'll just leave this here, then.
It has drunkenness, and screen shake, and scaling, and a UI overlay that propagates events down to the game, but only when appropriate. Notice that no events are explicitly forwarded to the UI library by the game, and everything works. I challenge anyone to swap out this UI library with any other library and then tell me with a straight face that they think the resulting explosion of event-wiring-boilerplate is in any way necessary or preferable to simply calling ui:show() in gamestate:enter() and ui:hide() in gamestate:leave().
It has drunkenness, and screen shake, and scaling, and a UI overlay that propagates events down to the game, but only when appropriate. Notice that no events are explicitly forwarded to the UI library by the game, and everything works. I challenge anyone to swap out this UI library with any other library and then tell me with a straight face that they think the resulting explosion of event-wiring-boilerplate is in any way necessary or preferable to simply calling ui:show() in gamestate:enter() and ui:hide() in gamestate:leave().
- Attachments
-
- beer.love
- (867.18 KiB) Downloaded 100 times
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: I LÖVE callbacks
Granted you give me until the end of the weekend, i'll tryairstruck wrote:I challenge anyone to swap out this UI library with any other library and then tell me with a straight face that they think the resulting explosion of event-wiring-boilerplate is in any way necessary or preferable to simply calling ui:show() in gamestate:enter() and ui:hide() in gamestate:leave().
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: I LÖVE callbacks
I hope you get a chance to do it! I put an updated copy of that little example here if you want to look at that instead. It's basically the same, just commented and organized a little better, and disabled tab navigation on one of the UIs.zorg wrote:Granted you give me until the end of the weekend, i'll try
- Positive07
- Party member
- Posts: 1014
- Joined: Sun Aug 12, 2012 4:34 pm
- Location: Argentina
Re: I LÖVE callbacks
I dont think simplicity is everything we should care about, having two functions call that do everything for the user doesnt make your API nice, as I understand your library is something like "Hey you are stupid and you can't write your UI code yourself so let me handle everything, just tell me how you want it to look".
To me a good API is one that let's you customize and hack even down to the minimal detail without having to rewrite the whole damn think or writing code for every little edge case. Of course perfection is impossible and an API like this may end up hiding some stuff, and it may also make coding a little harder in the sense that you have to wire up more stuff, but as Kikito said, you can have functions that do the wiring, but they don't have to be mandatory, just another utility the library provides.
So yes let me wire my input, if I want the library to not respond to mouse presses in a certain area let me do so, if I want to leave the textinput when the user presses "H" let me do so, if I want to remap each key of my keyboard for a certain textinput let me do so, if I want that moving the scroll wheel up moves the scrollbar down and moving it down actually scorlls up let me do so...
In this case I share Kikito's view point, a library that tries to do too much is a bad idea. You can't split things easily, customizing becomes hard, you have interdependencies everywhere.
I think all UI libraries out there lack this, input is too tied up to the UI when they are all different things.
EDIT: I must also add that there is no reason why Kikito nor I have to share your point of view airstruck nor you should share ours, I may also have differences with Kikito but who cares. Just make your UI library the best you can, if people like it they will use it, if they don't they will find alternatives or write their own, maybe you will inspire them. Feel free to code however you like, no one will criticize your work
To me a good API is one that let's you customize and hack even down to the minimal detail without having to rewrite the whole damn think or writing code for every little edge case. Of course perfection is impossible and an API like this may end up hiding some stuff, and it may also make coding a little harder in the sense that you have to wire up more stuff, but as Kikito said, you can have functions that do the wiring, but they don't have to be mandatory, just another utility the library provides.
So yes let me wire my input, if I want the library to not respond to mouse presses in a certain area let me do so, if I want to leave the textinput when the user presses "H" let me do so, if I want to remap each key of my keyboard for a certain textinput let me do so, if I want that moving the scroll wheel up moves the scrollbar down and moving it down actually scorlls up let me do so...
In this case I share Kikito's view point, a library that tries to do too much is a bad idea. You can't split things easily, customizing becomes hard, you have interdependencies everywhere.
I think all UI libraries out there lack this, input is too tied up to the UI when they are all different things.
EDIT: I must also add that there is no reason why Kikito nor I have to share your point of view airstruck nor you should share ours, I may also have differences with Kikito but who cares. Just make your UI library the best you can, if people like it they will use it, if they don't they will find alternatives or write their own, maybe you will inspire them. Feel free to code however you like, no one will criticize your work
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Re: I LÖVE callbacks
I intended it more as "hey you're smart enough to use a library that handles the low level details for you so you can get down to the business of creating your UI without a bunch of fussing around."as I understand your library is something like "Hey you are stupid and you can't write your UI code yourself so let me handle everything, just tell me how you want it to look".
It's interesting how this got turned around from me suggesting that users were smart enough to cope with a more rich event listener API into me apparently suggesting that users are stupid by working on a library that hides time-consuming implementation details behind a convenient high-level abstraction, in the interest of boosting productivity.
You can. There's a sensible default behavior, but you can override it.if I want the library to not respond to mouse presses in a certain area let me do so
You can. There's a sensible default behavior, but you can override it.if I want to leave the textinput when the user presses "H" let me do so
You can if you feel strongly enough about it to expose all those functions instead of just complaining about built-in functionality. There's a ticket open that mentions this. I'm not going bother with it any time soon, because the default functionality suits me fine, but feel free to make a pull request. It wouldn't take much effort.I want to remap each key of my keyboard for a certain textinput let me do so
You can. There's a sensible default behavior, but you can override it.if I want that moving the scroll wheel up moves the scrollbar down and moving it down actually scorlls up let me do so...
Of course UI libraries are concerned with user input. Receiving user input is probably the most important thing a UI does. Providing some level of abstraction for dealing with user input is a natural thing for a UI library to do.I think all UI libraries out there lack this, input is too tied up to the UI when they are all different things.
In this case, an abstraction was necessary because the library works with multiple backends that expose user input in different ways. I wanted to be able to use the library on top of either Love or SDL without having to write implementation-specific input handling code.
Criticize all you want, but complaining about the inclusion of default functionality that's easily overridden isn't going to convince me not to provide that functionality.no one will criticize your work
- Positive07
- Party member
- Posts: 1014
- Joined: Sun Aug 12, 2012 4:34 pm
- Location: Argentina
Re: I LÖVE callbacks
The problem is that when a library does something in a too specific way the users end up being discouraged because changing that behaviour is too difficult, so they end up throwing it away and even implementing their own, it's more of a psicological problem.airstruck wrote: I intended it more as "hey you're smart enough to use a library that handles the low level details for you so you can get down to the business of creating your UI without a bunch of fussing around."
It's interesting how this got turned around from me suggesting that users were smart enough to cope with a more rich event listener API into me apparently suggesting that users are stupid by working on a library that hides time-consuming implementation details behind a convenient high-level abstraction, in the interest of boosting productivity.
Most people start a project and when they don't find their perfect tools start to do Yak Shaving to fix the problem, Kikito wrote a great post about it too.
You as the owner of the library may not be able to see this, since it does exactly what you need it to do, and you know the internals so if it didn't do what you wanted you would easily fix it; well your solution may not be perfect for everyone, resulting in people getting frustrated when they can't do what they need.
Providing low level stuff is a great way to help fix this, you let the user easily change how everything works, of course you can provide sensible defaults as a high level feature, just let the users get to the low level stuff as easy as to the high level.
Currently I don't have a project where I would like to use your library, if I ever have one and I happen to need that feature I'm gonna help youairstruck wrote: You can if you feel strongly enough about it to expose all those functions instead of just complaining about built-in functionality. There's a ticket open that mentions this. I'm not going bother with it any time soon, because the default functionality suits me fine, but feel free to make a pull request. It wouldn't take much effort.
Well handling the input is what they do, so the abstraction would be "Okay, what's the input you have? I'll handle that for you" instead of "I'm gonna take this input and do this stuff, hope you don't bother"airstruck wrote: Of course UI libraries are concerned with user input. Receiving user input is probably the most important thing a UI does. Providing some level of abstraction for dealing with user input is a natural thing for a UI library to do.
I'm glad your library can override the default behaviours, that is a pretty nice thing. Can I simply, unhook the default behaviour entirely? If you can then your library does pretty much what Kikito and I are asking for, offers defaults, doesn't force you to use them, provides a way for defaults to not be used at all.
Well yes, your library is pretty cool on handling different backends.airstruck wrote: In this case, an abstraction was necessary because the library works with multiple backends that expose user input in different ways. I wanted to be able to use the library on top of either Love or SDL without having to write implementation-specific input handling code.
The user could have done that if you provided a nice API too, again I don't complain but you should know that even though no one has tried before you, writing a UI library which is framework agnostic and uses backends to wire up to them should be totally possible. Just provide a nice API and you can wire up any backend you would like, this is of course pretty much harder if the UI library already wires itself up to the input, you can only use the library in the backends it targets.
Fine with me I'm not trying to convince you, not saying my way is better, just pointing out there are different points of view so you should respect them all even if you don't think like them. Kikito also tried to say this and I think that is the reason he didn't follow the discussion, because there isn't a definite conclusion, your point of view won't change, neither his or mine, no matter how much we discussairstruck wrote: Criticize all you want, but complaining about the inclusion of default functionality that's easily overridden isn't going to convince me not to provide that functionality.
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Re: I LÖVE callbacks
The low level stuff is in there, of course, or the high level stuff on top of it wouldn't work. Whether everything everyone could ever want to use is exposed, I don't know. I figure if someone using the project needs some specific low level thing exposed that isn't already, they can open a ticket.Positive07 wrote:Providing low level stuff is a great way to help fix this, you let the user easily change how everything works, of course you can provide sensible defaults as a high level feature, just let the users get to the low level stuff as easy as to the high level.
Many of the default behaviors can be "destroyed." If someone has an actual need to remove a specific behavior that can't be removed right now, they can open a ticket.Can I simply, unhook the default behaviour entirely?
I think it's easier said than done. Loading and displaying an image, loading a font and displaying text, even just drawing a rectangle is completely different in SDL and Love. All of that stuff already needed to be abstracted behind a common API, so that the library can say "draw a rectangle" and it works on any supported backend. In the same way, when you call layout:show(), a bunch of events are wired up, but how that actually happens depends on the backend.writing a UI library which is framework agnostic and uses backends to wire up to them should be totally possible.
Here's the actual event wiring code in question.
https://github.com/airstruck/luigi/blob ... e.lua#L119
I really don't think you want to write all of this every time you show a layout or raise it above the other layouts. Yes, events need to be wired up to each layout separately, unwired when when a layout is hidden, and they need to be unwired and rewired when a layout is raised to the top so that event handlers for things like drawing the UI and capturing mouse input fire in the right order. What you might want is your own specialized backend that only replaces this function in order to change, say, mouse coordinates before passing them along to the library. If this doesn't work for someone's actual use scenario, they can let me know and we can come up with a solution. Again, if users have specific problems they're facing, they can open tickets.
- Positive07
- Party member
- Posts: 1014
- Joined: Sun Aug 12, 2012 4:34 pm
- Location: Argentina
Re: I LÖVE callbacks
Well good API that are really agnostic help with all that, I think we don't differ that much on beliefs.
As I said I would write a backend library which for example has functions like rectangle, image, circle and whatnot, that library would be written for each framework, say LÖVE, Lua SDL2 and every other one you may want.
Then I would require this library into my UI code and simply use that. The same with the input, I would separate it into a different library which has functions like getMousePosition and so and then I can require this into the UI, that library also provides functions to write framework specific code into it, for example basic callbacks for keypressed and keyreleased events and such that you would in turn call from love.keypressed and love.keyreleased or any other callback the framework may provide, with this you could easily wire up your framework with the input library.
If your input and graphic library are stateless you could even make all controls behave differently by wiring different states generated by this library into your elements.
You could of course provide a function that wires all this up by default, a function or argument to stop the library for wiring everything itself and facilities to wire specific things your self for an element, a set of elements, or everything you would like.
This API has a low level side(you can entirely change your backend and wire up new backends), medium level side (you can change the behaviour of an specific element, specific input), and high level side (wires everything itself and leaves the user with something that works with sane defaults).
Again modularity is a MUST, you end up with a bunch of related libraries, you should be able to use them separately, I think this is possible, because the wiring is also exposed as part of the API, just that normally it is handled by the other libaries.
I don't know if my way is perfect but it could work just as well as yours, I think both can cover mostly everything but I don't think mine rises that much the need of new tickets every single time, just do it yourself, the library doesn't need to cover every edge case because you can use it's API to extend it.
This my point of view on how I would like to tackle the problem, again I think your library is pretty neat and also looks good with all the default values, I wouldn't like to modify it though but that is my own taste again
I'm glad we could discuss this, you have really expanded my mind on how I would like some stuff to be done and how it's done, and how to tackle design choices and such. Thanks
But as I said we don't differ that much, sane default, offer low level API to modify the behaviour entirely, even disconnect it entirely from the normal input methods and drawing operations... We would just make our API different and separate modules differently but that is no big deal. I hope your library becomes even better and that you may have learned some new sight on this. We shouldn't really continue discussing this, I don't think neither of us is wrong, it can be done either way and both will work the same, it wouldn't be easier or harder just different.
As I said I would write a backend library which for example has functions like rectangle, image, circle and whatnot, that library would be written for each framework, say LÖVE, Lua SDL2 and every other one you may want.
Then I would require this library into my UI code and simply use that. The same with the input, I would separate it into a different library which has functions like getMousePosition and so and then I can require this into the UI, that library also provides functions to write framework specific code into it, for example basic callbacks for keypressed and keyreleased events and such that you would in turn call from love.keypressed and love.keyreleased or any other callback the framework may provide, with this you could easily wire up your framework with the input library.
If your input and graphic library are stateless you could even make all controls behave differently by wiring different states generated by this library into your elements.
You could of course provide a function that wires all this up by default, a function or argument to stop the library for wiring everything itself and facilities to wire specific things your self for an element, a set of elements, or everything you would like.
This API has a low level side(you can entirely change your backend and wire up new backends), medium level side (you can change the behaviour of an specific element, specific input), and high level side (wires everything itself and leaves the user with something that works with sane defaults).
Again modularity is a MUST, you end up with a bunch of related libraries, you should be able to use them separately, I think this is possible, because the wiring is also exposed as part of the API, just that normally it is handled by the other libaries.
I don't know if my way is perfect but it could work just as well as yours, I think both can cover mostly everything but I don't think mine rises that much the need of new tickets every single time, just do it yourself, the library doesn't need to cover every edge case because you can use it's API to extend it.
This my point of view on how I would like to tackle the problem, again I think your library is pretty neat and also looks good with all the default values, I wouldn't like to modify it though but that is my own taste again
I'm glad we could discuss this, you have really expanded my mind on how I would like some stuff to be done and how it's done, and how to tackle design choices and such. Thanks
But as I said we don't differ that much, sane default, offer low level API to modify the behaviour entirely, even disconnect it entirely from the normal input methods and drawing operations... We would just make our API different and separate modules differently but that is no big deal. I hope your library becomes even better and that you may have learned some new sight on this. We shouldn't really continue discussing this, I don't think neither of us is wrong, it can be done either way and both will work the same, it wouldn't be easier or harder just different.
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 2 guests