SFML community forums

General => Feature requests => Topic started by: cantor on February 25, 2016, 02:55:36 pm

Title: push Events...
Post by: cantor on February 25, 2016, 02:55:36 pm
Hello.

So this is my situation. Previously I had this (pretty standard) :


int main (int argc, char **argv) {

        Big_Drawable BD_1;
        Big_Drawable BD_2;
        ...
        Big_Drawable BD_n; // n is pretty large !

        while (window.isOpen()) {

                while (window.pollEvent (event) {

                        switch (event) {

                                case Event::MouseButtonPressed:

                                        // Do tons of stuff with BD_n and thounsands of other local variables.
                                // etc..
                        }
                }
        }
}


 

This is perfect.

Now : I want to include another feature. This app should receive signals not only from the OS, but also from other computers (let's say from the network).

I have somthing like this :



void clickedCallback () {
        // Here I want to do exactly the same stuff
        // as in the MouseButtonPressed.
        // But it's large code with huge amount of variables
        // That I can't easily put in an external function
}

// ... other callbacks for keyboards etc...



int main (int argc, char **argv) {

        Big_Drawable BD_1;
        Big_Drawable BD_2;
        ...
        Big_Drawable BD_n; // n is pretty large !


        RegisterCallback (clickedCallback);


        while (window.isOpen()) {
               
                while (listenToNetwork()); // Listen and call the callbacks when necessary

                while (window.pollEvent (event) {

                        switch (event) {

                                case Event::MouseButtonPressed:

                                        // Do tons of stuff with BD_n and thounsands of other local variables.
                                // etc..

                        }
                }
        }
}

 


So I really would enjoy doing just this :


void clickedCallback () {
        // Here I want to do exactly the same stuff
        // as in the MouseButtonPressed.
        // But it's large code with huge amount of variables
        // That I can't easily put in an external function

        Event event;

        event.type = Event::MouseButtonPressed;

        window.pushEvent (event); // <---- Yupi!

}

 

And that's it !  :D

Instead, I have to put all the code in external functions, with tons and tons of parameters to get all my datas.

Title: Re: push Events...
Post by: cantor on February 25, 2016, 05:23:54 pm
I reply yo myself because I found a work-arround using a second queue... But still, it's stupid work.

class HandleHOTAS {
public:
        HandleHOTAS (RenderWindow &win) : window(win) {
        }
        void handle_hotas (const HOTAS *msg) { // <- This is the callback function
                Event event;
               
                if (msg->left_click) {
                        event.type = Event::MouseButtonPressed;
                        event.mouseButton.button = Mouse::Left;
                        eventList.push (event);
                }
               
                 // [..... ]
        }
        bool pollEvent (Event &event) { // <- This is the new pollEvent function
                if (window.pollEvent (event)) return true;
                if (!eventList.empty()) {
                        event = eventList.front();
                        eventList.pop();
                        return true;
                }
                return false;
        }
       
private:
        RenderWindow &window;
        std::queue<Event> eventList;
};

 

Now I would call this HandleHOTAS::pollEvent instead of the RenderWindow::pollEvent

Title: Re: push Events...
Post by: Cmdu76 on February 25, 2016, 05:30:02 pm
If you can use lambda, you can use this solution :

std::function<void()> myCallback;

int main (int argc, char **argv) {

    Big_Drawable BD_1;
    ...
    Big_Drawable BD_n;
       
        myCallback = [&](){
                // Here your clicked function
        }

    while (window.isOpen()) {
               
                while (listenToNetwork()) {
                        if (packetType == ...) {
                                myCallback();
                        }
                }

        while (window.pollEvent (event) {
            switch (event) {
                case Event::MouseButtonPressed:
                                        myCallback();
                                       
                                // ...
            }
        }
    }
}
Title: Re: push Events...
Post by: cantor on February 25, 2016, 05:33:03 pm
If you can use lambda, you can use this solution :


Yes, I know. But I'm stick with plain old C++

Nested functions don't look good to me anyway.
Title: Re: push Events...
Post by: GraphicsWhale on February 26, 2016, 01:22:44 am
Yes, I know. But I'm stick with plain old C++

Lambdas are part of the C++ language.
Title: Re: push Events...
Post by: cantor on February 26, 2016, 09:26:08 am
Yes, I know. But I'm stick with plain old C++

Lambdas are part of the C++ language.

No kidding?  ;D

You know what I meant: C++ 98.


Title: Re: push Events...
Post by: R23MJ on February 26, 2016, 03:11:01 pm
Do you have a specific reason for using only c++98? C++14 is the standard now (I believe C++11 more widely supported though; Don't quote me there.)
Title: Re: push Events...
Post by: cantor on February 26, 2016, 07:26:47 pm
This thead is not about the language I wish to use but about the API of SFML.

And I think it would be usefull to be able to push events in the SFML's queue.

That was an example but I can imagine a lot more, whenever you have your own driver for user actions and wish to group all the action management code in one place, with the same queue, instead of having to make a new redundant queue next to it and useless work.
Title: Re: push Events...
Post by: Laurent on February 26, 2016, 08:28:01 pm
I think this is more an ugly hack to work around a bad design, than a real feature (at least in your case) ;)

The real solution to your problem is to find a better design, with a better abstraction/decoupling between your logic and the inputs that trigger it. Faking a mouse press event just because you can't easily call the corresponding code, doesn't look like a proper solution ;)

For example, what are those BD_n variables? Shouldn't they be in an array?
Title: Re: push Events...
Post by: cantor on February 26, 2016, 08:50:16 pm
I think this is more an ugly hack to work around a bad design, than a real feature (at least in your case) ;)

The real solution to your problem is to find a better design, with a better abstraction/decoupling between your logic and the inputs that trigger it. Faking a mouse press event just because you can't easily call the corresponding code, doesn't look like a proper solution ;)

For example, what are those BD_n variables? Shouldn't they be in an array?

Thanks for the answer.
The design was fine before I added this "feature". I agree with you about that, but what is wrong with my solution? It's not so ugly. It's not a fake mouse press, it's a real mouse press but the signal was not generated by sfml.

Doing two separate signal handling management code looks ugly to me too. I would even like to create custom events  that could be handled in the same loop just like other sfml events, but I'm going too far probably for you.

The BD_n was just supposed to represent tons of variables of different types, boring to pass to a function. (Functions with 100 parameters is just a ugly hack lol )

Passing a structure with pointers to the variables : even worse.

Title: Re: push Events...
Post by: GraphicsWhale on February 26, 2016, 10:57:33 pm
No kidding?  ;D

You know what I meant: C++ 98.

No, I didn't know what you meant. You sounded to me like you thought Lambdas were a compiler extension or something.

But more importantly, why would you only want to use C++98?

It's not a fake mouse press, it's a real mouse press but the signal was not generated by sfml.

Could you explain further?
Title: Re: push Events...
Post by: Laurent on February 27, 2016, 09:45:04 am
Quote
Doing two separate signal handling management code looks ugly to me too.
I don't think so. What you're doing is to create your own higher-level event loop, by merging SFML native events and events generated by your code. I would probably do exactly the same thing if I had to deal with custom events.

Quote
I would even like to create custom events  that could be handled in the same loop just like other sfml events
Isn't it exactly what you do in HandleHOTAS::pollEvent? If by "custom events" you mean something else than sf::Event, then it's fairly easy to do on top of what you already wrote. Just write your own Event structure that can hold either a sf::Event or something else.

Quote
The BD_n was just supposed to represent tons of variables of different types, boring to pass to a function. (Functions with 100 parameters is just a ugly hack lol )
Still a bad design in my opinion. Nobody should have to deal with 100 different variables in a function.
Title: Re: push Events...
Post by: cantor on February 27, 2016, 10:21:16 am
No kidding?  ;D

You know what I meant: C++ 98.

No, I didn't know what you meant. You sounded to me like you thought Lambdas were a compiler extension or something.

But more importantly, why would you only want to use C++98?

It's not a fake mouse press, it's a real mouse press but the signal was not generated by sfml.

Could you explain further?

Why? Because I already have 7000 lines of c++-98 and I dont want to mix them with -11 just to have a lambda function. And also because I master -98 programming but never really got interested in the new stuff. But I will...

Well it's just a mouse press but coming from a joystick system (HOTAS) plugged on another computer running another program. The two apps are communicating through UDP multicast. (LCM protocol)
It's like a huge flight simulator system with many computers running many programs with some Sfml-powered MMI
Title: Re: push Events...
Post by: cantor on February 27, 2016, 10:34:26 am
Isn't it exactly what you do in HandleHOTAS::pollEvent? If by "custom events" you mean something else than sf::Event, then it's fairly easy to do on top of what you already wrote. Just write your own Event structure that can hold either a sf::Event or something else.

Indeed it's exactly what I do.
The goal of this topic is to propose new features in the SFML library so people with the same needs dont have to write again and again the same thing on top of the library, right ?

Just adding a pushEvent function, and maybe adding a customizable field in the Event structure, would do the trick just fine
Title: Re: push Events...
Post by: Laurent on February 27, 2016, 11:34:01 am
Quote
Just adding a pushEvent function, and maybe adding a customizable field in the Event structure, would do the trick just fine
Yes it would. Although the "customizable" field in sf::Event would be ugly (a void*? with dynamic allocation/deallocation?).

But is it the right thing to do to solve your problem? I'm not sure. I'll probably need more relevant use cases to change my mind ;)
Title: Re: push Events...
Post by: eXpl0it3r on February 27, 2016, 12:32:27 pm
The event processing should be reserved for system events and nothing more. As Laurent points out adding customization to it will make things only ugly and serve the people using it no big advantage, since the system will most likely still be limited for their needs.

