Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
About the IMGUI Paradigm (github.com/ocornut)
58 points by ibobev on Aug 23, 2024 | hide | past | favorite | 47 comments


> Nowadays I am starting to believe that the term has caused more harm than benefits, because it suggests there are two camps "IMGUI" vs "RMGUI". The reality is there is a continuum of possibilities over multiple unrelated axises.

> The fact that we are even trying to put an official definition to a label is hindering people's imagination about the many possible areas of researches to be done in UI space.

Well said, but then the author proceeds and lists what IMGUI is and what it’s not.

My opinion is that we may just think about IMGUI as “the stuff that dear-imgui does”, which people understand well. And yes there’s a loop, and things get redrawn all the time and so on.

Everything else that borrows concepts from that is IMGUI-ish. I for myself definitely use some IMGUI concept when I do js apps, but is it imgui? Definitely not. Is it imgui-ish, hell yeah.

Trying to make the term IMGUI mean “good way of doing UI” is not gonna work…


It sucks that this is what immediate mode got reduced to. If you listen to what Casey was advocating for, it was to avoid the need to synchronise state between local state and black box state. This can be applied to UI, but just as well to f.e. a physics engine, where a constraint can live as long as you keep calling doConstraint().

Unfortunately, all people seem to have gotten out of that was if(doButton(...)).


There maybe a continium in games space, but in non-game apps it's all crystal clear and sharp boundaries:

Can the app stop generating wakeup interrupts and let CPU/GPU sleep?

Yes -> this means app events (like network transfer) need to be able to generate "update" events, which means those events need to be directed somewhere, which means retained mode.

No -> this means GUI is allowed to poll non-stop and thus can check every variable 60 times per second to support immediate mode.


Immediate mode and polling are not the same thing. With Dear ImGui you own the event loop so you can draw as frequently or infrequently as you want. It is not necessary to draw 60 times per second when nothing is happening.

Dear ImGui's sample code currently does draw every frame even when nothing is happening. Omar has said that he would eventually like to change this and it's on his roadmap, but it's low priority because he is currently targeting game industry users and doesn't want to attract a lot more users in other areas that will add to his support load and dilute his focus. [1]

He also has said the same thing about accessibility and fancy theming. These features are good examples of why "the stuff that dear-imgui does" is not a good definition of immediate mode. People often assume that anything Dear Imgui doesn't do is hard or impossible for any immediate mode API, but that's far from the truth.

Omar is only one guy. He has a target audience in mind and is not trying to satisfy all use cases at once. You have to remember that when comparing Dear ImGui to a framework like Qt or SwiftUI or whatever that has hundreds if not thousands of developers contributing to it.

[1] https://github.com/ocornut/imgui/issues/7892


> The structure and function of your UI is naturally expressed in the code of the functions that draw it, instead of in ephemeral and opaque object trees that only exist in RAM after they're constructed at runtime

This is probably it (although perhaps it is not quite the best explanation, but the example in the article helps to explain it); there are many possible implementations of an idea such as this. However, depending on the program and on other stuff, it is not always best for all kind of programs and all kind of UI. (In some cases, a kind of hybrid might do.)

And, as they say about the example, there are things to criticize about it. Still, it can show an example of its use, even though it is a simple example.

I had made my own variant of IMGUI. It uses a "win_form" block, which can be nested and which supports "break", and various other commands inside of the win_form block such as "win_command", "win_numeric", "win_boolean", etc; these commands do not have to be directly but can also be inside of a "if", "for", "switch", etc. These are implemented by C99 macros. The amount of state is small, not more than twenty bytes per active form (regardless of the number of widgets), and it is stored in the stack (but there is no need to explicitly add commands to declare or allocate this state; the "win_form" macro does this automatically).

The git repository https://github.com/zzo38/superzz0 is for a program that contains this UI implementation. The file called "common.h" contains the macros and function declarations, and "window.c" contains the implementation. You can see many uses of it in "edit.c" (search for "win_form" to find many of the uses).

