It is actually quite amazing how well the idea of reusable components works for Dear ImGui which doesn't have any obvious 'extension points' for components built into the API. Instead components are just regular functions which compose higher level UI widgets from builtin widgets and maybe dropping down into the ImDrawList renderer (which is also used by the builtin widgets to draw themselves).
And just like integrating Dear ImGui itself, integrating a component is just dropping a couple of source files into your project.
Yes, no extension points as you would have in a template style framework which executes canned imperative functionality around blocks of app code in a pre determined manner. ImGui is compositional, and you can compose render funcs in any order you like. Though the programming style appears imperative, the ImGui model is deeply functional, though implicitly so. IMHO Forth style threaded imperative models capture the implicitly functional model well.
And it gets the current rectangle from a global context, can allocate some of that rectangle space for itself, draw things, react to events, etc. It's more complicated when the widget needs to store state, but ImGui has pretty well established conventions for how to do that, which basically boils down to hashing the widget name or ID and storing your state there. And when you try, you find you need a lot less state than you might expect. Of course if you have custom data that already has state (e.g. an object passed into your widget), you can use and modify that directly which is great.
It's a very different way of thinking, and it does have some challenges but it usually ends up being a lot simpler and more robust than a "retained mode" gui.
You can manually transform vertices (call ImGui::ShadeVertsTransformPos) this is what angled headers are using https://github.com/ocornut/imgui/issues/6917
I agree it's not first-class citizen yet, next year new text API should make this easier.
I was working on an app using ImGui. Eventually, I noticed that my MacBook battery was draining whenever my app was running. Is this because immediate mode GUI rendering is inefficient?
You probably had your render loop set to poll rather than wait for events. If you don't configure wait events you'd be re-rendering your UI as fast as your monitor refreshes.
When you click the battery icon in the macOS menu bar you can see which apps are using significant energy, and in the 'Activity Monitor' tool you can also sort by energy usage.
I would be surprised if a typical ImGui app shows up there though (unless your renderer isn't vsync-throttled), on my laptop it's usually Chrome which is at the top of the list.
You can also write ImGui applications so that they only 'wake up' on user input.
Immediate mode here is relevant in terms of the api style, not the rendering strategy. From the README:
> A common misunderstanding is to mistake immediate mode GUI for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the GUI functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely.
I have tried running the example in the examples folder, but it fails to compile.
Seeing the errors:
/opensource/implot3d/implot3d.cpp:2650:20: error: no member named 'sin' in namespace 'std'
2650 | float s = std::sin(half_angle);
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2654:14: error: no member named 'cos' in namespace 'std'
2654 | w = std::cos(half_angle);
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2670:14: error: no member named 'fabs' in namespace 'std'
2670 | if (std::fabs(normalized_dot - 1.0f) < epsilon) {
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2680:14: error: no member named 'fabs' in namespace 'std'
2680 | if (std::fabs(normalized_dot + 1.0f) < epsilon) {
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2682:45: error: no member named 'fabs' in namespace 'std'
2682 | ImPlot3DPoint arbitrary_axis = std::fabs(v0.x) > std::fabs(v0.z) ? ImPlot3DPoint(-v0.y, v0.x, 0.0f)
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2682:63: error: no member named 'fabs' in namespace 'std'
2682 | ImPlot3DPoint arbitrary_axis = std::fabs(v0.x) > std::fabs(v0.z) ? ImPlot3DPoint(-v0.y, v0.x, 0.0f)
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2695:24: error: no member named 'acos' in namespace 'std'
2695 | float angle = std::acos(normalized_dot);
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2697:20: error: no member named 'sin' in namespace 'std'
2697 | float s = std::sin(half_angle);
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2701:16: error: no member named 'cos' in namespace 'std'
2701 | q.w = std::cos(half_angle);
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2707:17: error: no member named 'sqrt' in namespace 'std'
2707 | return std::sqrt(x * x + y * y + z * z + w * w);
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2786:26: error: no member named 'acos' in namespace 'std'
2786 | float theta_0 = std::acos(dot); // Angle between input quaternions
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2788:28: error: no member named 'sin' in namespace 'std'
2788 | float sin_theta = std::sin(theta); // Sine of interpolated angle
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2789:30: error: no member named 'sin' in namespace 'std'
2789 | float sin_theta_0 = std::sin(theta_0); // Sine of original angle
| ~~~~~^
/opensource/implot3d/implot3d.cpp:2791:21: error: no member named 'cos' in namespace 'std'
2791 | float s1 = std::cos(theta) - dot * sin_theta / sin_theta_0;
The linked code is including math.h (transitively), but using the std-namespaced functions provided by cmath. That seems like a bug, but presumably works on at least one platform.
The code doesn't seem to be tested on macOS. To make the example build I had to add an "#include <cmath>" at the top of both implot3d.cpp and implot3d_demo.cpp, this produces an executable which then fails with:
GLFW Error 65543: NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above
...which is fixed by changing the GLFW window hints like this:
I agree with you so much. There's many advantages to declarative and reactive GUI frameworks, but, god, they have so much "magic" going on at all times. Its hard to understand how the declarations get converted to pixels on the screen unless you spend a month digging through blog posts and source code to try and follow the trail of breadcrumbs.
'Rich' text editing might hit limitations with Dear ImGui's text rendering (e.g. not sure if things like italics, bold or strikethrough are supported out of the box).
Ok, rich text is always a good litmus test for a gui library. I get from this that ImGui is unfortunately not based on a good, versatile graphics engine.
Dear ImGui doesn't have a "graphics engine", the actual rendering is done by user-provided code which maps vertex- and index-arrays, and draw commands to system 3D APIs like D3D, Vulkan, Metal, GL etc...
Font handling is based on stb_truetype.h, but can be replaced with FreeType:
In any case, versatile text rendering is certainly not the design focus of Dear ImGui (AFAIK there's also no support for RTL layout), instead it is mainly targeted at quickly creating specialized UI tools (especially inhouse tooling for game development), less at creating end-user applications.
There's plenty of UI frameworks to create "end-user applications", but hardly any that fill the specific niche served by Dear ImGui.
There is microui if you want another one. Much more barebones as the name implies, but very easy to extend! Pleasant even if a bit quirky. Also nuklear, but haven't really gone much in depth with it.
Could you expand a bit on 'immediate mode design purity'? I've done immediate mode stuff from scratch and my experience had been "just write whatever code you need to get it to work," there hasn't really been an overall architecture guiding it. Never worked with an im library before.
Looking at the Nuklear example code again it turns out that I was remembering wrong. I seemed to remember that Nuklear requires to store persistent state on the API user side and pass that into the Nuklear functions, but this was actually microui 1.x (which also has been fixed in the meantime in microui 2.x).
Sorry about the confusion.
E.g. in microui 1.x defining a window worked like this:
The focus for this library is something else entirely which doesn't seem to align with your needs. Nevertheless, you are supposed to make the engine yourself, imgui is made to be bolted on top of that. And does a great a job.
Does anyone have examples of something made with ImGui that has good looking text and antialiasing? It seems like a really cool tool, but everything made with it seems to have a characteristic "crunchy" look.
Dear ImGui defaults to "ProggyClean rendered at size 13" for everything. It is somewhat crunchy indeed, but a lot of people don't mind and don't bother changing.
Still, you can look through the gallery of software using ImGui [0] or in the "screenshot threads" [1] for many examples which do have nicer fonts and text rendering.
There probably is, but keep in mind ImGui is geared towards tooling/visualization and not end-user UIs. The feature set matches this expectation since it's missing antialiasing, accessibility and more.
Ah good point, I guess my hope was that it could be a viable option for general GUI work, since everyone seems to find it really pleasant to use, and Id expect it to be easier to add accesibility features to imgui than to make eg Electron more performant.
> and Id expect it to be easier to add accesibility features to imgui than to make eg Electron more performant.
I wouldn't be so sure about that. Accessibility is difficult and very large, and would probably need major changes. Besides, I don't think Electron by itself cannot be performant. You can build pretty fast applications with it, if you know what you're doing. Most Electron developers don't focus on performance/resource usage though, but be able to ship fast. That's one of the major reasons web people chose Electron in the first place.
There's now 'accesskit' which seems to be targeted specifically at providing a cross-platform accessibility interface for custom UI frameworks (including immediate mode frameworks). It's written in Rust, but it has an optional C API. The most realistic option for Dear ImGui is probably to expose an "accessibility cmdlist" similar to how it exposes a "render cmdlist", and Dear ImGui user code can map this "accessibility cmdlist" to the tree structure AccessKit expects as input.
There are libraries that communicate with screen readers of every platform. Of course, you need to think where the text comes from and all so it scales with your app, but it really is a non issue in the end.
(edit: focusing in text having "meaning" and being spoken here. As it is very often I see this question about immediate mode GUIs. Of course there are other things about accessibility, but they're more of a design question rather than technology.)
And just like integrating Dear ImGui itself, integrating a component is just dropping a couple of source files into your project.
MyCustomThing::MyWidget( "name", whatever_value );
And it gets the current rectangle from a global context, can allocate some of that rectangle space for itself, draw things, react to events, etc. It's more complicated when the widget needs to store state, but ImGui has pretty well established conventions for how to do that, which basically boils down to hashing the widget name or ID and storing your state there. And when you try, you find you need a lot less state than you might expect. Of course if you have custom data that already has state (e.g. an object passed into your widget), you can use and modify that directly which is great.
It's a very different way of thinking, and it does have some challenges but it usually ends up being a lot simpler and more robust than a "retained mode" gui.
I would be surprised if a typical ImGui app shows up there though (unless your renderer isn't vsync-throttled), on my laptop it's usually Chrome which is at the top of the list.
You can also write ImGui applications so that they only 'wake up' on user input.
> A common misunderstanding is to mistake immediate mode GUI for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the GUI functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely.
No.
https://www.forrestthewoods.com/blog/proving-immediate-mode-...
Edit: https://github.com/brenocq/implot3d/pull/7
PS: it looks like the code was tested only on Linux, since the Windows build seems to suffer from the same `std::` prefix problem: https://github.com/floooh/implot3d/actions/runs/12393862255
I’ve been having to look at some react code lately. My god how I wish I were writing DearImGui code instead.
https://github.com/BalazsJako/ImGuiColorTextEdit
'Rich' text editing might hit limitations with Dear ImGui's text rendering (e.g. not sure if things like italics, bold or strikethrough are supported out of the box).
Font handling is based on stb_truetype.h, but can be replaced with FreeType:
https://github.com/ocornut/imgui/blob/master/misc/freetype/R...
In any case, versatile text rendering is certainly not the design focus of Dear ImGui (AFAIK there's also no support for RTL layout), instead it is mainly targeted at quickly creating specialized UI tools (especially inhouse tooling for game development), less at creating end-user applications.
There's plenty of UI frameworks to create "end-user applications", but hardly any that fill the specific niche served by Dear ImGui.
https://floooh.github.io/sokol-html5/sgl-microui-sapp.html
https://floooh.github.io/sokol-html5/nuklear-sapp.html
IMHO Nuklear goes a bit too much into the 'immediate mode design purity' direction which makes it a bit less convenient to use than Dear ImGui.
Microui is indeed a very minimal UI, but might be useful for just adding a small controller UI (similar to dat.gui in the JS world).
Sorry about the confusion.
E.g. in microui 1.x defining a window worked like this:
...in microui 2.x it's no longer necessary to store the window state on the user side:Still, you can look through the gallery of software using ImGui [0] or in the "screenshot threads" [1] for many examples which do have nicer fonts and text rendering.
[0] https://github.com/ocornut/imgui/wiki/Software-using-Dear-Im...
[1] https://github.com/ocornut/imgui/issues?q=label%3Agallery
I wouldn't be so sure about that. Accessibility is difficult and very large, and would probably need major changes. Besides, I don't think Electron by itself cannot be performant. You can build pretty fast applications with it, if you know what you're doing. Most Electron developers don't focus on performance/resource usage though, but be able to ship fast. That's one of the major reasons web people chose Electron in the first place.
https://accesskit.dev/how-it-works/
(edit: focusing in text having "meaning" and being spoken here. As it is very often I see this question about immediate mode GUIs. Of course there are other things about accessibility, but they're more of a design question rather than technology.)
have yet to see one. (no, vscode is definitely not remotely in the "performant" ballpark)
Consider adding screenshots to the readme.
In case you don't see them: https://imgur.com/a/ZYW0BsP
I've just opened an issue in case the author want to look into it. I got them to ~10MB total which is an improvement in any case.