Hello, welcome to my second article about ImGui! This article is a collection of useful things, hacks and other stuff I’ve found while using ImGui. Mostly it’s focused on using modern C++ and some parts of STL with ImGui.
- How To Use Wxwidgets In Dev C 2b 2b 4
- How To Use Wxwidgets In Dev C 2b 2b 1
- How To Use Wxwidgets In Dev C 2b 2b 1b
- How To Use Wxwidgets In Dev C 2b 2b 8
If you use SFML and want to learn how to use it with ImGui, use my binding and refer to this tutorial about setting it up!
- Programming C GUIs with the wxWidgets Library The wxWidgets library makes programming GUIs incredibly easy, far easier than with most platform APIs. Jeff Cogswell shows how this handy C library can shorten your programming time with powerful classes that are simple to use. Written by Jeff Cogswell.
- This chapter introduces the idea of the device context, generalizing the concept of a drawing surface such as a window or a printed page. It will discuss the available device context classes and the set of 'drawing tools' that wxWidgets provides for handling fonts, color, line drawing, and filling.
- Welcome to wxWidgets, a free and open source cross-platform C framework for writing advanced GUI applications using native controls. WxWidgets 3.1.3 is the latest release in the 3.1 development branch.
- Uff, long time since I worked with Dev-C, but basically you need to tell your compiler where to find the wxWidgets library. It should be somewhere around Compiler Options - Include Directories or the likes.
Different ImGui widgets (taken from ImGui's github page)
If you didn’t read the first article, here’s a short recap to get you started.
Use the Developer Command Environment and rebuild wxWidgets from the source. Your platform (32-bit/64-bit) must match the wxWidgets libraries in order for you to use them. A lot less headaches to build wxWidgets to suite your development environment. – Thomas Matthews Jun 23 '16 at 15:06. WxMidi is a C wrapper for wxWidgets around the PortMidi library. With this component, software developers using the wxWidgets application development framework can add MIDI in/out support to any wxWidgets application. Dev-C is a nice Free IDE for Windows that works quite well with wxWidgets. See their website here There is a binary package available in devpak (Dev-Cpp package format) available here, don't get the version from vUpdate (it is old). You need to install the newest (beta) version of devc, but generally, it's worth it.
Dear ImGui is an amazing library which can be used to create fast GUI for your game dev (and not only!) tools in very short amount of time. The resulting code is very simple to use and modify, you don’t have to store GUI widgets or register callbacks. Here’s some stuff that I’ve made in ImGui for my game:
Level Editor
Animation editor
Okay, enough of intros, let’s get right to tips.
First of all, it’s very useful to check out ImGui test window and its source to see how various things can be done. You have to add imgui_demo.cpp to your build and then call ImGui::ShowTestWindow
to show the window. Because there are so many examples, I won’t go over them and just focus on other stuff.
Labels are used in ImGui as unique IDs for widgets. You shouldn’t use same labels for two different widgets as it will introduce collisions between widgets and that will lead to some unwanted behavior.
Suppose you have two buttons with label “Meow” and you have a code like this:
The first button works as expected, but the second doesn’t work at all! These are the things that can happen when collisions occur between IDs. This won’t happen most of the time, after all there’s mostly no need to place two buttons which say the same thing in one window. But what if you really need these two “Meow” buttons? The solution is simple: you just have to add “##” and some stuff after that to resolve the collision:
All the text after “##” is not displayed and only used to give unique IDs to widgets with same labels.IDs should be unique in the same scope, so it’s okay to have two widgets with the same label in two different windows or have one of them in some tree or list (trees, lists and some other widgets have their own scopes, so collisions won’t happen between items in them and other items).
Let’s look at another situation. Suppose you have an array of int
s:
And now you want to create a bunch of InputInt
widgets for each array element. ImGui::PushID
/PopID
come to the rescue! You can push int
s, const char*
or void*
as IDs which will be appended to the label of the next created widget (but won’t be shown). For example, you can do this:
There are some situations where you don’t have an int
which you can use as part of ID, for example if you want to use for-ranged loop with the std::array
. In that case, you can use pointers to elements of the array which will be unique:
Suppose that you need to add some stuff to the window you’ve created before but you already called ImGui::End
. No problem, just call ImGui::Begin
with the name of the window in which you want to append stuff. Here’s an example:
How To Use Wxwidgets In Dev C 2b 2b 4
Sometimes it’s useful to use InputFloat2
or InputFloat4
with your point or rectangle structs which can be defined like this:
Using them with InputFloat2
or InputFloat4
is easy:
How To Use Wxwidgets In Dev C 2b 2b 1
This works because both Point
and Rect
structs are POD and don’t have “holes” in them, so the data they store is contiguous and can be interpreted as array of floats.
This method is not very safe, of course, so use it at your own risk. Someone can modify the struct and this may break your code which assumed that the floats you want to modify are stored contiguously. Unfortunately, there’s no way to pass array of pointers to InputFloat2
or InputFloat4
, but you can easily create your own solution. Let’s make a function which creates a widget similar to InputFloat4
and uses members of Rect
struct explicitly:
And now you can do this:
There are lots of things to be said about using ImGui with STL. ImGui doesn’t use STL at all and users have to pass raw arrays and const char*
s instead of std::vector
s and std::string
s, so you can’t just use STL and some modern C++ right away, but it can be done with some work.
Arrays
How To Use Wxwidgets In Dev C 2b 2b 1b
Some widgets require you to use raw arrays but those are not the best because you can’t use them with algorithms, for ranged loops, etc. And the other problem is that you have to manage the memory of variable size arrays yourself using new
and delete
. Using std::array
with Imgui::InputInt4
which expects you to pass raw array is easy, just do it like this:
std::array::data
returns a pointer to raw int array which can be passed to ImGui::InputInt4
.
The same can be done with std::vector
s which are guaranteed to be contiguous, so you can just use std::vector::data
the same way:
ComboBox, ListBox
ComboBox
and ListBox
can be used with arrays of const char
s, but what if you have std::vector<std::string>
instead? You have to redefine callback which ImGui calls to get next item of the array. Here’s how you can write Combo
and ListBox
wrappers for std::vector<std::string>
:
Ugh, that’s not the prettiest code, but it works. We store pointer to our vector in void*
and cast it back to vector in our lambda. What’s good about that code is that we don’t create any copies of strings and just use const char
pointers stored in std::string
s from our std::vector
.
InputText and std::string
ImGui lets you pass char array in InputText
and then it modifies it when user enters some text in the input field. The problem is that it’s hard to know the size of input in advance, so you have to allocate large enough buffer and then pass it in InputText
.
We can use std::vector<char>
as our buffer instead of using raw arrays. If the size of buffer is known at compile time, you can use std::array<char, N>
, where N
is the size of the buffer.
You can then create std::string
from your buffer like this:
One of std::string
constructors takes const char*
so we get it by calling data
.
Be careful when using std::string
as input buffer! Sure, you can always call std::string::resize
and allocate enough space, but don't use it in string handling code, because the string may contain zeros or trash and this can lead to some nasty bugs. The size of the string may not be what you expect. Moreover, when ImGui changes std::string
's internal char array, it doesn't modify it's size which can be another source of hard bugs.
Callbacks
ImGui lets you add callbacks to different widgets. Let’s make a silly callback which replaces all user input with char ‘A’.
First you define a free function:
How To Use Wxwidgets In Dev C 2b 2b 8
And then pass it to InputText
:
You can also use stateless lambdas which can be used just as free functions:
Suppose we don’t want to hard-code replacement character and want to use a char variable instead. We can’t capture the state in our lambda (it can’t be used as a free function), so we store the pointer to char in ImGuiTextEditCallbackData::UserData
:
Not bad, but capturing the state is so much prettier! And what if you wanted to pass more than one variable? This would get much harder, so I’ll show you how to use lambdas with state with ImGui!
Let’s define our own function which will lets us pass lambdas with state:
Here’s how it works: we create another lambda which is stateless and calls our original lambda which is stored in ImGuiTextEditCallbackData::UserData
. And now we can pass lambda with state like this:
Nice! But we can do better, because if we want to do the same with other widgets, we have to do the same thing over and over again. So let’s generalize the approach. First of all, let’s create a function which returns stateless lambda from lambda with state:
This is the same approach we’ve used in InputTextCool
function. function_traits<F>::arg_t<0>
gets us the first argument of passed lambda. These traits can be defined like this:
And now we can do this:
We can do the same thing “inline” like this:
Note that we had to store our lambda type in ReplacementLambdaType
type alias to cast from void*
later. This is almost the same as the previous approach (which I like more!).
ImGui is a wonderful library and it’s cool that you can easily expand it and use with all the stuff you like. There are some other tricks and tips I have to share, but this article got pretty big and so another part of this article will probably happen some day.
If you want to know about something or have something to share, feel free to do it in comments, I’ll use it for the next article. See ya!
Follow me on twitter @EliasDaler to not miss the new stuff!