As they say in the article, immediate mode does not necessarily mean that the library doesn't retain data (mine retains a single pointer, which is used to restore state when leaving a nested win_form block), that it needs a GPU to render, etc.


For some reason your comment shows as having been posted 6 days ago (or 8 days ago when editing my reply) even though this thread was created only 3 hours ago. What is happening here?


Sometimes submissions that don't get traction originally get merged into a more recent one that becomes popular.

Though... `past` link doesn't show anything else, but that might be because it was merged?


I don't know. I know I wrote it many days ago and not today, but on my computer it says 8 days ago on the /threads list but on this list it says 6 days.


I love the developer experience of Dear ImGUI, even though I use it through Python wrappers that confuse things sometimes. It just slices like a sword through several layers of often-pointless abstraction and puts the control over the main loop right in your hands.

And when you need to read the source to figure something out, it's just a few files of pretty self-evident C-ish code.


It should be the go to for general purpose cross-platform application UI development (instead of Electron,) and it's unfortunate that something so good and so useful is only meant for debuggers and editors.


On the flip side, targeting developers tightens the scope quite a lot! If nothing else, it massively increases the chance your target audience can at least get by with left-to-right text and 7-bit ASCII...

Cornut recently did a 10 year retrospective of Dear ImGui: https://github.com/ocornut/imgui/issues/7892 - an interesting read for me, as a Dear ImGui library user for many years now, but worth your time I think even if you aren't a user yourself. There is a specific section about the scope of the library: https://github.com/ocornut/imgui/issues/7892#issuecomment-22...


>general purpose cross-platform application UI development

because of the immediate mode paradigm it's not really a general purpose framework. The constant redrawing is just a complete resource hog in non real-time applications. The reason other graphics frameworks retain internal state (which Imgui exactly avoids) is to only redraw components when necessary. In theory you could write yourself some sort of widget state manager on top of it but then you've just reinvented react or Qt or what have you.

It's so popular in games and real time visualization because that's one of the domains where you redraw constantly anyway.


You don't need to have a constant redraw and IMGUI libraries do keep internal state. In fact both of these are explicitly mentioned in the linked article:

> IMGUI does not mean that the library doesn't retain data.

> IMGUI does not mean it needs a continuous loop nor need to refresh continuously.


First off, Dear ImGUI is not very non-English friendly. CJK, left-right (Arabic), emoji, are all problematic. It's also got issues with accessibility. Sure it's great, for it's intended purpose, game tools. But it's not so great for a banking app.

Second, Electron is not just UI. It's networking, file access, 2d drawing API, vector graphics, video conferencing, video playback, audio playback, video capture, audio capture, USB access, image decompressing, WebGL, WebGPU, WebAssembly, and many other things in a cross platform package.

It's trivial to make an app on one OS and ship on the other OSes without actually owning those OSes or even if you do own those OSes it requires almost zero knowledge of those OSes quirks and tools to make an app. Compare that to most other native cross platform frameworks and that's rarely true. Learning XCode on Mac, GCC/make/autotools on Linux, Visual Studio on windows, etc...


Only if you don’t care about accessibility and common controls.


You might have a point about accessibility, but what common controls does Dear IMGui lack? It has just about every control I can think of.


I think fassssst means controls common across applications in how, e.g., in macOS and Windows many applications use the same controls for labels, buttons, checkboxes, radiobuttons, listboxes, editor boxes, etc with a consistent look and feel/behavior (something at especially on macOS people do appreciate).


It's not just that. The OS adds features into the native widgets. Spell checking, translation, IME support, definition lookup, reconversion (CJK). You get them all for free and the OS can add more with every version, the least being password insertion. Render your own UI and that can't happen. That's one reason why Flash died. It meant that a new platform (mobile) couldn't give the user new ways it interact where as HTML could because it was up to the browser/OS to provide the low-level widgets, not the app itself.


