Hacker News new | past | comments | ask | show | jobs | submit login
Nuklear – A single-header ANSI C immediate mode cross-platform GUI library (github.com/immediate-mode-ui)
326 points by andsoitis on Dec 23, 2022 | hide | past | favorite | 100 comments



Here's a simple WASM version of the Nuklear standard demo:

https://floooh.github.io/sokol-html5/nuklear-sapp.html

The big difference to Dear ImGui is that Nuklear has a C API and is also implemented in C - and apparently it has more skinning/themeing options, which I haven't tinkered with yet.

TBH, for tools I prefer cimgui (a C wrapper around Dear ImGui), my impression is that Nuklear has a 'purer' immediate-mode design at the cost of some convenience, while Dear ImGui has a more pragmatic design approach, but also has less friction for writing UI code. I haven't needed skinning options so far though, that might be the actual USP of Nuklear.

It all might also just be personal bias, because I used Dear ImGui before Nuklear :)

For shits'n'giggles, here's both UI systems in the same application:

https://floooh.github.io/sokol-html5/nuklear-sapp-ui.html

(the menu bar and all windows that open from it is Dear ImGui, the rest is Nuklear).


> https://floooh.github.io/sokol-html5/nuklear-sapp-ui.html

The check-box being an empty square when it's checked, and a filled square when it's unchecked is an unpopular design decision.


You're right, it looked completely bogus to me with things seeming to do the opposite of what I configured, until I read your message! The problem with UIs is that people can't refrain from distinguishing themselves by doing something different from what seems intuitive to most, just because they can. And that results in the current web and interfaces...


Not just unpopular, it seems totally misleading and plain wrong to me. I've also seen elsewhere something similar, like checkboxes used instead of checkmarks as output widgets on web pages; cannot recall where though.


I think some of this stems from their use in dark patterns, such as opt-opt checkboxes that end up opting you in.

Then copy and paste took over.


I had something like this happen w some documentation I was working on in docbook (~13 years ago - forgive me if this isn’t 100% accurate), iirc: “[*]” meant “empty checkbox”.


This must be a mistake in the demo. Because all other UI elements behave exactly as you expect them.


I can’t remember the name for it, but there is a certain kind of switch design that’s meant to be visually ‘on’ when you’re turning something off.

The best example and how I learnt about this is the mute toggle on iPhones and the lock toggle on the old iPods.

When you turned the switch ‘on’ it turned the sound/buttons ‘off’. The signify this special kind of ‘inverted’ switch, they put the orange colour on there. [1]

This is a rare use case but it does exist. And definitely shouldn’t be the default in the UI library

[1] https://d3nevzfk7ii3be.cloudfront.net/igi/mmIJOyYlvjSvCBrH.m...


Another advantage of Nuklear is that it has a pure software renderer back end that comes with it. If you're developing on a system where you don't have OpenGL or any of the other myriad of software/hardware renderers, nuklear is pretty handy. It makes it easy to write your own driver for custom/embedded systems.


Pretty cool that works in a browser on a canvas. Might I consider it to build something like a simplified photopea or powerpoint? However it requires webgl and writing in C translated to wasm? Looks like webgl is well supported, do many folks have it disabled?

Not sure about that, maybe javascript with svg would be easier to write such an app in.


DearIMGUI has both an unofficial C wrapper and a new official C binding generator. I have personally used the CIMGUI wrapper with C99 apps using the Direct3D11 backend and it works great. The new API is started by the DearIMGUI creator but is still adding features that are available in CIMGUI.

Unofficial C API - https://github.com/cimgui/cimgui Official binding gen - https://github.com/dearimgui/dear_bindings


Then someone put Sokol and IMGUI together into a single .h + .cpp combo and you get https://github.com/pplux/imgui-app


Dear ImGui certainly seems more popular wherever skinning isn’t a priority (though I’ve seen games use it even for user facing UI). It’s become a bit of a Wilhelm scream, love spotting it in the wild.


No, the biggest difference is one is only intended for development and debugging.

> Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user).


Nuklear is great. I’ve spent countless hours hacking around with it. I’ve also built a customized version for classic Macintosh systems (down to System 2.0 or so) and built some simple Macintosh software for it. I put it on GitHub here: https://github.com/CamHenlin/nuklear-quickdraw


Now that's just awesome - I'll definitely have to play with this! What's the performance like on low-powered CPUs?


I went through great lengths to get it somewhat usable on slow CPUs. This is really where I spent the majority of my time. Check out my blog post introducing nuklear QuickDraw here https://henlin.net/2021/12/21/Introducing-Nuklear-for-Macint... where I have it running the nuklear calculator demo on an 8mhz Macintosh emulator in your web browser. The less you try to do on slow systems the better it is.



I've been using nanogui[0] to fit the bill for personal uses.

To be honest though, I'm at the point where I'd really prefer an easy and lightweight library to setup a http and/or websocket server, and just make a ui in the browser. I've got a simple use case -- I'm just making a simple scene editor & debugging ui for a toy ray tracer.

I know there are a ton of different libraries out there for the task, but that just makes it hard to evaluate the quality of any given library. I haven't given any a shot, I've only gone so far as to look at them and ponder what the size of the user base is, and question if the project will go inactive in a couple years. Or if it's going to require me to pull in some other host of dependencies.

Recommendations from HNers welcome!

[0] https://github.com/mitsuba-renderer/nanogui


Would redbean work for your purpose? It's very lightweight and fun to work with, though not suited for everything.

https://redbean.dev


Not exaclty -- it looks like it's pretty overkill for my needs

I'm looking for something more like websocketpp[0], or even just grpc without a requisite proxy. uWebsockets looks really promising, being header only, but in the fine print requires a runtime library. unfortunately, none of that ecosystem seems to use cmake, making integrating it that much more of a pain.

why use cpp for this, I'm sure some HNer will ask. the ray tracer itself is using cuda, that's why. I've also debated

- running it as a grpc server and having some proxy in a more web-accessible language

- creating python bindings and using python to make a websocket/http server for it

neither of those are out of the question, but they're not my first choices, because I'd like to keep the build & execution simple. introducing dependencies, especially other executables, is in conflict with that.

i don't need anything particularly scalable -- a threaded implementation, or one using select() would be fine, if not preferable.

[0] https://docs.websocketpp.org/

[1] https://github.com/uNetworking/uWebSockets


> To be honest though, I'm at the point where I'd really prefer an easy and lightweight library to setup a http and/or websocket server, and just make a ui in the browser.

Wouldn't that mean that the expiry date of your GUI is like: a few years or so?

Since web-stuff seems to change so constantly with breaking changes and revamps every few years being the norm.

Whereas a WIN32 app (or Unix or other) from 25 years ago probably still runs fine? I can't imagine the same for any web-app that was written for Netscape and now has to run in a modern browser.


nah, compatibility is longer than a few years. it can be practically impossible to deprecate stuff, even.

you see a lot of churn in the web ui world because browsers implement new features that new libraries take advantage of. it seems to be stabilizing a bit around react. the developers in the space do tend to reinvent the wheel more.

it's not that big of a deal to me though, because it's a pet project, not a professional product. if i want to show it off to non-technical friends/family, it's a lot easier for me to point them to a webpage than it is to have them install some binary I produce.

having a native gui isn't precluded going this route either, I'd just have a native gui connect via socket rather than interact directly.

> Whereas a WIN32 app (or Unix or other) from 25 years ago probably still runs fine? I can't imagine the same for any web-app that was written for Netscape and now has to run in a modern browser.

Sure, but then I'd have to learn all of the platform specific apis, or go with something like nuklear or nanogui (like i'm doing now). which is fine, sort of. it's not really the development I want to be doing, and it's got a frustrating workflow.

Just due to my background, having started my career in webdev, i feel more comfortable doing ui work in a browser than i do fussing with native or opengl based uis.


> you see a lot of churn in the web ui world because browsers implement new features that new libraries take advantage of

Also because of design language evolution (whether this is “fashion” or “advances in usability research” is a debate I’ll sidestep here); the old stuff still works fine, it just isn’t current style; if all you care about is “UI that works” and not “UI that looks and feels current”, web isn’t a bad target.


Related:

Nuklear: A cross-platform GUI library in C - https://news.ycombinator.com/item?id=26212787 - Feb 2021 (142 comments)

Nuklear: A single-header ANSI C GUI library - https://news.ycombinator.com/item?id=16347216 - Feb 2018 (176 comments)

Nuklear: A small ANSI C GUI toolkit - https://news.ycombinator.com/item?id=11522452 - April 2016 (92 comments)


I used Nuklear for a little demo project I put together to wrap my head around matrix transforms in graphics programming. It's very easy to use and pleasant to work with!

https://github.com/jpe90/model-view-projection


This is a simple and easy to use library. I made my first immediate mode UI with it recently: https://autoptt.com/

Of course, I forgot to add a frame limit so it ate up a full CPU core at first, but after fixing that, the usage was basically zero.


Interesting, this seems more resource efficient than even fltk, which is the lightest usable cross-platform GUI library. And it's pure C unlike fltk.

It's great to see such projects in an era of unabashed resource consumption.


The price for the 'lightest' general UI toolkit probably goes to microui:

https://github.com/rxi/microui

Just around 1100 lines of C code.

You need to bring your own renderer, but that's the same for Nuklear or Dear ImGui.

I wrote a WASM wrapper for the microui demo too:

https://floooh.github.io/sokol-html5/sgl-microui-sapp.html


I love these kinds of UI frameworks except for one thing -- the text is always so poorly rendered. Not sure if it's just poor fonts or lack of good antialiasing, but compared to how a browser or native windowing system renders text, immediate mode GUIs are practically unbearable and make me want to close them after short usage. Maybe because I use a high-DPI screen (Macbook Air), not sure, but it feels like taking a step in the wrong direction for user comfort.


I must mention that the WASM demos all render to a half resolution framebuffer when running on a high-dpi display, and the resulting aliasing and upscaling may introduce all sorts of artefacts (even as late as in the browser and window system).

I've configured the canvas upscaling to use point filtering because that looks nicer for Dear ImGui's and Nuklear's default pixel fonts (otherwise the text look slightly blurry after the upscaling), but the point filtering doesn't look exactly great for microui's default font.

Using a proper TTF font rendered in native resolution on a HighDPI display will look a lot better. But proper 'non-native' text rendering is a surprisingly tricky thing to do right.


The default fonts are just plain awful. It's trivial to drop in a better font and make it indistinguishable from native.

Possibly a licensing issue as to why they don't include better ones by default as you have to bake it in? or they want to make the binary as tiny as possible by not using a bigger font file?


Font is one thing.

The hard part is text layout which is a very very complicated affair, especially if you want to support different languages and/or writing systems.


Your comment reminded me of "Text Rendering Hates You" (https://faultlore.com/blah/text-hates-you/ and https://news.ycombinator.com/item?id=30330144 )


Yeah this. Once you get to something more than plain English, it means pulling in HarfBuzz


If you want visually pleasing results, even English needs layout processes like kerning.


:-/ must have mentioned that by 'plain' I meant monospace, С64-like


This one is 1100 lines of code, nice for embedded project.

A nice font renderer is orders of magnitude more code, e.g., harfbuzz 25,000 lines of code with or FreeType with 245,000 lines of code. Many projects do not want that kind of bloat.

I'd guess some of these little ones allows using your own bmp font, so render a font you like, and use the rendered glyphs.


>Many projects do not want that kind of bloat.

It isn't bloat if it's desired functionality. Not every project is optimized to run in an embedded environment, nor does it need to be.


Adding 250,000 lines of code to render fonts to an 1100 line functional gui library is bloat no matter how you slice it. If someone want that renderer, it's not that hard to wire it in.

And if you in particular want it, fork them and merge them.


Meh. A small C library is easier to extend than a sprawling C++ library, and it's perfectly valid to want a minimal gui that can actually import fonts. Even just building a font atlas on top of that would be useful in a lot of projects.


Your demos are really cool!

https://floooh.github.io/sokol-html5/

Interestingly the imgui and nuclear both work on mobile while the microui demo doesn't appear to handle any input. Imgui works surprisingly well (although everything is a bit small for touch).


Impressive. This is suckless-grade minimalism.


See also the FOX Toolkit, which is still just about alive.

https://www.fox-toolkit.org/


I use Nuklear for a Steam game I made in C. It worked well for my needs but there are a few things I still haven't figured out yet - like rendering centered multi-line text. Localizing my game was very straightforward with Nuklear - I didn't run into any roadblocks with fonts or different alphabets. I was able to get the interfaces to be controller-friendly too. Overall, I had a positive experience and will use it again.


Did the Steam Overlay work?


In the pathological case, the steam overlay needs zero effort to "implement". It works out of the box in most cases when the application is launched via the Steam launcher.


It only works for DirectX, OpenGL, Metal, Vulkan: https://partner.steamgames.com/doc/features/overlay

It also uses heuristics to find the right window that can lead to issues. Not a common problem, but one I unfortunately ran into :(


What other rendering backend options are there even these days?


Electron and other HTML runtimes are what I had in mind. I’m not sure what renderer they use, but it’s something else.


Yep! No issues with the Steam Overlay.


I used Nuklear quite a lot [1]. Was a pleasure to use, skinnable which is great for videogames and pretty performant.

1 - https://executionunit.itch.io/smith-and-winston


I really like this trend. Also see:

* Raylib - A single header file game engine https://www.raylib.com/ * Miniaudio - A single header file audio library https://miniaud.io/

Both (actually, not just three systems) cross-platform.

For their design and cross-platform support they make for great bases for Go libraries, unlike most C code out there.


I can't say I'm excited about this trend, if it is a trend.

Immediate mode GUIs are usually pretty nice from a developer point of view, but many of them are lacking many things like accessibility and text selection. Maybe good for 3D modelers, video editors, etc., but not for more general purpose apps.


General purpose apps are pretty bad with accessibility. I've noticed a trend with Electron based apps which neglect to proper use aria annotations until someone complains.

Harping on immediate mode GUIs doesn't help. I don't think anyone is against making IM GUIs more accessible.

The predominant immediate mode library in Go, Gio, has been slowly working on support for various ecosystems. I believe it supports Android to some extent already.


The trend I was talking about is small, well-designed simple to use, truly cross-platform header only libraries.

For accessibility I think that's sadly a part that people in general don't seem to care a lot. And while some of the big libraries do a lot for you there, it also depends a lot on how it really is used. The trend to Electron and others also isn't really helping there.

To be fair though, I am happy about the trends that this topic is actually something people even are aware of. Five, ten, fifteen years ago this was very different. I remember a time when using HTML over Flash for accessibility reasons was considered a non-argument. Now you see that topic brought up "a lot".


It really depends on where you work. In large companies, there was already a strong emphasis on accessibility 10-15 years ago, if only because there's a bunch of requirements if you want to sell software to the government.

As for small and simple libraries... it's great when the subject matter is also small and simple. UI is not, though.


Having a peep at miniaud.io, I am astounded to say the least.

It supports almost all of the popular back-ends across platforms. A library as complex as PortAudio in a (largish) header.


Yes, I found it by accident, because I dug into a Go code base I don't even use for fun, because I wondered about how they do audio, noticed it wasn't actually cross-platform. So I wondered if it's solved overall and found this, which seems to be the most straight-forward way of supporting pretty much all platforms that Go supports. Not completely sure about Plan 9 though.

https://github.com/gen2brain/malgo


I tend to use ImGui for testbed projects. It's flexible and quick to get up and running. I only have two minor complaints about it.

1. It would be nice to have some built in image handling functions, i.e. to be able to allocate and draw images on the screen.

2. Skinning is currently rather limited. (I know this has been a long requested feature).

Other than those minor gripes, I like it a lot.


> 1. It would be nice to have some built in image handling functions, i.e. to be able to allocate and draw images on the screen.

I think this would actually be fairly tricky to handle inside Dear ImGui, because the image object must be in a format that's understood by the rendering backend. The way ImGui handles image rendering via an opaque ImTextureID handle which is passed through to the renderer backend is actually quite elegant IMHO.


I can see what you mean - but I would think that an array of int32s representing RGBA would be fairly standard these days. ImGui already draws fonts using textures, if I recall.


If you're writing the ImGui backend already, don't you practically have to handle texture upload? Why not just upload the image yourself?

I've never found this to be problematic. Long before ImGui even gets involved I've already got stb.h and a spinning textured cube.


I suspect that the majority of ImGui users use one of the included, ready-to-use backends. For example, I use the OpenGL one. I work around the lack of images, handling the textures myself, but it's always struck me as an odd omission.


I suspect (1) is just because Dear ImGui is BYO graphics backend, so it doing lots of clever texture management stuff for lots of images would increase the surface area of that integration which would make it harder to use for most folks.


I would venture that 99% of people who use ImGui do not create their own graphics backend, but rather use one of the standard ones included (I use the OpenGL backend, for example). Creating a new backend would be more work, for sure - although I think that ImGui is already using textures for its font rendering - so perhaps some of that work could be reused.


This looks cool, but I don’t do a lot of GUI work. Why would one use this as opposed to Qt?


License issues aside the typical use case is that you want to integrate the UI with an existing 3D renderer (e.g. you have a 3D engine, and want an UI overlay for tooling and debugging). 'Bring your own renderer' UI frameworks like Nuklear or Dear ImGui are perfect for this use case. With 'traditional' UI frameworks like Qt, WPF, GTK... this is a massive PITA and even if it's possible would add an incredible amount of bloat.

...and then there's also the convenience of writing immediate mode UI code. Personally, I would never want to go back to event-/callback-/signal-driven UIs.


will immediate mode keep the cpu active thus not power saving friendly?


Immediate mode UIs tend to be more practical in applications where you're updating the entire screen every frame anyway. If your application is going to be mostly static anyway, a retained mode UI will probably better serve your needs, and also be easier on power.


You can pause your main loop when there is no input or animations that would require a redraw. That saves a lot of CPU when the app is idle. You need to run on mouse moves if you want hover effects though.


In addition to what others have said, they are different types of GUI systems. As an immediate mode UI, the logic behind what gets drawn to the screen in Nuklear runs every frame, and it draws/updates the entire screen every frame. A retained mode UI like QT draws elements once when they need to be updated, and they get left there until an event occurs that requires something change. So immediate mode UIs like Nuklear and Dear ImGUI, tend to be more appropriate for rendering the UI elements of games and other programs that already draw/update the screen each frame. Retained mode tends to be more useful for traditional "desktop" like applications where interacting with the standard toolkit widgets serves the primary purpose of the program. Of course there are many ways of blurring the lines and using either for both, so this isn't a hard and fast rule, just a rule of thumb.


QT is a huge dependency that you have to bundle with your app. This is tiny in comparison. Also probably easier to prototype with.


rapid development/prototyping


But it's faster to use a QList<Whatever> than having to do the same in C (repeat for all the non GUI classes that Qt brings in).


Not faster to integrate it into a build system or compile it though.


C++ is most certainly slower to compile… it's no problem to build it.

Anyway usually the consensus is that it's worth to save human time increasing compilation time. Otherwise nobody would use Rust instead of C


Nice UI - Please take also a look at Geeonx cross-platform C GUI library for Windows and Linux with GUI designer https://www.geeonx.de


Does anyone know of something similarly lightweight but retained mode?


You can check out LVGL: https://github.com/lvgl/lvgl/

It's geared more for embedded, but you can use an sdl back end for desktop (which might kill your light weight requirement depending on your strictness level). I wrote my own tty/framebuffer driver for it and use it directly on the frame buffer (not Linux) but it's pretty nice to work with. But if you need metal/openGL/Vulcan/directX and hardware acceleration, it's probably not what you're after.


lvgl uses SDL2 could get access to 2D acceleration I think.


Thank you!


Does this support writing to a linear frame buffer? Would be interesting to port to run on my OS if so.


It does. I've done it, starting with their x11_rawfb demo. It's pretty nice, but I've personally switched to using LVGL (https://github.com/lvgl/lvgl) for the OS I work on, as I find it a better fit for the purpose. I do still have a soft spot for Nuklear though, and depending on what you're trying to do with your OS, could also be a good fit. Really not hard to get it going if you don't mind implementing your own keyboard/mouse driver layer.


Nuklear returns a bunch of vertices, vertex-indices and draw commands, so it plugs best into a 3D API (like GL, D3D, Metal, Vulkan...). To render into a frame buffer you'd need to implement a simple software rasterizer with texturing support.


One of their demos already has a software rasterizer. I've used it to draw directly to a frame buffer for a custom OS that didn't support accelerated graphics. It's in the demo directory under x11_rawfb. I made some tweaks to that (getting rid of all X11 stuff) and wrote my own fb/tty/mouse/keyboard driver and got it working great without any graphics API layer between it and the pixels that get drawn directly to video memory and the screen.


I have backend for the Hisilicon SoC from 2016, its about 1500 lines of C code, few calls to 2D API and copypasta of the triangle rasterizer. Dunno about modern version requirements.


Sounds like the answer to just about everybody's areweuiyet? Question


Can you use python or ruby with something like this, or only C?



Why didn't they write it in Rust? Rust really needs a good GUI library to take off.

I'm hoping the wxWidgets creators will rewrite their library in Rust or at the very least create bindings for it.


For people that have used both Nuklear and ImGui, how do they compare? Which would you choose for your next project and why?


I've tried Nuklear and it was very difficult to get things to lay out correctly or at all. Even after reading the source, I didn't get how it was supposed to work. IMGUI works really well and is direct and simple, it's an easy choice in my opinion.


It's like egui, but in C instead of Rust.


> * Written in C89 (ANSI C)

Just why. C17 exist.

Why is is that some developers stick with C89, whilst in the C++ community, unless you work for some really backwards company, you adopt the latest standard before it's even officially nailed down?

C89 needs to die. Stop supporting it.


Probably for portability reasons.


They are awaiting your pull request. Have at.


This is something you want to check not assume or you can end up wasting a lot of time just to annoy the maintainers:

> Reviewing changes to src/* and nuklear.h:

> Ensure C89 compatibility


Good point! I misspoke:

Feel free to fork at your convenience!

Would have been more accurate.


Ping me when it can WebKit

EDIT: this was flippant of me, but I was trying to make a real point.

I'm simply too used, as a front-end dev, to the flexibility I get from CSS and HTML and SVG and React, and React-Three-Fibre for fancy stuff. Put it in Electron and boom.

Yes, it's a horrible, horrible mess. Yes, it's ungainly. Yes, it's twenty layers of abstraction.

But Electron apps have come an enormous way. My favourite apps are now all Electron. While non-Electron apps make a strong start, they simply cannot keep up with the innovation made possible by here-you-go-ing the last 30 years of web progress.

Yeah, I know that's not the use case for something like this. Opposite! Opposite! But you know what? For most medium-sized 2022 front-end workloads, widgeting is a thoroughly solved problem.

By 2030, most apps will include an entire web browser, just as insurance for future market-competitive growth rate.

This is why adopting MAUI, Blazor, etc, is folly, and even this kit -- aside from it obvious hacker-cool minimalist street cred -- is the sort of 'meme dependency' (rhymes with meme stock) that HN adores despite the fact that it will see almost no non-toy use cases.

Get yourself a web browser. HTML is the VT220 of 2030.




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

Search: