GLIMGUI released

March 26, 2014

Ages ago I wrote a nice article about how I searched for a simple GUI system for a game that I was working at the time. I ended up writing my own GUI system that was using the IMGUI approach and I am still very happy with this. It indirectly inspired @the_vrld to create Quickie which is an IMGUI system for my favourite 2D game framework LÖVE.

In the article I had written that I plan to release a simple library that can be used as a starting point for more advanced IMGUI explorations. Turns out I never did publish it so here we go:

Grab the code from: https://bitbucket.org/MartinFelis/glimgui.

It is licensed under the MIT license and as said very basic but with ~500 lines it should also be very easy to adjust and extend it. It is written in plain C and only depends on OpenGL and glut. Only ASCII strings are supported but if you have a fully featured unicode rendering function available it should be very easy to plug it in (look at glimgui_printxy(float x, float y, const char str*, ...)).

Here are some screenshots (very basic but easy-peasy to pimp): main_menu options

And here the full source code for the UI including the button logic that was used for the screenshots:

void draw_ui () {
  glimgui_prepare ();

  // Drawing of the GUI

  // We have two GUIs that are indicated by the global gui_layout value
  if (gui_layout == 0) {
    glimgui_label (99, "Main Menu", 20, 20, 1, 1); 

    if (glimgui_button (1, "Some Button", 220, 100, 180, 50)) {
      printf ("Some Button was pressed!\n");
    }

    if (glimgui_button (2, "Options", 220, 180, 180, 50)) {
      glimgui_clear();
      gui_layout = 1;
      printf ("Switching to Options!\n");
    }

    if (glimgui_button (3, "Quit", 220, 380, 180, 50)) {
      printf ("Quit!\n");
      glutDestroyWindow(window_id);
    }
  } else {
    glimgui_label (99, "Options", 20, 20, 1, 1); 

    if (glimgui_button (1, "Some Other Button", 220, 100, 180, 50)) {
      printf ("Some Other Button was pressed!\n");
    }

    glimgui_label (98, "Enter your name:", 150, 180, 1, 50);

    static char name[32] = { "IMGUI fan\0" };

    if (glimgui_lineedit (2, name, 16, 290, 195, -1, 20)) {
      printf ("Changed name value: '%s'\n", name);
    }

    glimgui_label (97, "Enter your age:", 150, 210, 1, 50);

    static char age[32] = { "99\0" };

    if (glimgui_lineedit (3, age, 3, 290, 225, -1, 20)) {
      printf ("Changed age value: '%s'\n", age);
    }

    if (glimgui_button (4, "Back", 220, 380, 180, 50)) {
      printf ("Switching back!\n");
      glimgui_clear();
      gui_layout = 0;
    }
  }

  glimgui_finish ();
}

Nice, ey?

Tags

Quest for a GUI (or Simple GUIs for Games)

September 13, 2010

This post describes my quest for a simple graphical user interface for my Asteroids clone.

What has happened so far

In my Asteroids clone I had an extremely simple GUI in which one had to press specific keys in the main menu. Return started the game, ‘h’ showed the highscore and ‘q’ quit. When starting the game, the player was presented with a screen where he/she/it could enter a name, after pressing the return key the actual game would start. I encapsulated the drawing and the input processing in the class Overlay and had for each state (MainMenu, ShowHighscore, EnterPlayername) different subtypes of the Overlay class. This all worked okay for this very simple UI, however I wanted to have a proper menu where one could use the arrow keys and maybe even the mouse. For this, my previous approach would have to be hacked up that I wanted to avoid as I found having these multiple Overlay classes tedious. So there was a need for a proper GUI.

Related Work

The popular general-purpose GUI library Qt (read: “cute”) impressed me a lot, as it allows one to display Qt widgets within OpenGL as is demonstrated in this post. As Qt is well supported on major OS’ this was a big plus. Additionally Qt has a lot of tools for GUI creation and whatnot, however for my simple purpose this all would have been an overkill, as I merely need just a few buttons and maybe some text input. Still, the capabilities of the library were very impressive. The site http://labs.trolltech.com also has a lot of entries which talk about how to do OpenGL with Qt.

I needed a simple approach that would be able to render widgets within OpenGL if possible open-source. From earlier game GUI research I had a short look on libraries like CEGUI, clanlib, seemed too complicated for my simple purpose. GLUI is a little older however seems to work but did not look as intended for game user interfaces. There are a few more, such as GLAM and libUFO, that I had a short look at, however they also did not seem to be actively maintained for quite some time. GLGooey is also a bit dated however seemed quite nice concerning the programming interface. There are much more but nothing entirely catched me.

In the commercial world Scaleform, that uses Flash, seemed very interesting and powerful, however as no pricing was listed on their page it seemed doubtful it would be a price I would be willing to pay for my simple purpose. Additionally for a small amateur project this would not be the right choice as I want to mainly program a game, not design a super fancy user interface. Awesomium is used by Wolfire Games for the user interface and allows one to use HTML, Javascript and CSS for the Userinterface. Nice! However also costs money that would be too much for my purpose. (Note: Over on http://www.pathogenstudios.com they use Berkelium which is supposed to be similar to Awesomium and open-source, I just found when I already had my own solution for the GUI problem…).

Retained mode GUI

In a classical “retained mode GUI” (a.k.a. RMGUI) one creates Widgets, connects events such as “OnButtonPress”, “OnMouseHover”, “OnTextEnter” with callback functions that are processed whenever the events occur. This is also sometimes called event-driven. The created widgets are registered with some WidgetManager that checks whether the events have happened (e.g. checks whether the mouse is over a button and if it detects it was clicked, it reports a “OnButtonPress” event by calling the associated callback function). In the Qt library they created the Signal-Slot-mechanism just for that purpose.

As with everything, there is a catch. Implementing such a system is not straight forward. It usually results in quite a number of classes and one has to wire up all the callbacks to the events. Additionally for each action that should be performed by a button one needs a callback function. Qt does all this in a very convenient way, however implementing their Signal-Slot-mechanism would be too much for what I want to do.

The reasons why I don’t like this approach are that I don’t want to implement a whole widget managing system and additionally I would end up with a lot of small callbacks for the buttons in the menu. In the main menu most of them would only set the game state from MainMenu to ShowHighscore, eg. SetMainMenuState() and SetShowHighscoreState().

Immediate Mode GUI

I don’t know how I got there, but I read somewhere about “immediate mode GUIs” (a.k.a. IMGUIs). One of the main proponents is Casey Muratory from Molly Rocket. There is a video where he gives an introduction to IMGUIs. I had a short look at the first minutes of the video a few months ago, but then got distracted and forgot about it. A few weeks ago, however I stumbled over the tutorial of Jari Komppa. It gives a nice and clear introduction what the idea of IMGUIs are and how they work, along with sample code that uses the SDL and OpenGL, that convinced me my quest is over.

Basically one does not create widgets and connect them with callback functions, instead one only calls functions that perform the drawing and check simultaneously whether certain events have happened. As logic for differs for each widget type one has for each widget type one function. For widgets like buttons or a text edit this function would return true if the button was pressed or the text was changed, respectively.

When drawing your UI this results in code of the form (example for a button):

if (IMGUI_button (StartButtonId, "Start", x, y, w, h)) {
	SetGameState (GameStateEnterPlayerName);
}

The only thing here that might arise questions is the StartButtonId. This can be any value other than 0 and must not collide with the Id of another widget that should be visible on the screen.

From the programmers point of view, a text edit could look like this:

char *name_value = GetPlayerName(name_value);
if (IMGUI_textedit (TextEditId, name_value, 32, x, y, w, h)) {
    SetPlayerName(name_value);
}

That’s it! This simple line displays and allows modification of the player name!

You have to pass a pointer (or in C++ maybe a reference) of the string that should be displayed and modified, the maximum length of the string and the position and size of the edit widget. There is still some code that needs to be called at the beginning and the end of the frame, but this is everything you need to do for the widget.

A huge advantage of this is, that for a programmer it is very easy to read. Also it is very easy to build interfaces for the most common menus, including settings screen with sliders, text edits, checkboxes and whatnot. Even for handling input of the mouse and keyboard simultaneously it is the same code!

But also IMGUIs have their flaws (of course!). They require a high framerate as there is always a 1 frame latency (e.g. for text entries). However if you redraw your screen anyways (as I am currently doing it) this should be okay.

IMGUI vs RMGUI

One might ask, why not everyone is using this approach. There is also a quite long discussion about IMGUI vs. RMGUI over on GameDev (http://www.gamedev.net/community/forums/topic.asp?topic_id=545995). Most criticisms are:

Efficiency is not a problem for me, as neither my game nor my current GUI even remotely scratch on the hardware limits. Of course it is very simple, but I won’t optimize here before it is necessary.

My current GUI designer is actually very happy with the IMGUI approach. However my GUI designer also knows how to program, so I might be in a very prestigious position, but this might be alleviated that I *am* my GUI designer.

“Paradigms used by IMGUIs is anachronistic”? Well … so what? This doesn’t mean I have to do everything in a anachronistic way. Additionally the IMGUI plays very well together with a MVC for which the state of the UI is stored in the Controller and the drawing is performed in the View. (Okay, this might be put a little too optimistic, as the drawing functions do modify the UI state, however in this case a tighter coupling between the View and the Controller is okay in my opinion).

Conclusion

So in total IMGUIs might not be perfect for everyone, but should you be an amateur game programmer and want to add a GUI with keyboard and mouse support, I highly recommend giving it a shot! IMGUIs are very easy to implement and should you really need something more sophisticated, you can still switch to something else. But I guess you probably won’t. Some poeple are actually very happy with this approach of GUI programming, see here: http://blogs.unity3d.com/2009/08/17/doing-a-talk-at-gdc-europe-tomorrow/.

I plan to write up a small sample library under a liberal open-source library that can be modified to your needs. You will read about it somewhere on this blog.

Further Reading

Tags