You may link to this document using short form: https://www.dearimgui.com/faq or its real address: https://github.com/ocornut/imgui/blob/master/docs/FAQ.md or view this file with any Markdown viewer.
This library is poorly documented at the moment and expects the user to be acquainted with C/C++.
ImGui::ShowDemoWindow()
function. The demo covers most features of Dear ImGui, so you can read the code and see its output.ImGui::ShowMetricsWindow()
function exposes lots of internal information and tools. Although it is primarily designed as a debugging tool, having access to that information tends to help understands concepts.This library is called Dear ImGui. Please refer to it as Dear ImGui (not ImGui, not IMGUI).
(The library misleadingly started its life in 2014 as “ImGui” due to the fact that I didn't give it a proper name when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations e.g. Unity uses it own implementation of the IMGUI paradigm. To reduce the ambiguity without affecting existing code bases, I have decided in December 2015 a fully qualified name “Dear ImGui” for this library.
I occasionally tag Releases but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
You may use the ‘docking’ branch which includes:
Many projects are using this branch and it is kept in sync with master regularly.
Read Getting Started.
Read EXAMPLES.md.
Read BACKENDS.md.
Read PROGRAMMER GUIDE
section of imgui.cpp.
The Wiki is a hub to many resources and links.
For first-time users having issues compiling/linking/running or issues loading fonts, please use GitHub Discussions.
You can read the io.WantCaptureMouse
, io.WantCaptureKeyboard
and io.WantTextInput
flags from the ImGuiIO structure.
io.WantCaptureMouse
is set, you need to discard/hide the mouse inputs from your underlying application.io.WantCaptureKeyboard
is set, you need to discard/hide the keyboard inputs from your underlying application.io.WantTextInput
is set, you can notify your OS/engine to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).Important: you should always pass your mouse/keyboard inputs to Dear ImGui, regardless of the value io.WantCaptureMouse
/io.WantCaptureKeyboard
. This is because e.g. we need to detect that you clicked in the void to unfocus its own windows, and other reasons.
void MyLowLevelMouseButtonHandler(int button, bool down) { // (1) ALWAYS forward mouse data to ImGui! This is automatic with default backends. With your own backend: ImGuiIO& io = ImGui::GetIO(); io.AddMouseButtonEvent(button, down); // (2) ONLY forward mouse data to your underlying app/game. if (!io.WantCaptureMouse) my_game->HandleMouseData(...); }
Note: The io.WantCaptureMouse
is more correct that any manual attempt to “check if the mouse is hovering a window” (don't do that!). It handles mouse dragging correctly (both dragging that started over your application or over a Dear ImGui window) and handle e.g. popup and modal windows blocking inputs.
Note: Text input widget releases focus on the “KeyDown” event of the Return key, so the subsequent “KeyUp” event that your application receive will typically have io.WantCaptureKeyboard == false
. Depending on your application logic it may or not be inconvenient to receive that KeyUp event. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard
to enable.io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad
to enable (with a supporting backend).USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
section of imgui.cpp for more details.style.TouchPadding
setting) to accommodate for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing for screen real-estate and precision.Your renderer backend is not using the font texture correctly or it hasn't been uploaded to the GPU.
ImGui_ImplXXX_NewFrame()
? B) maybe the texture failed to upload, which can if your texture atlas is too big. Also see docs/FONTS.md.You are probably mishandling the clipping rectangles in your render function. Each draw command needs the triangle rendered using the clipping rectangle provided in the ImDrawCmd structure (ImDrawCmd->CllipRect
). Rectangles provided by Dear ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom)
and NOT as (x1,y1,width,height)
. Refer to rendering backends in the backends/ folder for references of how to handle the ClipRect
field. For example, the DirectX11 backend does this:
// Project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) continue; // Apply scissor/clipping rectangle const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; ctx->RSSetScissorRects(1, &r);
USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!
USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!
A primer on labels and the ID Stack...
Dear ImGui internally needs to uniquely identify UI elements. Elements that are typically not clickable (such as calls to the Text functions) don't need an ID. Interactive widgets (such as calls to Button buttons) need a unique ID.
Unique IDs are used internally to track active widgets and occasionally associate state to widgets.
Unique IDs are implicitly built from the hash of multiple elements that identify the “path” to the UI element.
Since Dear ImGui 1.85, you can use Demo>Tools>ID Stack Tool
or call ImGui::ShowIDStackToolWindow()
. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
Begin("MyWindow"); Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK") Button("Cancel"); // Label = "Cancel", ID = hash of ("MyWindow", "Cancel") End();
Begin("MyWindow"); if (TreeNode("MyTreeNode")) { Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "MyTreeNode", "OK") TreePop(); } End();
Begin("MyFirstWindow"); Button("OK"); // Label = "OK", ID = hash of ("MyFirstWindow", "OK") End(); Begin("MyOtherWindow"); Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK") End();
Begin("MyWindow"); Button("OK"); Button("OK"); // ERROR: ID collision with the first button! Interacting with either button will trigger the first one. Button(""); // ERROR: ID collision with Begin("MyWindow")! End();
Fear not! This is easy to solve and there are many ways to solve it!
Begin("MyWindow"); Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play") Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window End();
Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID") Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same ID, different label sprintf(buf, "My game (%f FPS)###MyGame", fps); Begin(buf); // Variable title, ID = hash of "MyGame"
PushID()
/ PopID()
to create scopes and manipulate the ID stack, as to avoid ID conflicts within the same window. This is the most convenient way of distinguishing ID when iterating and creating many UI elements programmatically. You can push a pointer, a string, or an integer value into the ID stack. Remember that IDs are formed from the concatenation of everything pushed into the ID stack. At each level of the stack, we store the seed used for items at this level of the ID stack.Begin("Window"); for (int i = 0; i < 100; i++) { PushID(i); // Push i to the id tack Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click") PopID(); } for (int i = 0; i < 100; i++) { MyObject* obj = Objects[i]; PushID(obj); Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click") PopID(); } for (int i = 0; i < 100; i++) { MyObject* obj = Objects[i]; PushID(obj->Name); Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click") PopID(); } End();
Button("Click"); // Label = "Click", ID = hash of (..., "Click") PushID("node"); Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") PushID(my_ptr); Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click") PopID(); PopID();
PushID()
:Button("Click"); // Label = "Click", ID = hash of (..., "Click") if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag) { Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click") TreePop(); }
When working with trees, IDs are used to preserve the open/close state of each tree node. Depending on your use cases you may want to use strings, indices, or pointers as ID.
Short explanation:
ImGui::Image()
, ImGui::ImageButton()
or lower-level ImDrawList::AddImage()
to emit draw calls that will use your own textures.#define
it to a custom type/structure if you need.Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.
Long explanation:
OpenGL: - ImTextureID should contains 'GLuint' (GL texture identifier). - See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp
DirectX9: - ImTextureID should contain a 'LPDIRECT3DTEXTURE9' (pointer). - See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp
DirectX11: - ImTextureID should contain a 'ID3D11ShaderResourceView*' (pointer) - See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
DirectX12: - ImTextureID should contain a 'D3D12_GPU_DESCRIPTOR_HANDLE' (always 64-bits) - See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp
For example, in the OpenGL example backend we store raw OpenGL texture identifier (GLuint) inside ImTextureID. Whereas in the DirectX11 example backend we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure tying together both the texture and information about its format and how to read it.
User code may do:
// Cast our texture type to ImTextureID MyTexture* texture = g_CoffeeTableTexture; ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2(texture->Width, texture->Height));
The renderer function called after ImGui::Render() will receive that same value that the user code passed:
// Cast ImTextureID stored in the draw command as our texture type MyTexture* texture = (MyTexture*)(intptr_t)pcmd->GetTexID(); MyEngineBindTexture2D(texture);
Once you understand this design, you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui. This is by design and is a good thing because it means your code has full control over your data types and how you display them. If you want to display an image file (e.g. PNG file) on the screen, please refer to documentation and tutorials for the graphics API you are using.
Refer to Image Loading and Displaying Examples on the Wiki to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11.
C/C++ tip: a u64 is 8 bytes. You may safely store any pointer or integer into it by casting your value to ImTextureID, and vice-versa. Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID. Here are some examples:
GLuint my_tex = XXX; ImTextureID my_imtexid; my_imtexid = (ImTextureID)(intptr_t)my_tex; // cast a GLuint into a ImTextureID (we don't take its address! we just copy the address) my_tex = (GLuint)(intptr_t)my_imtexid; // cast a ImTextureID into a GLuint ID3D11ShaderResourceView* my_dx11_srv = XXX; ImTextureID my_imtexid; my_imtexid = (ImTextureID)(intptr_t)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque ImTextureID my_dx11_srv = (ID3D11ShaderResourceView*)(intptr_t)_my_imtexid; // cast a ImTextureID into a ID3D11ShaderResourceView*
Finally, you may call ImGui::ShowMetricsWindow()
to explore/visualize/understand how the ImDrawList are generated.
We do not export maths operators by default in imgui.h in order to not conflict with the use of your own maths types and maths operators. As a convenience, you may use #define IMGUI_DEFINE_MATH_OPERATORS
+ #include "imgui.h"
to access our basic maths operators.
You can setup your imconfig.h file with IM_VEC2_CLASS_EXTRA
/IM_VEC4_CLASS_EXTRA
macros to add implicit type conversions to our own maths types. This way you will be able to use your own types everywhere, e.g. passing MyVector2
or glm::vec2
to ImGui functions instead of ImVec2
.
std::vector
or any other data structure: the BeginCombo()/EndCombo()
API lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter()
API. Prefer using them over the old and awkward Combo()/ListBox()
api.std::string
on applications with a large amount of UI may incur unsatisfactory performances. Modern implementations of std::string
often include small-string optimization (which is often a local buffer) but those are not configurable and not the same across implementations.ImDrawList
api to render shapes within a window.ImGui::Begin("My shapes"); ImDrawList* draw_list = ImGui::GetWindowDrawList(); // Get the current ImGui cursor position ImVec2 p = ImGui::GetCursorScreenPos(); // Draw a red circle draw_list->AddCircleFilled(ImVec2(p.x + 50, p.y + 50), 30.0f, IM_COL32(255, 0, 0, 255)); // Draw a 3 pixel thick yellow line draw_list->AddLine(ImVec2(p.x, p.y), ImVec2(p.x + 100.0f, p.y + 100.0f), IM_COL32(255, 255, 0, 255), 3.0f); // Advance the ImGui cursor to claim space in the window (otherwise the window will appear small and needs to be resized) ImGui::Dummy(ImVec2(200, 200)); ImGui::End();
ShowExampleAppCustomRendering()
in imgui_demo.cpp
from more examples.IM_COL32(255,255,255,255)
to generate them at compile time, or use ImGui::GetColorU32(IM_COL32(255,255,255,255))
or ImGui::GetColorU32(ImVec4(1.0f,1.0f,1.0f,1.0f))
to generate a color that is multiplied by the current value of style.Alpha
.IM_VEC2_CLASS_EXTRA
in imconfig.h
to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use #define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui.h"
to use our math operators, but instead prefer using your own math library and set it up in imconfig.h
.ImGui::GetBackgroundDrawList()
or ImGui::GetForegroundDrawList()
to access draw lists which will be displayed behind and over every other Dear ImGui window (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated with a Dear ImGui window.ImGuiWindowFlags_NoDecoration
flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via GetWindowDrawList()
and draw to it in any way you like.ImGui::GetDrawListSharedData()
, or create your own instancing ImDrawListSharedData
, and then call your renderer function with your own ImDrawList or ImDrawData data.The short answer is: obtain the desired DPI scale, load your fonts resized with that scale (always round down fonts size to the nearest integer), and scale your Style structure accordingly using style.ScaleAllSizes()
.
Your application may want to detect DPI change and reload the fonts and reset style between frames.
Your ui code should avoid using hardcoded constants for size and positioning. Prefer to express values as multiple of reference values such as ImGui::GetFontSize()
or ImGui::GetFrameHeight()
. So e.g. instead of seeing a hardcoded height of 500 for a given item/window, you may want to use 30*ImGui::GetFontSize()
instead.
Down the line Dear ImGui will provide a variety of standardized reference values to facilitate using this.
Applications in the examples/
folder are not DPI aware partly because they are unable to load a custom font from the file-system (may change that in the future).
The reason DPI is not auto-magically solved in stock examples is that we don't yet have a satisfying solution for the “multi-dpi” problem (using the docking
branch: when multiple viewport windows are over multiple monitors using different DPI scales). The current way to handle this on the application side is:
platform_io.Monitors[]
before NewFrame()
).platform_io.OnChangedViewport()
to detect when a Begin()
call makes a Dear ImGui window change monitor (and therefore DPI).This approach is relatively easy and functional but comes with two issues:
Begin()
without knowing on which monitor it’ll land.Begin()
call crossing monitor boundaries. You may need to do some custom scaling mumbo-jumbo if you want your OnChangedViewport()
handler to preserve style overrides.Please note that if you are not using multi-viewports with multi-monitors using different DPI scales, you can ignore that and use the simpler technique recommended at the top.
On Windows, in addition to scaling the font size (make sure to round to an integer) and using style.ScaleAllSizes()
, you will need to inform Windows that your application is DPI aware. If this is not done, Windows will scale the application window and the UI text will be blurry. Potential solutions to indicate DPI awareness on Windows are:
SDL_WINDOW_ALLOW_HIGHDPI
needs to be passed to `SDL_CreateWindow()``.ImGui_ImplWin32_EnableDpiAwareness()
helper method in the Win32 backend.<dpiAware>
property.Use the font atlas to load the TTF/OTF file you want:
ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
(Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
(Read the docs/FONTS.md file for more details about font loading.)
New programmers: remember that in C/C++ and most programming languages if you want to use a backslash \ within a string literal, you need to write it double backslash “\”:
io.Fonts->AddFontFromFileTTF("MyFolder\MyFont.ttf", size); // WRONG (you are escaping the M here!) io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size); // CORRECT (Windows only) io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT
The most convenient and practical way is to merge an icon font such as FontAwesome inside your main font. Then you can refer to icons within your strings. Read the docs/FONTS.md file for more details about icons font loading.
Use the font atlas to pack them into a single texture. Read docs/FONTS.md for more details.
When loading a font, pass custom Unicode ranges to specify the glyphs to load.
// Add default Japanese ranges io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, nullptr, io.Fonts->GetGlyphRangesJapanese()); // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need) ImVector<ImWchar> ranges; ImFontGlyphRangesBuilder builder; builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters) builder.AddChar(0x7262); // Add a specific character builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 16.0f, nullptr, ranges.Data);
All your strings need to use UTF-8 encoding. You need to tell your compiler to use UTF-8, or in C++11 you can encode a string literal in UTF-8 by using the u8“hello” syntax. Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! See About UTF-8 Encoding section of FONTS.md for details about UTF-8 Encoding.
Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter()
. The applications in examples/ are doing that. Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). You may also use MultiByteToWideChar()
or ToUnicode()
to retrieve Unicode codepoints from MultiByte characters or keyboard state. Windows: if your language is relying on an Input Method Editor (IME), you can write your HWND to ImGui::GetMainViewport()->PlatformHandleRaw for the default implementation of GetPlatformIO().Platform_SetImeDataFn() to set your Microsoft IME position correctly.
You may take a look at:
Yes. People have written game editors, data browsers, debuggers, profilers, and all sorts of non-trivial tools with the library. In my experience, the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more “offline” UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library.
Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient, and powerful.
Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization than the more typical RMGUI paradigm.
Somewhat. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, and fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create a user interface for games, although with ingenious use of the low-level API you can do it.
A reasonably skinned application may look like (screenshot from #2529):
Dear ImGui takes advantage of a few C++ language features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui doesn't use any C++ header file. Dear ImGui uses a very small subset of C++11 features. In particular, function overloading and default parameters are used to make the API easier to use and code terser. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors, and templates (in the case of the ImVector<> class) are also relied on as a convenience.
There is an auto-generated c-api for Dear ImGui (cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating bindings to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see Bindings for various third-party bindings.
omar AT dearimgui.com
if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance, or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people to work on this project. Please see Funding page.