- 155comments
- 509comments
- 190comments
- 76comments
- 50comments
- 57comments
- 566comments
- —discuss
- 17comments
- 46comments
- 10comments
- 138comments
- 123comments
- 125comments
- 12comments
- 200comments
- 301comments
- 364comments
- 1comments
- 27comments
- 93comments
- 20comments
- 25comments
- 16comments
- 51comments
- 49comments
- 281comments
- 127comments
- 9comments
- 123comments
If the correct URL is http://iki.fi/sol/imgui/ why does it redirect to http://sol.gfxile.net/imgui/? Should be the opposite.
iki.fi is a Finnish mail and homepage url rerouting service whose selling point is trying to stick around forever with minimal overhead. With it, people can use their ISP-provided email addresses and homepages and use the Iki addresses as canonical locations for their stuff that will work even after they change ISPs.
This is a really interesting approach to writing graphical user interfaces, if you have written any GUI code ever this is highly recommended reading. The differences are subtle but extremely important. Here is a simple example that both renders a button and tests if it has been clicked:
if button("label", 100, 100) { buttonAction(); }
There are two main benefits to IMGUI's. First, you don't need to package your data from whatever store it is into some GUI widget format. The canonical example is a long list or any other data intensive format that you want the user to be able to explore. In a classical GUI there is a lot of data packing and unpacking to be done to handle this.
The second benefit is that your UI's can be much more dynamic and reactive. Because rendering can be nested inside conditional statements and similar it's easy to create bespoke details easily that would be very hard with a traditional GUI framework.
The main limitation with IMGUI's is that they are easier to implement on a system that has pretty constant screen refresh and where you can control the pixels on the screen directly. It is possible to implement an IMGUI on top of a classical GUI framework but that is usually not worth the effort, the classical framework will kill most of the benefits of IMGUI.
A second word of warning is that while IMGUI's tend to result in 40-50% less code that code will be more intensive. This is definitely a technique you want to utilize when you need to hit those high notes and create something world changing.
For a concrete example of IMGUI's in the wild take a look at the editor at http://tinkercad.com. The whole user interface is done as an IMGUI system which is a big reason why we have been able to create things like our unique manipulation widget.
Manually checking if buttons are pressed seems very wrong to me, I want some kind of event framework to associate a 'button' area to an action. Then when a click is fired, work out which button this maps to, and execute the specific action.
I don't see how IMGUI specifically can add features over other methods either.
It requires a twist in your thinking for sure. We are so used to events, but don't realize how user unfriendly they can be. Polling is quite usable, and its rather easy to modularize polling code without any callbacks or inverted control flow.
If you have an object-oriented language (or near enough) with usable function types you can still emulate "traditional" GUI things if you really want to. Behold:
I have found that imgui are easy to use, but only for the basics. When you want to build something more complex, like animations and transitions between dialogs, it becomes messy.
Unity 3d uses imgui style editor and extension (you can extend the system in realtime, while it's working)
I have this excellent tutorial translated to luajit+sdl ffi bindings http://github.com/malkia/ufo/tree/master/samples/SDL/imgui
There's a good video on Immediate-Mode GUI by Casey Muratori at http://mollyrocket.com/861
C++11 lets you do compile time string hashing, so you can automatically generate the IMGUI_SRC_ID from __FILE__ and hopefully get rid of one bit of manual handholding with GEN_ID.
Either I'm missing something, or this must be absolutely horrific in terms of performance. Each object draws itself every frame, is that correct? If that's not true, then you must spend a huge amount of time trying to figure out which objcts need to be drawn and which objects don't. Indeed this is the very work that most event driven GUI frameworks try to spare the developer from having to deal with, because the problem is not trivial.
As I said, maybe I'm missing something, in which case I would love for someone to enlighten me...
For small UIs in games that run at frame rate, the performance is probably competitive to (if not better than) a retained UI. They are probably redrawing their screen on each frame anyways, while retained has its own memory/compute overhead to consider.
Now, there is some point where the immediate mode UI becomes uncompetitive with retained; if you have a lot of complex/nested widgets for example, or you care about power consumption for a mostly static UI.
In games and other interactive applications you redraw screen every frame (sth like 60 times a second) anyway. And drawing a few more sprites when you're drawing sth anyway is almost free, when you have acceleration. And doing simple animations is much simpler (you just change the proprty you want to with required step per frame, it is refreshed anyway, so no need to mark dirty rectangles, calling .refresh(), etc).
Also - perceived latency is low, because from the time you click something to the time screend redraws, there is at most 1/FPS seconds. Most probably less than 20 milliseconds.
Simple solution to this redrawing issue is global flag signifying whether refresh is needed that is cleared in the frame loop after all gui calls. Also complete redraw on every frame is how most game UIs work anyway and it's not significant performance issue today (it was an issue 15 years ago when I wrote several immediate UI libraries for DOS, although performance issue there had more to do with overhead of synchronizing redraws with mouse driver than graphics performance itself).
The main problem with this approach is that you essentially end up doing one large busyloop across many irrelevant parts of code. This implementation seems to solve this by blocking at the end of each iteration waiting for any event to occur, but probably still wastes CPU time significantly.