Sign in to follow this  
glGuy3f

OpenGL GUI design

Recommended Posts

Didn't want to steal any of the well deserved thunder in the other GUI thread, so I made my own. I'm planning on making my own GUI (mostly for the learning experience) and I wanted some input on some design considerations. The only design decisions I've made thus far are 1) OpenGL (duh) 2) Object oriented 3) HTML/XML based configuration The goal will be to have something that is "self contained" and relatively easy to integrate with existing projects (something you could add to a GLUT example with minimal effort, for instance). What I'd really like to do (I think) is in the process of making the GUI, make a tool for creating GUI layouts. The tool spits out HTML/XML for the layout, and maybe c/c++ files for the hooks into your code. Thats my line of thinking anyway. Technical issues revolve around how to best make the GUI hook into the program (callbacks, etc), object hierarchies. how to handle events, etc. So, any suggestions/advice/hopes out there? What do you look for in a GUI? Thanks in advance

Share this post


Link to post
Share on other sites
Hi, I've got few general comments, that you might find useful.

Quote:

The only design decisions I've made thus far are
1) OpenGL (duh)
2) Object oriented
3) HTML/XML based configuration



2. You want to use OOP - good idea. IMHO best way to create GUIs, is to use tree structures - literally everywhere. So, you should create abstact class TControl with pure virtual functions like Update(), Render() etc., from that class you derive other classess like TButton, TCheckbox etc. that can reimplement what they want.

Also, tree structure of GUI actuall objects (that appear "physically" in application) is very handy - so that you can put 3 buttons in window, and when you move window - buttons move automatically, just because they are positioned relative to their father.
For navigating in such tree structure, I use concept similiar to hard drive directories and files - you can access each control by its full, absolute name. So, in above example with window and three buttons, you can get pointer to one of them by name "myWindow.myButton1". Other example: "MainMenu.Options.Player1Panel.Name".

Btw, it proved to be useable in real life situations, unlike some of my other "inventions" :-)

Quote:

how to handle events, etc.


In one of my GUI's I used callback system, and due to lack of safety (I had to juggle naked ID's myself) - using it was very annoying, and non-stop I had to fight with stupid bugs and typos. Man, that was exhausting. IMHO, I think callbacks are to error prone to be usable - though your needs may vary.

Then, in next GUI I tried my little invention: "callback classess", in which (theoretically) you create separate C++ classess (that inherit from TControlHandler, which has some virtual methods like OnLeftMouseButtonPressed() etc.) for each control, which is tedious, but I thought that it would give other benefits, ie. in one place you can implement several different functions for one object (like pressing left and right mouse buttons on control), you can easily introduce variables that are visible in all methods, you can add other functions to class without cluttering global namespace etc. But in practice it turned to be one big mess, impractical to use and also very annoying :-/


Now, after some initial reading, signals and slots have attracted my attention, and I'll probably use them in my next GUI. Read more:

Signals in QT
Signals in ClanLib


Btw, I strongly suggest to read also this: clicky, it's really great article for beginning! :-)

HTH

Share this post


Link to post
Share on other sites
Yes, I am indeed planning to use a Parent/child relationship (trees) for the GUI.

It would work something like this:
1) The "Master Object" (MO) is declared somewhere in your code (probably where you are doing all your initializaion)
2) The MO loads a GUI based on a config file you pass it on initialization
3) At some point in your main loop, you pass the MO an event (mouseup, mousedown, mousemoved, keyup, keydown, etc) and a location. The MO does the rest, figuring out which GUI item(s) need to respond.

This where things get tricky, and where some decisions need to be made. At some point, you need to execute code outside the MO (callbacks, signals, whatever). How much of the GUI do you expose to the developer? The config file can handle basic behaviors and effects... but if you want something more (creating your own neato effects), you have to provide the developer access to your classes and.... yuck.

Basically the problem is ease of use Vs. expandibility... I don't see how you get one without sacrificing the other.

Share this post


Link to post
Share on other sites
Quote:

At some point, you need to execute code outside the MO (callbacks, signals, whatever). How much of the GUI do you expose to the developer? The config file can handle basic behaviors and effects..


I thought about adding AngelScript commands inside my .xml files, since I will be using AngelScript anyway for my AI code, console etc. But, after thinking about it for a while, now IMHO doing it wouldn't be the wisest thing, since you would actually duplicate core functionality, without adding anything new to system. Except, for some bloat :-)

Ok, I know that sometimes ease of maintaining .txt files may be tempting, but please think for yourself - there will come time when you'll need to add new behaviours to your GUI, and in such moments, you'll probably use evil "copy n' paste" pattern.

In short: think of better ways of improving your GUI / spending your free time :-)


Quote:

but if you want something more (creating your own neato effects), you have to provide the developer access to your classes and.... yuck.


I don't understand this one - just give developer full, unrestricted access to public interface and be with it! And for creating neat effects, like blur, fading, glowing buttons, automatically moving windows, spinning textboxes (ok, I agree, it's rather late here, I need more sleep and less exams ;-) ) etc. just introduce those two virtual functions that I mentioned: Update() and Render(), and - give developer option to bind to them in two ways:


1. Derive from some control and reimplement ie. Render() - use it only when you need one global behaviour that is shared across all controls of one type. You could also use sth like subclassing, which is discussed in last link from last post, here: Code project and here: GUI class frameworks.

2. Add additional callback / signal / whatever, which is called each time Update() / Render() / Whatever() is called. Then, you may customize all your GUI controls easy way, without adding new classess, without reimplementing, deriving etc., by just plugging in to that thing. However, you can do it only on single control basis, and believe me: there's nothing worse than adding the same behaviour to many individual objects.

...

Ok, I was wrong in last sentence. There is much worse thing to do, than adding the same behaviour to many individual objects - it is, maintaining this behaviour, especially by small tweaks, that are needed for final, polished look! Now, that's a horror :-D


Quote:

Basically the problem is ease of use Vs. expandibility... I don't see how you get one without sacrificing the other.


Yup, it's standard problem in writing GUIs... expandability and flexibility are generally way to go, but also remember to KISS* :-)


* KISS = Keep It Simple Stupid

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this