A better and more common approach is to implement your own message bus (http://www.optank.org/2013/04/02/game-development-design-3-message-bus/) and/or command pattern (https://github.com/SFML/SFML-Game-Development-Book/tree/master/04_Input), that way you have the maximum flexibility to adjust things to your specific needs and you can easily feed the system events into the message bus - event fake system events.
Title: Re: push Events...
Post by: GraphicsWhale on February 27, 2016, 09:22:03 pm
Why? Because I already have 7000 lines of c++-98 and I dont want to mix them with -11 just to have a lambda function. And also because I master -98 programming but never really got interested in the new stuff. But I will...

The only benefit to using C++98 over C++11 is support for outdated compilers.

Indeed it's exactly what I do.
The goal of this topic is to propose new features in the SFML library so people with the same needs dont have to write again and again the same thing on top of the library, right ?

Just adding a pushEvent function, and maybe adding a customizable field in the Event structure, would do the trick just fine

I disagree. SFML events should be used solely for events generated by SFML, not by the application.

Also, there is no clean way of doing customizable events. You're pretty much stuck with creating your own event system if you want custom events.
Title: Re: push Events...
Post by: cantor on February 27, 2016, 09:26:37 pm
I have to disagree.

You have user data streams, you have custom audio streams, you have the capacity to create your own Drawable and Transformable object, I dont see any good reason why you shouldn't have custom events, or at least a smart way of making them - not involving reinventing the wheel every time.
Title: Re: push Events...
Post by: GraphicsWhale on February 27, 2016, 10:08:16 pm
You have user data streams, you have custom audio streams

And it makes sense. Why limit the ability to load resources to just whatever kinds of files SFML can decode? The underlying APIs support it. It's also fairly easy to implement.

you have the capacity to create your own Drawable and Transformable object

Again, there's nothing about the underlying APIs (in this case, OpenGL) that prohibits custom shapes, and it's pretty easy to implement custom shapes.

I dont see any good reason why you shouldn't have custom events

What limitation is SFML imposing on you by not letting you create your own event type? And it's not like there's any demand for such a feature.

or at least a smart way of making them

What do you mean?

not involving reinventing the wheel every time.

It's really not too terribly difficult to implement a simple event system. There is no clean way to achieve what you want, so you'd be much better off making your own anyways.
Title: Re: push Events...
Post by: Laurent on February 27, 2016, 11:07:59 pm
Then show us this "smart way" please ;)
Title: Re: push Events...
Post by: cantor on February 28, 2016, 11:54:19 am
I disagree. SFML events should be used solely for events generated by SFML, not by the application.

