-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convenient event handling mechanism #51
Comments
How I see it. With SDL2:
With SDL2pp:
In more complex cases it may be less readable though. |
I'm not that familiar with C++11 but I guess |
Yes, that's lambda. Sure, corresponding event structure will be passed, I just also want to provide a way to not pass it when it's needed. Lambda syntax is pretty hard to read even without arguments :( |
If you have ever used XNA they have several static classes in the Input namespace that you can access like, and you can do stuff like: I think it would be far more usable (but less C++11ish) to have something of this kind:
It doesn't have to be that monolithic, other idea is there could be one struct/class for each event type:
That way you can pass around the polled events instead of just listening to a fixed set of callbacks. |
I have written a small proposal of how it could work, you can see it at my repo in the event_manager branch is not complete but it gives you general idea |
Honestly this doesn't look too useful to me. You store events in a vector - what's the purpose of it? You seem to try to recreate keyboard state from the events - why is this needed while there's SDL_GetKeyboardState() which doesn't even need wrapping? My idea was oo-wrapping around clumsy event handling code SDL project have, e.g. mainly an
Now, users can encapsulate event handling code in EventHandler derived class and forget an ugly switch. From here, it's possible to build more, both high and low level abstractions which allow users to avoid even more boilerplate code.
Usage:
|
I didn't know SDL_GetKeyboardState() existed, but yeah the idea was to provide functionality like that for every event type (I used keyboard as an example), but your proposals sound far better, just one thing: On the "callback" base approach (EventHandlerRegistry) should there be a way to "unregister" callbacks? Having AddMouseMotionHandler to me implies you can RemoveMouseMotionHandler. |
Yes! I though about it but forgot to add it to an example. There should probably should just be a single RemoveHandler method, as long as handler IDs returned by Add*Handler are global. |
I have uploaded another branch with my proposal for the change (this one is pretty bare bones compared to the other one), you can find it in my repo and is called event_handler_2.0, relevant files are: EventHandler.hh/EventHandler.cc. Stuff I know will rise questions, and my reasoning to do it that way:
|
Doesn't rise any questions, this is a good idea.
This would be a bad design and we should not tolerate that. E.g. if event handling logic in encapsulated in a class, it should not leak outside. But yes, it should be flexible, and I've had a couple of additional ideas which may help improve this:
and the former is called in both cases. Likewise, we may have
This adds a bit of confusion, but at the same time it adds the flexibility, which IMO overweights. The call order IMO should be from more generic to less generic (e.g. OnAnyEvent, then OnMouseButton, then OnMouseButtonDown).
I agree. It's very tempting to have event info passed through arguments, but I guess it's just too inflexible. |
Now some comments on the code (I guess it's time to add CONTIBUTING.md to the repo...): Please
also I'm an ardent opponent of reversing comparison order in conditions: this makes programmers intent less apparent and the code less readable, while "= instead of ==" problem is easily detected by static analyzers and compilers for a long time. |
So I've been giving it a long thought because it bothers me the idea of calling several no-op functions which on top would be confusing for the users but after your posts I realized it, we are doing it wrong, we are coupling event polling and event handling. Basically the polling functions are vey simple wrappers for the SDL_PollEvent() function and don't necessarily needs to know about event handling, consider:
Where T is an object that can be called with SDL_Event as argument: free functions/lambdas/classes or structs with operator(SDL_Event) member functions. We can argue about about the readability of the operator(SDL_Event) vs a named member function (like HandleEvent(SDL_Event)) but that we can have that discussion later. Now, this only solves half of the problem (polling) and we need a solution for the actual event handling to save the users the horrible We need an easy templated way to say: for any given SDL_EventType call all of the given functions that accept the specific event structure, example:
That way the user can explicitly say what are the only events that should be handled and we can use lambdas in addition to classes/structs. |
I have been watching this issue for days. And I hope my looper class will help you.
This class is a wrapper for event in my SDL project. It is used like this:
|
I like how you are using the operator+() as in .NET's event callbacks. I can't exactly understand how your Looper class works with stuff like |
Here is my implement of
You can view this for the whole Looper class implement . |
We need c++11 style event handling mechanism instead of legacy switch-loop
The text was updated successfully, but these errors were encountered: