ImGUI is one of the most popular graphical user interface libraries available for content creation, debugging, and visualization tools. Since this library can be used for many applications, it often becomes highly entangled and messy to work with.
As a game developer, I was tasked with implementing the main framework and a large amount of ImGUI content for a game called Arc Apellago. It was overall a simple game, but it also contained a surprising amount of ImGUI content.
Given the design of ImGUI, content separated across windows with some content on them, how can we clean the code up?
For one, we can contain all the functionality and related information for our given window in its own object. So far, a window is just a context and some updated content. First, let us make a class that holds a
showWindow_ class variable, and an
Update to update this window’s content.
A parent class that follows these requirements could look as follows:
When the previous image is reduced and grouped, you get the following:
This reduced-content window contains three major pieces of content:
- FPS / Display Statistics
- Debug Settings
- Collision Settings
As these are only related as configuration/stats content, we can break these up as well. To do so, let us create another class,
EditorBlock, which can be attached to any
These blocks of content are quite simple - just an update for the content they should display.
They both allow for separation of code and allows multiple teammates’ content on the same window if you are working on a team.
Next, we must adapt our current
EditorWindow to store these
It should be noted that the
Update function will now just call the
As an example of using the blocks, let’s implement the
StatsEditorBlock which displays the following:
ImGUI FPS stat has been omitted for simplicity.
Note that creating a class for each block allows it to implement helper methods and have internal state variables - which are often useful.
Now that all the functionality is abstracted out and self-contained in other classes, the interface is as simple as choosing which blocks go where.
// Create a window and give it a title
This layout separates unrelated code into manageable blocks to allow for easier layout planning and code decoupling. With ImGUI’s initialization and update code out of the way, it will be much easier for your teammates to create ImGUI blocks or windows as they require - this played a large role in my team’s final ImGUI implementation.
Some final notes and tips:
- Use the
ifdefparadigm to compile-out ImGUI from your project if you don’t want to ship with it and test that this define works regularly.
- Check out the docking branch of ImGUI to help organize your ImGUI windows further.