3 ms·
I'm just doing stuff myself, using C with OpenGL and some platform code. I can already target the web using emscripten. I'll be able to compile to Android in th
by jstimpfle 6y ago
I'm just doing stuff myself, using C with OpenGL and some platform code. I can already target the web using emscripten. I'll be able to compile to Android in the future.
It is a tough learning curve but I'm starting to see the light. Depending on your application, completely self-contained GUIs don't actually need that much code - it's mostly the knowledge of how to architect them.
A hard problem is how to approach construction of Widgets and hierarchies of control elements. The traditional OO centric approach is far too much boilerplate to be practical without a huge third-party library, but the Immediate GUI approach which got talked about a lot recently is maybe a little simplistic. I think I've found a good middle ground between "immediate" and "retained".
- fctorial 6y agoThat would require knowledge of every platform specific graphics stack (wayland, win32, cocoa, ndk). How is this a feasible approach? Are you making your own custom cross platform framework?
- jstimpfle 6y agoNo I'm just doing OpenGL. This is about cross platform - I don't really use the platform specific fuss. I need a window to draw to, and maybe a little file writing or networking code. I don't do Macs so far, so I can't tell you about that. I have a little boilerplate for setting up a window and getting input events for X11 (Linux) and Win32/GDI. It's about 300-400 lines each. You can opt to use GLFW3 instead to target all the big platforms with a single file that is also 300-400 lines. Mac is supported, too. I have mostly ceased to use GLFW since I prefer to code the stuff myself to have absolute control in case I need it, and to understand the issues of the platforms I have dealt with - but frankly GLFW is a very good and sleek library to get an OpenGL window and some inputs. Getting to the web using emscripten was similar. They support an older GLFW2 API so it was a matter of maybe 30 minutes to convert my GLFW code to run on the web. They also have a HTML5 API (html5.h) which is probably better, so I expect to add another couple hundred lines later at some point for that. Emscripten / the Web required me to port my desktop OpenGL code to OpenGL ES 3.0, which was quickly done and a very good idea to do anyway. And after all, the OpenGL rendering backend code is not that big either if your architecture is right. Mine is currently 700 lines, and it supports solid faces, textured faces, alpha-channels, subpixel font rendering - all of course for 2D and 3D.
- krzat 6y agoYou should look at modern UI libraries like Flutter or SwiftUI. It's a lot like immediate UI, but: - it is capable of storing state: storing position in scroll view, which page is currently visible, etc. - it tracks dependencies, so ideally UI building code is executed again only if something changed that would affect it's output.
- jstimpfle 6y agoThe approach I currently take is I just re-layout on each frame. If you have <1000 elements visible on the screen, I don't think that will ever be a problem. I currently have only about 20 though, so I don't really know. The important point is that I don't allocate and re-initialize the state of all controls. It's enough if you do from scratch the layout - that gets much simpler if you don't have to code a diff against the previous state. So I basically have a simple Widget abstraction - a draw function and a process-input function + some identification data (implemented as a union of void-ptr and int). I can then make lists of these abstract Widgets, and each list represents the set of childs of a superordinate element. This abstraction allows me to construct hierarchies and to have unabstracted and very flexible code for the layout, while the layout and input processing code can be generic - it's a simple loop over the list, calling the callback with the abstract handle. If there are ever performance problems you can still fluidly move more towards some retained layout state. This for sure will require more complex code, but if you just do it for complex layouts with lots of elements, I figure you get the best of both worlds. Mouse and drag handling is a little bit tricky as well - how to keep sending events to the slider control widget for example even if the mouse is temporarily outside the widget? The important realization is that dragging needs global state. You set the mouse globally as "grabbed" and provide a callback to execute when there are more mouse events.