flohofwoe 9 days ago

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.

  • osullivj 8 days ago

    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.

  • itronitron 9 days ago

    If you are familiar with other native windowing toolkits (such as Motif, Qt, Swing) can you elaborate on how Dear ImGui takes a different approach?

    • joeld42 9 days ago

      ImGui doesn't have "components" like a traditional toolkit. If you want a custom component you just make a regular function like:

      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.

db48x 9 days ago

That is very nice. Almost wish I had a use for it.

valine 9 days ago

How did you create the rotated labels? That's been a major pain point for me using ImGui, I wish there was native support for that.

  • ocornut 9 days ago

    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.

ilrwbwrkhv 9 days ago

Beautiful. Need a port of this for the rust equivalent: eGui. Maybe I'll get on it one of these days.

pro14 9 days ago

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?

  • valine 9 days ago

    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.

  • flohofwoe 9 days ago

    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.

  • pdpi 9 days ago

    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.

jhx2000 9 days ago

Wonderful! But I see the picture you included in the README. It looks a little weird when zoomed in; the coordinates don't zoom together.

mike_kamau 9 days ago

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;
  • nemetroid 9 days ago

    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.

  • flohofwoe 9 days ago

    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:

         glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
         glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
         glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
         glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
    
    I'll see if I can create a pull-request...

    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

forrestthewoods 9 days ago

DearImGui and ImPlot are so good. This is a delightful addition to the family.

I’ve been having to look at some react code lately. My god how I wish I were writing DearImGui code instead.

  • TheMagicHorsey 9 days ago

    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.

  • amelius 9 days ago

    Does it have a good rich text editor?

    • flohofwoe 9 days ago

      I use this in a project, but it's more like a source code editor:

      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).

      • amelius 9 days ago

        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.

        • flohofwoe 9 days ago

          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:

          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.

          • spookie 9 days ago

            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.

            • flohofwoe 9 days ago

              I have some experience with both :)

              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).

              • jayshua 9 days ago

                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.

                • flohofwoe 9 days ago

                  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:

                      static mu_Container window;
                      if (mu_begin_window(ctx, &window, "Style Editor")) { ... }
                  
                  ...in microui 2.x it's no longer necessary to store the window state on the user side:

                      if (mu_begin_window(ctx, "Style Editor", mu_rect(350, 250, 300, 240))) { ... }
        • spookie 9 days ago

          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.

Fraterkes 9 days ago

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.

  • diggan 9 days ago

    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.

    • Fraterkes 9 days ago

      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.

      • diggan 9 days ago

        > 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.

        • flohofwoe 9 days ago

          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.

          https://accesskit.dev/how-it-works/

        • spookie 9 days ago

          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.)

        • jcelerier 9 days ago

          > You can build pretty fast applications with it, if you know what you're doing.

          have yet to see one. (no, vscode is definitely not remotely in the "performant" ballpark)

laurentlb 9 days ago

Interesting!

Consider adding screenshots to the readme.

  • genezeta 9 days ago

    There are 6 animated gifs already at the very beginning of the readme.

    In case you don't see them: https://imgur.com/a/ZYW0BsP

    • buccal 9 days ago

      Total size of GIFs in that page is 46.7 MB. GitHub allows for real video upload which could be compressed much more efficiently: https://github.blog/news-insights/product-news/video-uploads...

      • genezeta 9 days ago

        Yes, it's really not ideal. But I'm seeing around half of that size (~23MB instead of 46).

        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.

    • vultour 9 days ago

      Strange, those also didn't show up on the first page load, but when I opened it up again after reading your comment they were there.