What, no... Look at my second post, the HandleHOTAS class, what is wrong with it ? Even Laurent said he would do the same if I understood right. A click is a click. I see nothing wrong.

Maybe what you really mean is to use the internal std::queue<Event> for internal events only.
Title: Re: push Events...
Post by: GraphicsWhale on February 28, 2016, 11:44:18 pm
A click is a click. I see nothing wrong.

SFML's event system is simply to forward events from the OS to your application. If you want to support some non-standard device as well, you're going to have to create your own event system.

Plus, and I have yet to see any suggestions yet, how could you possibly go about implementing such as a feature? For custom events, the size of sf::Event needs to be known when SFML is being compiled, which means we aren't left with many options (and all of the options are sub-optimal). And I can't see any realistic use of pushing an event such as MouseButtonPressed/MouseButtonReleased, which would make real mouse clicks and controller "mouse clicks" ambiguous, which is also a bad idea.
Title: Re: push Events...
Post by: cantor on February 29, 2016, 11:57:03 am
A click is a click. I see nothing wrong.

SFML's event system is simply to forward events from the OS to your application. If you want to support some non-standard device as well, you're going to have to create your own event system.

Plus, and I have yet to see any suggestions yet, how could you possibly go about implementing such as a feature? For custom events, the size of sf::Event needs to be known when SFML is being compiled, which means we aren't left with many options (and all of the options are sub-optimal). And I can't see any realistic use of pushing an event such as MouseButtonPressed/MouseButtonReleased, which would make real mouse clicks and controller "mouse clicks" ambiguous, which is also a bad idea.