One of my perverse ideas for a project is to make a Dear ImGUI (the most common IMGUI library and basically what many people associate with "ImGUI") backend for Lazarus/LCL (the most non-IMGUI/Retained mode framework you can probably think with OOP -something that IMGUI aficionados seem to have a distaste for- layers thick enough to act as armor :-P).


> IMGUI does not mean it needs to refresh all-or-nothing.

The author of microui described an interesting approach to this here https://rxi.github.io/cached_software_rendering.html


On the other hand, flutter has plenty of state management options :) - https://docs.flutter.dev/data-and-backend/state-mgmt/options - it's like living in the US, you don't like how your state is managed - move to the next one!


One thing I never figured out how to do in an immediate mode system is encapsulating functionality. In a retained mode system I can have, for example, a panning view widget, which wraps another widget and allows you to pan and zoom using the mouse. How would one encapsulate such functionality with an immediate mode ui toolkit?


That sounds exactly like a scroll area. For example Dear ImGui has scrolling based on a draw list which will be clipped to the current visible area. Nothing stopping adding panning and zoom controls for this. In fact I saw mouse panning added in one of the ImColorTextEdit forks. Maybe Dear Imgui doesn't have a "zoom" feature built-in, but I don't imagine that being hard to implement. Just additional scaling and clipping to the draw list.


Can it be done outside of the library in the user code?


Click to drag yes since it's just using ImGui::SetScrollX, ImGui::SetScrollY based on mouse events. For zoom, it could be in user code if it's your own custom widgets or rendering with ImGui::GetWindowDrawList()->Add{Something}, but I don't think Dear ImGui has a super great api for zoom with the built in windows/widgets like we're talking about here. It's a limitation of this api, not the immediate mode paradigm in general (like the article argues).

For example, ImColorTextEdit renders an ImGui:Dummy() to create a dummy widget of a specified width and height which defines the scroll area, and then based on the current ImGui::GetScrollX() and ImGui::GetScrollY() it uses ImGui::GetWindowDrawList()->Add{Rectangle,Line,Text, etc} to custom render the contents inside the widget based on what should be visible at the scroll positions. Since it's custom code it would be easy to use a zoom param to adjust the scale of things and what is submitted to the draw list.


> "Minimize state synchronization."

> void UpdateUI()

Minimize state synchronization by effectively synchronizing state on each screen refresh?

> "Minimize state storage on user side."

> Immediate mode is a style of API where important state is kept in user code

Then reduce state stored in user code by storing "important state" in user code?

> "Minimize setup and maintenance."

I don't find the example convincing. It seems like any more complexity beyond this toy example puts you right back where you started. Building components by hand is stone age ideology regardless of how you push state.

https://github.com/ocornut/imgui/blob/master/examples/exampl...

> "Easy to use to create dynamic UI which are the reflection of a dynamic data set."

Which is great for a video game.


Try it! Worst thing that'll happen is that you'll still hate it.


Somewhat of a nitpick..

> The acronym is misleading because "immediate-mode" was initially coined as a reference to obsolete graphics API which made it very easy to render contents.

Is that actually true? From what I remember of hearing Casey (the person who coined the term) talk about it on Handmade Hero and various other streams, it's differentiating between 'immediate mode' and 'retained mode' GUI APIs (QT, GTK, Swing, MFC .. etc) which make you retain handles to UI elements. AFAIK it didn't have anything to do with the graphics API whatsoever ..? Right?

EDIT: Watched the video linked of Casey from 05, which I'd never seen before and was quite interesting. I'm not totally convinced that the small portion he talked about renderer APIs near the 10 minute mark substantiates the claim, but it might.


Yes, it's true.

Direct3D had a retained mode up until version 3.0, but the only examples of it ever being used in a commercially successful game was LEGO Island and LEGO Rock Raiders.

Instead of supplying all the draw commands every frame, you would give it your 3D scene and it would draw it.


I tried to use it (for fun) at some point but the API design felt too verbose/cumbersome for what it did and by the time DrawPrimitive was added in D3D5 it was simpler to use that directly than use D3DRM.

It was also very clear that D3DRM was designed by a different team than D3DIM.


All modern graphics APIs are retained mode, because you push data to the GPU and the GPU maintains its own state. The closest you can get to immediate mode is OpenGL 1.0 with glBegin, etc.


https://learn.microsoft.com/en-us/windows/win32/learnwin32/r...

I think you could also draw some analogies between server side and client side rendering. Where the authoritative view state lives is the most important bit I think.


I hate writing GUI's, I cannot get them to "click" with me, but for some reason the immediate mode GUI paradigm makes a lot more sense to me. It doesn't help that UI code is usually really blocky and error prone either, but IMGUI and GIO are great


Working with GUIs really "clicked" with me when I learned the Elm programming language and framework for building web applications (front-end) [1]. The Model-View-Update paradigm matches very well the UML state machine modelling taught in universities [2].

[1] https://guide.elm-lang.org/architecture/ [2] https://en.wikipedia.org/wiki/UML_state_machine


Say I have a very long listbox containing thousands of items, and each item has a height that may be different (e.g. a list of font families where each line may have a slightly different line height).

How would IMGUI perform the drawing, given the scrollbar is at (say) 20%?


I'm not sure I've ever used any library that goes to any particular effort to support this sort of thing. The standard assumption for listboxes is that every row has the same height. So you'd probably handle it the same way you would with any other system: accept that there'll be some effort involved, and get the library to do the remainder for you. So, probably, something like let the library know the total height of the contents, have it look after the viewport height and scroll bar position for you, and then draw the viewport contents as required.


Your browser goes through extraordinary lengths to support this sort of thing.


I guess I just got old at some point. I simply don't think of web browsers as relevant when it comes to programming.


> and each item has a height that may be different

This criterion means you'd have to roll your own solution. Otherwise, ImGuiListClipper exists for exactly this kind of thing.

https://github.com/ocornut/imgui/blob/864a2bf6b824f9c1329d84...


I'm not a fan of IMGUI, but there is nothing about it that prevents caching data (in fact AFAIK most IMGUI libraries do cache data), so it'd be done pretty much the same way as in a regular GUI library: by caching the (unscrolled) item rects, updating the rect cache whenever the listbox size changes, caching the visible (after scrolling) items and updating the cache whenever the listbox size or scroll position change. Might have forgotten some other case, but the idea is the same.


But caching means that you're storing information about the items, which brings you closer to RMGUI.


I feel like I must be missing something here. Why not store the ID of the top-most visible list item, and just render the next n until you run out of box height? Surely you're not trying to draw thousands of items that aren't even visible on screen?


Basically, it is how we did graphics programming back in MS-DOS, UNIX framebuffers, and everywhere else where desktop OSes didn't had a GUI framework to start with.


Are there GUI builders like for VB6, but for IMGUI libraries?


Posted last week: ImRAD is a GUI builder for the ImGui library

https://news.ycombinator.com/item?id=41261426


> they are different interpretation of what IMGUI means?

Yes. Good luck clearing that up. The programming community as a whole couldn't even get Object Oriented Programming right. It originally meant little machines passing messages to each other (Smalltalk, Objective-C). What we got was inheritance, encapsulation, and polymorphism (Java).


> It originally meant

"Smalltalk encourages well-factored designs through inheritance. Every class inherits behavior from its superclass … all forms of ordered collections in the system will instantly acquire this new capability through inheritance."

"Modularity: No component in a complex system should depend on the internal details of any other component."

"Polymorphism: A program should specify only the behavior of objects, not their representation."

1981 "Design Principles Behind Smalltalk" Daniel H. H. Ingalls

https://www.cs.virginia.edu/~evans/cs655/readings/smalltalk....




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: