How to Build User Interfaces with ImGui


GeeXLab + ImGui

Dear ImGui (or ImGui in short!) is a powerful library to draw user interfaces (widgets) in OpenGL or Vulkan applications. The freshly released GeeXLab 0.17.0.1 comes with ImGui support. ImGui has a lot of functions for drawing user interfaces and GeeXLab comes with a subset only, because implementing all those functions would have taken too much time.

In the current GeeXLab, the following objects are supported:
– windows
– texts and colored texts
– checkboxes
– progress bars
– buttons
– sliders (1D and 4D)
– trees
– plotlines

Thanks to these widgets, we have the main features we need for most of the demos. I also tested ImGui’s combo boxes and list boxes and I hope to add them shortly.

ImGui is an immediate mode library: you have to build all ImGui windows and widgets each and every frame. Once you understand it, you can really start using ImGui functions. The immediate mode allows you to make the displaying of ImGui widgets really dynamic: you can change the position, size, content of every widget at any time. You can add a new widget or remove an existing widget at any moment.

Minimal ImGui Canvas

Let’s see how to use the new ImGui functions. A new library is available for ImGui: gh_imgui.

The first thing to do is to initialize ImGui in a INIT script:

1
gh_imgui.init()

The second thing is to clean up ImGui resources in a TERMINATE script:

1
gh_imgui.terminate()

Now all important things will take place in the FRAME script. The first ImGui function to call in a FRAME script is gh_imgui.frame_begin(). This function sets the current drawing aera and transmits mouse data. The last ImGui function to call is gh_imgui.frame_end(). Between both functions, you can call any other ImGui drawing functions.

Here is a minimal FRAME script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
winW, winH = gh_window.getsize(0)
 
gh_renderer.set_scissor_state(1)
gh_renderer.set_viewport_scissor(0, 0, winW, winH)
gh_renderer.clear_color_depth_buffers(0.2, 0.2, 0.2, 1.0, 1.0)
 
local LEFT_BUTTON = 1
local mouse_left_button = gh_input.mouse_get_button_state(LEFT_BUTTON) 
local RIGHT_BUTTON = 2
local mouse_right_button = gh_input.mouse_get_button_state(RIGHT_BUTTON) 
local mouse_x, mouse_y = gh_input.mouse_get_position()
 
 
gh_imgui.frame_begin(winW, winH, mouse_x, mouse_y, mouse_left_button, mouse_right_button)
 
--
-- You can call ImGui drawing functions between frame_begin() and frame_end().
--
 
gh_imgui.frame_end()

The rest of the tutorial will be focused on ImGui functions to call between gh_imgui.frame_begin() and gh_imgui.frame_end().

Text

gh_imgui.text() and gh_imgui.text_rgba() allows to print a text in a window:

1
2
gh_imgui.text("Hello (with default color)")
gh_imgui.text_rgba("Hello (yellow color)", 1.0, 1.0, 0.0, 1.0)


GeeXLab + ImGui

Did you notice the caption of the windows? It’s ImGui default window that is displayed if we do not specify our own window.

Window

To draw a window, we have to call two functions: the beginning and the end of the window:

1
2
3
4
5
6
7
8
9
10
11
12
width = 300
height = 200
pos_x = 20
pos_y = 20
window_flags = 0
pos_flags = 4
size_flags = 4
gh_imgui.window_begin("Test Window", width, height, pos_x, pos_y, window_flags, pos_flags, size_flags)
 
gh_imgui.text("Hello")
 
gh_imgui.window_end()


GeeXLab + ImGui

The various flags control the look and behavior of the window. Here are the possible values for window_flags:

1
2
3
4
5
6
window_default = 0
window_no_resize = 2
window_no_move = 4
window_no_collapse = 32
window_show_border = 128
window_no_save_settings = 256

Here are the possible flags for pos_flags and size_flags:

1
2
3
pos_size_flag_always = 1 -- Always set the pos and/or size
pos_size_flag_once = 2 -- Set the pos and/or size once per runtime session (only the first call with succeed)
pos_size_flag_first_use_ever = 4  -- Set the pos and/or size if the window has no saved data (if doesn't exist in the .ini file)

Separator, Same Line, Bullet and Vertical Space

A SEPARATOR is an horizontal line. A SAME_LINE allows to draw several widgets on the same line (useful for texts that include words of different color). A BULLET draws bullet (useful for lists). A vertical space allows to add more vertical space between two widgets.

1
2
3
4
5
6
7
8
9
local IMGUI_WIDGET_SEPARATOR = 1
local IMGUI_WIDGET_SAME_LINE = 2
local IMGUI_WIDGET_BULLET = 3
local IMGUI_WIDGET_VERTICAL_SPACING = 4
 
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_SEPARATOR)
gh_imgui.widget(IMGUI_WIDGET_BULLET)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)

Here a concrete example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
local IMGUI_WIDGET_SEPARATOR = 1
local IMGUI_WIDGET_SAME_LINE = 2
local IMGUI_WIDGET_BULLET = 3
local IMGUI_WIDGET_VERTICAL_SPACING = 4
 
gh_imgui.text("Hello (with default color)")
gh_imgui.text_rgba("Hello (yellow color)", 1.0, 1.0, 0.0, 1.0)
gh_imgui.widget(IMGUI_WIDGET_SEPARATOR)
 
gh_imgui.text("text (default color) +")
gh_imgui.widget(IMGUI_WIDGET_SAME_LINE)
gh_imgui.text_rgba(" yellow text", 1.0, 1.0, 0.0, 1.0)
 
gh_imgui.widget(IMGUI_WIDGET_SEPARATOR)
 
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.text("height VERTICAL_SPACING before this line")
 
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
gh_imgui.widget(IMGUI_WIDGET_SEPARATOR)
gh_imgui.widget(IMGUI_WIDGET_VERTICAL_SPACING)
 
gh_imgui.text("A list:")
gh_imgui.widget(IMGUI_WIDGET_BULLET)
gh_imgui.text("item 1")
gh_imgui.widget(IMGUI_WIDGET_BULLET)
gh_imgui.text("item 2")
gh_imgui.widget(IMGUI_WIDGET_BULLET)
gh_imgui.text("item 3")

And the result:


GeeXLab + ImGui

Button

To draw an interactive button just call gh_imgui.button(). The button function returns its state: pressed or not.

1
2
3
if (gh_imgui.button("Click me") == 1) then
  -- do something if pressed.
end

Progress bar

To draw an interactive progress bar, call the gh_imgui.progress_bar() function. In the following code snippet, the progress bar is set to 35% of progression:

1
2
3
4
fraction = 0.35
size_x = 0 -- for automatic width
size_y = 0 -- for automatic height
gh_imgui.progress_bar(fraction, size_x, size_y, "A progress bar set to 35 %")


GeeXLab + ImGui

Checkbox

To draw an interactive checkbox, call the gh_imgui.checkbox() function. The checkbox function returns its state: checked or unchecked.

1
2
3
4
initial_state = 0
if (gh_imgui.checkbox("Checkbox", initial_state) == 1) then
  -- do something if checked.
end

1D Slider

To draw an simple slider (that control a single value only), call the gh_imgui.slider1f() function. This function returns a value according to the position of the slider.

1
2
3
4
5
6
initial_state = 0
local min_value = 0.0
local max_value = 1.0
local power = 1.0 -- Use power!=1.0 for logarithmic sliders.
local initial_value = 0.5
slider_value = gh_imgui.slider_1f("Slider 1f", initial_value,   min_value, max_value,   power)


GeeXLab + ImGui

 

Code Samples

I think that most of the basic functions of the gh_imgui library has been covered. More functions (trees, slider4f, plotlines) are available in the full version of the code sample pack:

– gl-21/imgui/demo_02.xml (OpenGL 2.1)
– gl-32/imgui/demo_02.xml (OpenGL 3.2+)
– vk/imgui/demo_02.xml (Vulkan)

The demo for this article is available here:
– gl-32/imgui/test01.xml (OpenGL 3.2+)

For any feedback or question, a forum is available HERE (english) or HERE (french).

A nice overview of ImGui functionalities is available by calling the show_test_window() function. This function draws two windows and shows a lot of ImGui features. Many of them are not available yet in GeeXLab. But it’s cool to see them in action:

1
2
3
4
5
gh_imgui.frame_begin(winW, winH, mouse_x, mouse_y, mouse_left_button, mouse_right_button)
 
gh_imgui.show_test_window()
 
gh_imgui.window_end()


GeeXLab + ImGui

3 thoughts on “How to Build User Interfaces with ImGui”

  1. ericb

    What you propose looks extremely interesting, and I coud probably help to make the Linux version work, but how to download the source code ? FYI, the Linux download is completely broken : it does start, and after ~ 1 MB, it is stalled, and fails.

  2. JeGX Post Author

    Thanks for your feedback Eric ( c’est ton site: http://eric.bachard.free.fr/news/ ? ).
    I just made some minor changes in the downloads, could you please try to download the linux version again?

    ImGui is available from the branch 0.17 of GeeXLab. So you won’t be able to test ImGui functions with GeeXLab 0.16.1.1 for Linux. I hope to update Linux, macOS and RPi very very shortly.

    Just saw your tab module for ImGui. Sounds nice! I will try to test it and why not, add it to GeeXLab.

  3. ericb

    Hello,

    Ok, I’ll wait. I’ll provide my prefered mail in the comment, and you’ll just have to ping me once a Linux version will be available, or if you need help (no promise, but just in case).

    About ImGui tabs: I think something is still buggy, and -one day- I’ll fix other bugs. e.g. when you resize the window, the scrollbar does some strange effects, and overlaps the window. Probably yet one other wrong constant used in the tab size computation or something close.

    There is a screenshot (at the bottom of the page) : https://github.com/ScottMudge/imgui_tabs/issues/1

    P.S. : oui, c’est mon site (mais je n’ai rien posté depuis …. ouh ça fait longtemps, mais ça me démange 🙂

Leave a Comment

Your email address will not be published. Required fields are marked *