For non-standard devices, a RenderWindow::pushEvent (Event &) is all that is necessary.


For Custom Events, you have multiple solutions :

1) Add a Event::UserEvent enum , a void *userData field, which is deallocated in the ~Event destructor.
 Then you just need to event.userdata = static_cast<void*> new MyEvent (stuff); I agree it's not very sexy.


2) Make "Event" a template parameter. Constraint this template parameter to be a subclass of Event (this can be done even with C++-98). This is not an easy solution in a library though



Title: Re: push Events...
Post by: Nexus on February 29, 2016, 05:02:44 pm
As mentioned, the sf::Event queue carries operating system events only. The sf::Event type itself was never conceived to be filled by users, let alone be extensible for custom events. The existing interface gives you certain guarantees and invariants1. Loosening it, or worse, bloating both the sf::Event and the sf::Window APIs in order to support user-defined events is not only a bad idea because it adds complexity most users won't benefit from2, but also because there's no reasonable way of bringing custom events to a common denominator. The proposed void* + cast + dynamic allocation approach is very ugly, not type-safe and slow. Everybody can write that better, but one needs to know the concrete use case, which SFML is too abstract for.

_________
1 sf::Event guarantees which union members can be read, depending on the value of the type member.
2 Those who did benefit could easily write a wrapping queue themselves -- knowing the STL, it's a trivial task done in a matter of minutes. And one gains much more flexibility than any solution built into SFML.
Title: Re: push Events...
Post by: GraphicsWhale on February 29, 2016, 08:53:52 pm
1) Add a Event::UserEvent enum , a void *userData field, which is deallocated in the ~Event destructor.
 Then you just need to event.userdata = static_cast<void*> new MyEvent (stuff); I agree it's not very sexy.

That solution is too.. C-ish.

2) Make "Event" a template parameter. Constraint this template parameter to be a subclass of Event (this can be done even with C++-98). This is not an easy solution in a library though

The problem here is that that would require either:

- Your custom event structure to be compiled alongside the SFML source.
- Any SFML source that uses the event structure to be moved into header files.
Title: Re: push Events...
Post by: Jesper Juhl on February 29, 2016, 10:46:58 pm
+1 @Nexus.
Title: Re: push Events...
Post by: cantor on February 29, 2016, 11:03:30 pm
Okay then.. Let's do nothing at all!  :-X

Maybe this awsome library is awesome as it is
Title: Re: push Events...
Post by: Jesper Juhl on March 01, 2016, 05:28:44 pm
Some things you could look at:

The Thor Input module (http://www.bromeon.ch/libraries/thor/documentation/v2.0/group___input.html).
D-Bus (https://www.freedesktop.org/wiki/Software/dbus/).
libsigc++ (http://libsigc.sourceforge.net/).
Qt signals and slots (http://doc.qt.io/qt-5/signalsandslots.html).
Title: Re: push Events...
Post by: eXpl0it3r on March 01, 2016, 06:00:38 pm
Well since you're not willing to use modern C++, you'll pretty much do a lot of hard work and write ugly code. ;)
Title: Re: push Events...
Post by: SeriousITGuy on March 02, 2016, 10:26:45 am
Safe yourself the hassle and just use Sigc++. I wanted to write something similar the last months and it was a big pain. Then I found Sigc++ and I am happy with it.
Title: Re: push Events...
Post by: cantor on March 02, 2016, 10:39:04 am
Safe yourself the hassle and just use Sigc++. I wanted to write something similar the last months and it was a big pain. Then I found Sigc++ and I am happy with it.

Yes but a Message Bus and a Signal/Slot are two different mechanism.
I was looking for a message bus system
Title: Re: push Events...
Post by: Jesper Juhl on March 02, 2016, 10:00:06 pm
Did you see my previous post? It was not all just signals and slots.