1. 12
  1. 5

    This is just a list of all the UI libraries in the world, and from the commentary I don’t think the author has actually used most of them.

    I’ve tried several UI libraries over the last few years in the context of a small gamedev team trying to find something that’s acceptable to the devs/artists/users. If you don’t mind your app looking like a free dev tool you have exactly one option: ImGui is infinitely better than everything else. You don’t have to buy in to a gigantic framework, you just write normal C++ and a functional UI comes out the other end 10 mins later. The docs are “ok” but it ends up being way easier than everything else anyway. From a user’s perspective ImGui apps are pleasant to use, they can actually hit your monitor’s refresh rate, and run anywhere. You can try to wrangle it into something that looks nice, especially for non-interactive parts of the UI, but it’s very time consuming and ends up being write-only code, and your artists will hate you for it.

    If you need it to actually look good then it gets more complicated, every option I’ve tried came with significant downsides:

    • Qt: you have to buy in to a gigantic framework which comes with all the usual gigantic framework downsides, notably people will actively avoid learning it because they don’t want to pigeonhole themselves into being Qt devs
    • Noesis: it seemed ok but our artists couldn’t get motivated to learn XAML/Blend
    • Ultralight: it’s supposed to be WebKit but a lot of stuff doesn’t work and our artists got annoyed. Web UI frameworks don’t seem to translate super well to game UIs. You have to go with janky frameworks (preact + htm) unless you want to waste enormous amounts of time setting up and maintaining a javascript build pipeline. Perf is very sus, which is not acceptable when you can buy a 280Hz monitor for $300

    For now we’re trying to make a DIY “react native” on top of Yoga. It’s very much a WIP but so far it seems totally good enough for non-interactive parts of the GUI, and we’re hoping ImGui widgets with real layout will be good enough for the menus. The integration has been surprisingly little work so far, considering we also had to add a scripting language (Luau) and inspector (ImGui!), but we did already have the rendering primitives in place to make it usable.

    1. 1

      How’s the a11y situation for your Yoga + ImGui solution? My understanding is that ImGui’s a11y is a bit behind when it comes to supporting asstive technology APIs.

      1. 1

        How’s the a11y situation

        There isn’t one :)

    2. 5

      I’ve been playing with Dear ImGui recently. The documentation is terrible and probably should be listed in the ‘cons’, but the good news is that the abstractions are so simple that it doesn’t really need them. I’ve been using the ImTui back end, which renders with ncurses. There’s also one for rendering via WebSocket to a browser, along with many others for displaying in a more conventional GUI. I’d probably list a couple of other cons:

      • No accessibility features (yet - I think it’s planned)
      • No native look and feel (it’s mostly used in games, where this doesn’t matter)
      • Still a fairly young / small project, so lacks things like rich text layout APIs that you’d find in a more mature project.

      The docs spend so much time telling you what an immediate mode GUI isn’t that they forget to tell you what it is. Coming from OpenStep, I expected to hate it and I’ve been really surprised at how much I’ve enjoyed programming with it. The idea behind an immediate-mode GUI is that you treat the GUI as stateless. Each frame, you call a function for each control, which creates the control if it doesn’t exist and tells you if the user interacted with it. The framework is free to cache things between frames (and probably needs to for performance) but this means that memory management is trivial. In the framework, there’s a map from control identifiers to controls, at the end of the frame any controls that weren’t referenced can be deleted. Outside of the framework, there are no references to controls held by your code and no references to your code held by the framework.

      Rather than building a hierarchy of objects that represent controls, you execute code that builds the controls each frame. If you want a new window, you call a begin-window function, then a load of other functions that build controls in that window, and then end-window. Similarly, if you want any other kind of container view, you call a start function, then call functions to create things inside the list, then an end function. All of the functions that define containers (windows, tabs, combo boxes, and so on) return true if the thing is visible, false otherwise. This means that you can skip all of the code that displays things that aren’t visible.

      If you want two different controls to bind to the same data, read from the data source when you instantiate them. If the user interacts with either control, you will be notified (by the return value) when you create the control for the next frame and so you can update the data source then and it will be propagated to any controls drawn later in the frame and into all controls in the next frame.

      All of this completely eliminates most of the complexity of MVC frameworks. You write functions that take on the complete roll of a controller, with a very narrow interface to the views. Each frame they (logically) create the view and write back to the model if anything has changed. If you call a view function to create a control then any notification of state changed (button pressed, slider moved, text entered in text field, and so on) will be provided either by the return value or by a callback that’s invoked on the top of the stack, so your state management is trivial.

      The immediacy of the feedback means that you don’t need to track any state. The shape of your GUI directly reflects the shape of the code and any bit of your model that you’re reading to display is the same bit that you’d update for changes from the UI. If you want to display a load of items in a tree / outline view, then you’ll probably have a recursive function call for each layer in the tree and then a loop inside it for displaying each item at a given level. If you put buttons there and the user clicks one then the function that creates the button will return true and you can handle at at the point where you’re already traversing that bit of your data structure.

      1. 5

        Big fan of immediate mode GUIs and contributor to Nuklear.

        No accessibility features

        One of the big hurdles of most non-native GUI toolkits, not just the IMGui variants. Doing this properly can be done, but ohh dear is it a big chunk of work. Not exactly accessibility per se, but smaller steps like improving the multi language input was the missing piece in my use-case. As long as you stick to a use-case where being accessible isn’t required (Embedded, machine touchscreens), intermediate mode GUIs are a god send. PS: Mainstream screenreaders for the visually impared have an OCR fallback, though this is no excuse of course.

        Still a fairly young / small project

        Even with all the crazy industry support Dear IMGui pulled in, this will always be the case. It’s a fairly niche style to program. When I tell seniors “this paradigm mixes code on GUI definitions in a very pleasant way” they take out a crucifix and try to repell the sinful idea of mixing code like I’m the devil himself. MVC is the standard I learned in uni and will never leave bigger team sizes, I think.

        All of this completely eliminates most of the complexity

        When doing very complex layouts, IMGui can backfire hard. Straight shotgun to the foot, as you start to re-implement all that state and abstractions you got rid of in the first place. But for anything with a more straight forward purpose, simpler design, the IMGui style is unparalleled in simplicty and comfort. Niche, but when it fits, it’s glorious.

        1. 1

          Big fan of immediate mode GUIs and contributor to Nuklear.

          I had a brief look at Nuklear but when it said that it used ANSI C89 I ran away.

          MVC is the standard I learned in uni and will never leave bigger team sizes, I think.

          That’s definitely true now, although model-view-update is increasingly fashionable and I think immediate-mode GUIs fit that model very cleanly.

          When doing very complex layouts, IMGui can backfire hard. Straight shotgun to the foot, as you start to re-implement all that state and abstractions you got rid of in the first place. But for anything with a more straight forward purpose, simpler design, the IMGui style is unparalleled in simplicty and comfort. Niche, but when it fits, it’s glorious.

          I haven’t reached that point yet, but creating a tree view containing a row of different views that all update the part of the data structure that they’re expanding is an order of magnitude less code than it is with Cocoa / GNUstep. My normal litmus test for a GUI toolkit is whether it can smoothly scroll a table view with ten million rows. I haven’t tried that with Dear ImGUI yet. I presume that I’d need to draw the visible rows myself, which is fairly easy if it can tell me which ones need to be visible. GNUstep does a bit of caching here, rendering more rows and clipping. I believe Cocoa now renders a larger range to a texture and just composites it in the right place.

          1. 1

            ANSI C89

            You may use it from any C or C++ standard. The C89 thing was originally done by vurtun back in the day to ensure compatibility with even the most obscure embedded compiler. Since most of the work was done, the C89 thing was kept going to keep that quite unique part of this project. Some of the C stuff to make it happen are quite interesting and were mentioned in C related articles from time to time.

            model-view-update

            Ohh, didn’t know such a thing existed. Gonna read up on it, thanks!

        2. 2

          is there a layout engine that computes (and re-computes) relative positions on controls when screen window gets resized?

        3. 2

          It is obvious that the world needs just another GUI toolkit :-)

          Stories with similar links:

          1. C++ UI Libraries via calvin 3 years ago | 10 points | 12 comments