imgui-njs
is a manual-port / partial-rewrite of
dear imgui, a
a popular GUI
framework used in games and production tooling development. dear imgui
differs from typical GUI frameworks (like Qt) in its
immediate nature. Instead of programming a GUI via a layout and separate
event-handling callbacks, the immediate-mode approach intermixes the layout,
styling and event-handling. This approach has benefits and drawbacks.
Here are some of the allures:
- it's easy to learn and get simple interfaces running quickly
- dynamic interfaces are naturally expressed. If you are building tools or experiences with lots of dynamic graphics it may be easier to do this with an immediate-mode GUI approach.
dear-imgui
targets desktop applications development and can be used to
target applications on Mac, Windows and Linux because its built atop
the portability layers of C++, libsdl-like
platforms and OpenGL-like rendering. Bindings to many other programming
languages are available. During 2018-19 dear imgui
was ported to the
the html/javascript/browser platform. imgui-js
achieves this through a combination of manual glue code, the webgl canvas,
and the results of the emscripten cross compiler. imgui-njs
takes this
one step further by replacing enscripten and webgl with pure html, canvas
and natural, modern javascript. The primary advantage of this approach is that
it's more approachable for most web programmers. No OpenGL/3D experience
is required. Pure javascript and html5 canvas all the way down. This
makes, for example, multi-font support trivial. No texture atlases
are required (or at least, this aspect of GPUs is hidden behind the
browser's canvas implementation). A significant disadvantage of this approach
is that it fundamentally breaks from the original dear-imgui
codebase and
foists the ongoing support and improvement of the library onto the developers
of this codebase.
Now it's possible to develop immediate-mode interfaces for web applications using the combination of javascript and imgui-njs. But, you ask, why would anyone want to do this? After all, we already have a host of gui frameworks and packages available? Generally, the answer is you probably don't. But if you have a graphics-intensive and GUI-intensive application and require a web-deployment model, this approach may be for you.
- The biggest and most controversial choice was to embrace the idea that javascript and C are sufficiently different as to render the idea of minimizing code diffs unreasonable. This is an entirely manual port (with some rewritten sections). While it's still a straightforward activity to migrate changes from dear-imgui, it's far from automatic. This contrasts with the cross-compilation approach taken by imgui-js. Supporting legacy or c+gl-specific features was not the priority here.
- lower performance (speed and memory) than C++ plus OpenGL/DirectX/Vulcan/Metal. May not be suitable for performance-sensitive games or tools.
- integration with 3d via separate DOM elements
- pass by reference of POD doesn't work. We rely on onChange callbacks and introduce ValRef and MutableString datatypes (see types.js).
- utf8 not directly supported, javascript native strings are utf-16
- float vs double not relevant, (lots of datatype distinctions irrelevant)
- method polymorphism not supported, there are a few cases where we inspect args to support a variety of calling styles.
- Colors are represented as objects, not float4 or u32.
- Vec2 are objects and can't be aliased to an array[2]
- Fonts aren't gl textures. We let the browser manage them in the standard html/canvas fashion. Text layout however isn't browser, but rather imgui.
- Images are referred to by url, not texture id.
- Drawlists are managed differently have have different interfaces.
- Text filtering uses javascript regexp
- Memory allocation is out of your hands (for better and worse)
- Since browser is portable, separable renderer/plugins aren't required.
- Persistance and Security governed by browser (and server).
- text input is re-written (but inspired by 'stb_textedit')
- code has been factored into lots of small files rather than a few big ones. We combine them into an imgui class via javascript mixin. Long lines have been shortend. Internal methods renamed to start with lowercase. Public methods & vars remain UpperCase. 'snake_case' is deprecated (but still prevalent).
- introduction of named styles (combining colors, fonts and windows)
- additional style configurations
- named fonts part of style
- numerical expressions will be generalize via a number-edit widget
atop javascript
eval
. (simple */+ operators work).
- we introduce guictx.LineHeight to separate FontSize from line spacing. It is expressed as a percentage of FontSize.
- FontScale, FontGlobalScale, FontBaseSize are not supported since we rely on css-like font specs. The same effect can be achieved by selected a new font (which combines face and scale).
- WindowFontScale supported in the form of a per-window font.
- we introduced a per-window zIndex to enhance control over window stacking order. This is currently more of a proof-of-concept than a full-featured implemenation.
See todo.md for current status. tl;dr: there's still a lot to do! The basic widget demos are mostly functional. Code is approximately equivalent to dear-imgui 1.70 (WIP). This code is very much a work in progress and probably not ready for prime time.