Page 1 of 1

Gui system

Posted: Sat Oct 30, 2010 12:32 pm
by adikid89
I've been working on a gui system for Moosader's "Picking Open Sticks" game, and although it's not too polished and it's kinda lame, I think it's awesome!:D ... so I thought I'll share what I got done so far... maybe get some constructive criticism from other people who made gui systems(or similar stuff) on how they made theirs :D.

Here's basically how it looks like:
Image

I implemented so far a basic widget(which is the base widget - doesn't do much), a label widget(-displays text), a line_edit widget(-you can enter text in it), and a button widget.
Widgets have focusing levels, and when you click on a widget it gets focus, meaning that it is drawn before the other widgets and it receives the keyboard input events!
Also you can move widgets using drag&drop :D.

It works "kinda" like qt does(notice the "" ...) though way lamer. For example if you want to get user input for his name you can make a class UserNameWidget : public Widget, and you add a line_edit widget and a button widget to it. And when the button is clicked you save the text from the line_edit to a string in the UserNameWidget(where it will be accesible), clear the line_edit text and maybe change the game's state to notify the change(or you can have a flag in the class to notify that the user has entered the name )

I didn't implement a slots/signals pattern, I found it rather difficult to do.. so I made a set of virtual functions(which you can reimplement in derived classes) that get called when a event of sorts happens.
here's a code example of how to use it :D

Code: Select all

//create a widget
   gui::Label label;
//initialize with default image .. or you can use your own image
   label.SetDefaultImage();
//set the position of the widget. default = 0,0
   label.SetPos(550,0);
//set the alignment of the text --label specific function
   label.SetAlignment(gui::Center);
//add the label to the guimanager(*making it a main widget), or to another widget(*making it a child widget)
   gui::GuiManager::GetSingleton().AddWidget("label",&label);
L.E. : The Picking Open Sticks project is available at google code

Re: Gui system

Posted: Fri Nov 05, 2010 7:00 pm
by eatcomics
That's really sweet, and I'm really happy to see POS (Lol, the name implies its a pile) is coming along so great :D

Re: Gui system

Posted: Mon Feb 21, 2011 10:00 am
by adikid89
Necroing this thread because I updated the library a tad :lol: . I wrapped the gui system in a nice little static library. I also implemented widget composition(meaning widgets can contain other widgets) that I really wanted to do a long time ago.

The most significant improvement is the fact that now it's actually usable! Before you weren't really able to do anything with it, because it turned out to be sooo quarky to use, you weren't really able to manipulate data.. as in, the widgets had no knowledge of the rest of the game, so that meant it couldn't affect the state of the game, thus rendering the entire gui system.. rather useless.. if it makes sense.
The only way you change the game state, is that I made a Clicked() function , and you'd call that to check if the widget was clicked. And the function was very buggy it just barely worked.
The way I did it now, is that I am actually allowing 3 different approaches to handling the events, and manipulating data accordingly:

1. The Giant Invisible Behind-the-Scenes Widget Master-Mind
This is probably my favorite approach. You have one screen-sized invisible widgets where you will place all data the needs to be accessed/modified(that's where a pointer to your game goes), and you add all the other widgets to it. The reason why this would be useful, is because every child widget, upon receiving an event, will also redirect that event to the highest-order parent widget. So you'll make a MyWidget : public Widget, and overload the OnChildEvent functions, and you can make a switch on the child's name, and based on the widget, you can modify the game state. An example would be, The Start Game button. when OnChildEventClickPressed() occures on your master-mind widget, and widget's name is "startButton_widget", then you'd do something like game->StartGame(); I hope it makes sense to people.. I'm not sure how else I could better explain.

2. Functor Callbacks
I guess method isn't half bad either, you'd make a MyFunctor : public gui::Functor, and overload the virtual operator() (the parentheses operator). You can also place the data you need to be accessed/modified in it. And example would be..

Code: Select all

struct MyFunctor: public gui::Functor {
     void operator() (){ if(game) game->Start(); }
     Game* game;
};
And you would connect the functor to a certain event, like this: widget->SetHandler(gui::ON_CLICK_PRESSED, new MyFunctor());

3. Random Access
This is the worst idea, I might remove/replace it. It is just the method I first used, I haven't removed it yet. You can't really access/modify the game state directly, instead, the game needs to query for the state of the widgets.

Code: Select all

Widget* widget = m_gui.FindWidgetByName("startButton_widget");
if(widget && widget->Clicked()) 
   game->Start();
I'm thinking I'll add another way to use it...which is The Adaptor. Basically you'd assign an Adaptor class to the GuiManager. In your game class or whatever you have, you hold the Adaptor, and you let the GuiManager that you want to use an adaptor, which will redirect the events. An example of how it'll look:

Code: Select all

m_gui->SetAdaptor(&m_adaptor);
//.. then..in an update method or something you can query the adaptor for events
while(m_adaptor->NextEvent()) {
   if(m_adaptor->GetWidget()->GetName() == "startButton_widget")
      m_startGame = true;
}
... or something. I don't exactly know.. because it't not implement yet.. but it does look nice.. I'll probably add that too for flexibility's sake.

And here's a reward for reading the wall of text!