• Advertisement
Sign in to follow this  

How do you manage user interface events?

This topic is 3030 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi friends! What do you think about this topic: Let's say I have these classes: CApp CGame CButton CApp creates a CGame instance, and this one create several instaces of CButton, which has a method called Released(). How can I know which button is being pressed from inside CButton class? How can I send a messege telling a certain button was released (or pressed, it does not matter now) to an appropiate class instance? Should I create another class called CEventProcessor or CEventHandler to centralize all my events and send them to an apropiate class? Should I give to my CButton instance a name when I instantiate it (button name) and on Released() code execute/write something like a switch-case with that name? Thanks a lot for your help.

Share this post


Link to post
Share on other sites
Advertisement
The best way of handling 'things' happening and need to alert other 'things' is by using the event delegate model. I work on a commercial game that has a very large and complex UI and it was orignally architected using messages, we are moving over to events and delegates and things are becoming much more simple because of it. I suggest you look at how C# solves this problem.

Hope that helps,

Share this post


Link to post
Share on other sites
Quote:
Original post by Dave
The best way of handling 'things' happening and need to alert other 'things' is by using the event delegate model. I work on a commercial game that has a very large and complex UI and it was orignally architected using messages, we are moving over to events and delegates and things are becoming much more simple because of it. I suggest you look at how C# solves this problem.

Hope that helps,


Thanks for help, I forgot to say I am using C++/OpenGL. Do you mean using any software engineering pattern?

Share this post


Link to post
Share on other sites
Seen some interesting stuff about so-called "Immediate mode" guis lately in which you effectively specify the GUI like:


res = gui.button("some text");
if(res.state == button.pressed)
{
// do button stuff, maybe fire an event off to the game or something
}


It's interesting because it does away with the whole event model and simplifies creating game guis, which are normally quite small anyway.

I believe Unity uses this approach too.

Share this post


Link to post
Share on other sites
Quote:
Original post by evolutional
Seen some interesting stuff about so-called "Immediate mode" guis lately in which you effectively specify the GUI like:


res = gui.button("some text");
if(res.state == button.pressed)
{
// do button stuff, maybe fire an event off to the game or something
}


It's interesting because it does away with the whole event model and simplifies creating game guis, which are normally quite small anyway.

I believe Unity uses this approach too.


I looked into this as well and still couldn't quite see the benefit. But hey :D.

Share this post


Link to post
Share on other sites
Quote:
Original post by evolutional
Seen some interesting stuff about so-called "Immediate mode" guis lately in which you effectively specify the GUI like:


res = gui.button("some text");
if(res.state == button.pressed)
{
// do button stuff, maybe fire an event off to the game or something
}


It's interesting because it does away with the whole event model and simplifies creating game guis, which are normally quite small anyway.

I believe Unity uses this approach too.


Wow, I'm currently working on a minimalistic UI system, and that is ridiculously simple, and I don't see any obvious drawbacks.

I was going to use function pointers that are triggered on press. I feel like I completely over-complicated the problem.

Share this post


Link to post
Share on other sites
Unless you need something more powerful (i.e. if you're making an in-game editor or something), I'd recommend going with the "immediate mode" UI system.

On the other hand, I'm not too fond of it myself lol. Dave's got the right idea, the best solution is to use delegates. The easiest way is to use BOOST; either the fuction handler or slots & signal system. Here's how my old system was setup:


struct ClickEventArguments;
typedef boost::function<void (Control *, ClickEventArguments &)> ControlClickHandler;

class Button : Control
{
public:
ControlClickHandler OnClick;
};

// in CGame::Initialize() or whatever
myButton.OnClick = boost::bind(&CGame::myButton_OnClick, this, _1, _2);

// in CGame
void myButton_OnClick(Control *Sender, ClickEventArguments &Arguments)
{
// do something
}



As a note, the function has the Sender argument so that you can use the same function for multiple controls.

Anyway, that's how I would set it up (hopefully nobody notices that this is pretty much exactly how WinForms works >_> <_<.)

Share this post


Link to post
Share on other sites
Quote:
Original post by evolutional
Seen some interesting stuff about so-called "Immediate mode" guis lately in which you effectively specify the GUI like:


res = gui.button("some text");
if(res.state == button.pressed)
{
// do button stuff, maybe fire an event off to the game or something
}


It's interesting because it does away with the whole event model and simplifies creating game guis, which are normally quite small anyway.

I believe Unity uses this approach too.


Sorry, I don't understand it very well, can you explain it more?

Thanks.

BTW, I'm using C++

Share this post


Link to post
Share on other sites
Basically, you keep a handle on the instance of a certain button, and manually check if it is pressed.

Share this post


Link to post
Share on other sites
Quote:
Original post by c_olin
Wow, I'm currently working on a minimalistic UI system, and that is ridiculously simple, and I don't see any obvious drawbacks.

I was going to use function pointers that are triggered on press. I feel like I completely over-complicated the problem.


I might be able to see some drawbacks, for example how exactly do you set/unset the pressed property? having each object query the input system to see if the cursor is on top of it and whether a button is pressed doesn't seem that efficient to me as opposed to propagating a single x,y button state event, and if you do that you're back either to the Observer Pattern or some sort of message system, except you'll be doing the same work again when you iterate over the controls to see which one is pressed if any.

So to me, on one side you're just pressing a button and the light turns on, but behind the wall there's a Rube Goldberg machine making it work.

or am I missing something? [smile]

Share this post


Link to post
Share on other sites
The draw backs i see are doing things like layouts. A hierarchical more orthodox UI has the natural relationships needed to perform relative positioning according to parents etc. If you wanted to do this with an immediate mode UI then you'd still have to be storing that information somewhere. Then, if you do store it somehow it might as well be a hierarchy anyways in order to do what you could just do with a retained UI.

From a Data POV an immediate mode UI assumes you have a backend that is already storing the data and that you can do a direct reflection of that data. Given the ratio of retained to immediate UIs out there that tells you two things:

- It's not as easy to understand how all the things that you can do in a retained UI are done in an immediate UI. So why bother when you already know how to do it in a retained way.

- It is hard to get working for large systems.


I've not seen any large scale projects used as examples of immediate UIs (i could have just missed them) but at the same time the examples i have seen have been so trivial as to be nearly pointless.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kwizatz
Quote:
Original post by c_olin
Wow, I'm currently working on a minimalistic UI system, and that is ridiculously simple, and I don't see any obvious drawbacks.

I was going to use function pointers that are triggered on press. I feel like I completely over-complicated the problem.


I might be able to see some drawbacks, for example how exactly do you set/unset the pressed property? having each object query the input system to see if the cursor is on top of it and whether a button is pressed doesn't seem that efficient to me as opposed to propagating a single x,y button state event...


Why does every object have to query the input? The UI system checks the mouse position when the mouse button is clicked, if it is over a button, that button's pressed flag is set to true.

Share this post


Link to post
Share on other sites
Quote:
Original post by c_olin
Why does every object have to query the input?


Because (as far as I understand it) that one function you see in the example is doing literally everything. It defines the button, renders the button and returns the state/event. Your gui can't check what the mouse is over or set some objects flag, because such an object doesn't exist. Elements only exist as a function call and event handling boils down to a crapload of if/else/switch orgies unless your gui is _really_ simple.

Share this post


Link to post
Share on other sites
Quote:
Original post by Trienco
Quote:
Original post by c_olin
Why does every object have to query the input?


Because (as far as I understand it) that one function you see in the example is doing literally everything. It defines the button, renders the button and returns the state/event. Your gui can't check what the mouse is over or set some objects flag, because such an object doesn't exist. Elements only exist as a function call and event handling boils down to a crapload of if/else/switch orgies unless your gui is _really_ simple.


Exactly, granted you could check once per frame and save the data, but you still have to make the check against your cached data once per button just to set the flag, then check the flag again in order to take action.

To me this is a lot like XML/SOAP, laughtably easy for the user, yet a pain to implement its inner workings.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kwizatz
laughtably easy for the user, yet a pain to implement its inner workings.


Sounds like every good API I've ever used.

Quote:
Original post by Dave
I've not seen any large scale projects used as examples of immediate UIs


Well there's Unity3D.

[Edited by - CadetUmfer on November 4, 2009 10:40:34 AM]

Share this post


Link to post
Share on other sites


// in CGame::Initialize() or whatever
myButton.OnClick = boost::bind(&CGame::myButton_OnClick, this, _1, _2);




Does CGame::myButton_OnClick() have to be static? Or does it bind the method of the instance it is bound in?

Share this post


Link to post
Share on other sites
Quote:
Original post by c_olin

*** Source Snippet Removed ***

Does CGame::myButton_OnClick() have to be static? Or does it bind the method of the instance it is bound in?


It binds. That's why the helper function is called boost::bind, and why 'this' is passed as a parameter. :)

Share this post


Link to post
Share on other sites
Is color picking commonly used in menus?
I thought it would make thing much easier that way:
The windows would occlude the others perfectly, if drawn in order.
Easy identification: for example red channel is the parent window identifier, and blue the ui control identifier (have to index them properly).
Non clickable ui control isn't drawn, non clickable window (it invoked a dialog for example) is drawn as black (non cickable), or green channel is the child dialogs identifier (so it can blink, or anything).
Not speaking of arbitrary shaped buttons.

Color picking has a great disadvantage anyway: only 256 windows, with only 256 ui controls in each of them.

Share this post


Link to post
Share on other sites
Quote:
Original post by Programmer16
Unless you need something more powerful (i.e. if you're making an in-game editor or something), I'd recommend going with the "immediate mode" UI system.

On the other hand, I'm not too fond of it myself lol. Dave's got the right idea, the best solution is to use delegates. The easiest way is to use BOOST; either the fuction handler or slots & signal system. Here's how my old system was setup:

*** Source Snippet Removed ***

As a note, the function has the Sender argument so that you can use the same function for multiple controls.

Anyway, that's how I would set it up (hopefully nobody notices that this is pretty much exactly how WinForms works >_> <_<.)


Can I do something like that without using BOOST or any other library?

Thanks.

Share this post


Link to post
Share on other sites
Yes, you would just have to reimplement what boost::function already does. IF you search for c++ and delegates you should find some articles about the inner workings and how to implement them. E.g. here: CodeProject.

But thats not exactly trivial. Thats why there are libraries like boost.

Share this post


Link to post
Share on other sites
Quote:
Original post by CadetUmfer
Quote:
Original post by Kwizatz
laughtably easy for the user, yet a pain to implement its inner workings.


Sounds like every good API I've ever used.



Yes, but we're talking here about doing all the work yourself, meaning you'll be the provider and the client, you're not really saving yourself any work, might as well balance the load.

Quote:
Original post by CadetUmfer
Quote:
Original post by Kwizatz
I've not seen any large scale projects used as examples of immediate UIs


Well there's Unity3D.


Not my quote, that one belongs to Dave.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement