2015-09-09 20:33:32 +03:00
|
|
|
# Zahnrad
|
2015-07-25 23:16:35 +03:00
|
|
|
[![Coverity Status](https://scan.coverity.com/projects/5863/badge.svg)](https://scan.coverity.com/projects/5863)
|
2015-07-25 22:32:37 +03:00
|
|
|
|
2015-05-21 14:06:29 +03:00
|
|
|
This is a bloat free minimal state immediate mode graphical user interface toolkit
|
2015-08-27 20:25:13 +03:00
|
|
|
written in ANSI C. It was designed as a simple embeddable user interface for
|
2015-09-17 18:31:43 +03:00
|
|
|
application and does not have any direct dependencies. It does not have
|
|
|
|
a default renderbackend, os window and input handling but instead provides a very modular
|
|
|
|
library approach by providing a simple input state storage for input and draw
|
|
|
|
commands describing primitive shapes as output. So instead of providing a
|
|
|
|
layered library that tries to abstract over a number of platform and
|
|
|
|
render backends it only focuses on the actual GUI.
|
2015-03-11 16:00:59 +03:00
|
|
|
|
2015-03-14 19:05:30 +03:00
|
|
|
## Features
|
2015-04-16 17:20:00 +03:00
|
|
|
- Immediate mode graphical user interface toolkit
|
2015-03-14 19:05:30 +03:00
|
|
|
- Written in C89 (ANSI C)
|
2015-09-15 19:13:43 +03:00
|
|
|
- Small codebase (~8kLOC)
|
2015-05-17 15:39:02 +03:00
|
|
|
- Focus on portability, efficiency, simplicity and minimal internal state
|
|
|
|
- No global or hidden state
|
2015-09-15 19:13:43 +03:00
|
|
|
- No direct dependencies
|
2015-05-11 13:45:22 +03:00
|
|
|
- Configurable style and colors
|
2015-04-30 17:12:21 +03:00
|
|
|
- UTF-8 support
|
2015-09-16 11:41:14 +03:00
|
|
|
- Optional vertex buffer output and font handling
|
2015-03-24 15:08:42 +03:00
|
|
|
|
2015-09-18 00:09:49 +03:00
|
|
|
The library is self-contained within four different files that only have to be
|
|
|
|
copied and compiled into your application. Files zahnrad.c and zahnrad.h make up
|
2015-09-17 18:31:43 +03:00
|
|
|
the core of the library, while stb_rect_pack.h and stb_truetype.h are
|
|
|
|
for a optional font handling implementation and can be removed if not needed.
|
2015-09-18 00:09:49 +03:00
|
|
|
- zahnrad.c
|
|
|
|
- zahnrad.h
|
2015-09-17 18:31:43 +03:00
|
|
|
- stb_rect_pack.h
|
|
|
|
- stb_truetype.h
|
2015-09-17 18:35:45 +03:00
|
|
|
|
2015-09-18 00:09:49 +03:00
|
|
|
There are no dependencies or a particular building process required. You just have
|
|
|
|
to compile the .c file and #include zahnrad.h into your project. To actually
|
2015-09-17 18:31:43 +03:00
|
|
|
run you have to provide the input state, configuration style and memory
|
|
|
|
for draw commands to the library. After the GUI was executed all draw commands
|
|
|
|
have to be either executed or optionally converted into a vertex buffer to
|
|
|
|
draw the GUI.
|
|
|
|
|
2015-05-09 16:22:23 +03:00
|
|
|
## Gallery
|
2015-09-17 18:31:43 +03:00
|
|
|
![gui
|
|
|
|
demo](https://cloud.githubusercontent.com/assets/8057201/9937241/24f55e7e-5d60-11e5-9957-c010cf763f15.png)
|
|
|
|
![gui
|
2015-09-17 18:35:45 +03:00
|
|
|
explorer](https://cloud.githubusercontent.com/assets/8057201/9937240/24f509ce-5d60-11e5-894a-e7e9e228de30.png)
|
2015-09-17 18:31:43 +03:00
|
|
|
![gui
|
|
|
|
nodedit](https://cloud.githubusercontent.com/assets/8057201/9937243/24f6a5ea-5d60-11e5-81bc-21de3b6f4b1b.png)
|
2015-05-09 16:22:23 +03:00
|
|
|
|
2015-04-25 17:44:43 +03:00
|
|
|
## Example
|
|
|
|
```c
|
2015-08-10 21:34:47 +03:00
|
|
|
/* setup configuration */
|
2015-09-18 00:09:49 +03:00
|
|
|
struct zr_style style;
|
|
|
|
struct zr_user_font font = {...};
|
|
|
|
zr_style_default(&style, ZR_DEFAULT_ALL, &font);
|
2015-05-29 15:47:42 +03:00
|
|
|
|
2015-09-09 14:54:20 +03:00
|
|
|
/* allocate memory to hold draw commands */
|
2015-09-18 00:09:49 +03:00
|
|
|
struct zr_command_queue queue;
|
|
|
|
zr_command_queue_init_fixed(&queue, malloc(MEMORY_SIZE), MEMORY_SIZE);
|
2015-09-09 14:54:20 +03:00
|
|
|
|
2015-09-17 18:31:43 +03:00
|
|
|
/* initialize window */
|
2015-09-18 00:09:49 +03:00
|
|
|
struct zr_window window;
|
|
|
|
zr_window_init(&window, 50, 50, 220, 180,
|
|
|
|
ZR_WINDOW_BORDER|ZR_WINDOW_MOVEABLE|ZR_WINDOW_SCALEABLE,
|
2015-09-16 16:04:26 +03:00
|
|
|
&queue, &style, &input);
|
2015-04-25 17:44:43 +03:00
|
|
|
|
2015-06-28 11:09:53 +03:00
|
|
|
/* setup widget data */
|
2015-08-05 13:48:01 +03:00
|
|
|
enum {EASY, HARD};
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_size option = EASY;
|
|
|
|
zr_size item = 0;
|
|
|
|
zr_state active = 0;
|
2015-06-28 11:09:53 +03:00
|
|
|
|
2015-09-18 00:09:49 +03:00
|
|
|
struct zr_input input = {0};
|
2015-04-25 17:44:43 +03:00
|
|
|
while (1) {
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_input_begin(&input);
|
2015-04-25 17:44:43 +03:00
|
|
|
/* record input */
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_input_end(&input);
|
2015-04-25 17:44:43 +03:00
|
|
|
|
2015-05-14 16:14:15 +03:00
|
|
|
/* GUI */
|
2015-09-18 00:09:49 +03:00
|
|
|
struct zr_context context;
|
|
|
|
zr_begin(&context, &window);
|
2015-08-06 17:36:28 +03:00
|
|
|
{
|
|
|
|
const char *items[] = {"Fist", "Pistol", "Railgun", "BFG"};
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_header(&context, "Show", ZR_CLOSEABLE, 0, ZR_HEADER_LEFT);
|
|
|
|
zr_layout_row_static(&context, 30, 80, 1);
|
|
|
|
if (zr_button_text(&context, "button", ZR_BUTTON_DEFAULT)) {
|
2015-08-06 17:36:28 +03:00
|
|
|
/* event handling */
|
|
|
|
}
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_layout_row_dynamic(&context, 30, 2);
|
|
|
|
if (zr_option(&context, "easy", option == EASY)) option = EASY;
|
|
|
|
if (zr_option(&context, "hard", option == HARD)) option = HARD;
|
|
|
|
zr_label(&context, "Weapon:", ZR_TEXT_LEFT);
|
|
|
|
zr_combo(&context, items, LEN(items), &item, 20, &active);
|
2015-04-25 17:44:43 +03:00
|
|
|
}
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_end(&context, &window);
|
2015-04-25 17:44:43 +03:00
|
|
|
|
2015-05-14 16:14:15 +03:00
|
|
|
/* draw */
|
2015-09-18 00:09:49 +03:00
|
|
|
const struct zr_command *cmd;
|
|
|
|
zr_foreach_command(cmd, &queue) {
|
2015-05-29 15:47:42 +03:00
|
|
|
/* execute draw call command */
|
2015-04-25 17:44:43 +03:00
|
|
|
}
|
2015-09-18 00:09:49 +03:00
|
|
|
zr_command_queue_clear(&queue);
|
2015-04-25 17:44:43 +03:00
|
|
|
}
|
|
|
|
```
|
2015-09-17 18:31:43 +03:00
|
|
|
![gui
|
|
|
|
screenshot](https://cloud.githubusercontent.com/assets/8057201/9937242/24f58b9c-5d60-11e5-94df-780232ca613e.png)
|
2015-04-25 17:44:43 +03:00
|
|
|
|
2015-05-09 15:11:55 +03:00
|
|
|
## IMGUIs
|
|
|
|
Immediate mode in contrast to classical retained mode GUIs store as little state as possible
|
|
|
|
by using procedural function calls as "widgets" instead of storing objects.
|
|
|
|
Each "widget" function call takes hereby all its necessary data and immediately returns
|
2015-09-15 19:13:43 +03:00
|
|
|
the user modified state back to the caller. Immediate mode graphical
|
2015-05-09 15:11:55 +03:00
|
|
|
user interfaces therefore combine drawing and input handling into one unit
|
|
|
|
instead of separating them like retain mode GUIs.
|
|
|
|
|
|
|
|
Since there is no to minimal internal state in immediate mode user interfaces,
|
2015-09-15 19:13:43 +03:00
|
|
|
updates have to occur every frame, on every user input update or program state change
|
|
|
|
which on one hand is more drawing expensive than classic
|
2015-05-09 15:11:55 +03:00
|
|
|
retained GUI implementations but on the other hand grants a lot more flexibility and
|
|
|
|
support for overall layout changes. In addition without any state there is no
|
|
|
|
duplicated state between your program, the gui and the user which greatly
|
|
|
|
simplifies code. Further traits of immediate mode graphic user interfaces are a
|
|
|
|
code driven style, centralized flow control, easy extensibility and
|
|
|
|
understandability.
|
2015-04-20 22:14:58 +03:00
|
|
|
|
2015-04-12 16:40:42 +03:00
|
|
|
## FAQ
|
2015-09-17 18:31:43 +03:00
|
|
|
#### Where is the demo/example code and documentation?
|
2015-04-30 17:12:21 +03:00
|
|
|
The demo and example code can be found in the demo folder.
|
2015-09-17 18:31:43 +03:00
|
|
|
There is demo code for Linux(X11), nanovg and OpenGL with SDL.
|
|
|
|
The documentation can be found in gui.h. I documented each submodule and
|
|
|
|
function with description and parameter explanation.
|
2015-04-12 16:40:42 +03:00
|
|
|
|
2015-04-16 21:05:43 +03:00
|
|
|
#### Why did you use ANSI C and not C99 or C++?
|
2015-04-12 16:40:42 +03:00
|
|
|
Personally I stay out of all "discussions" about C vs C++ since they are totally
|
|
|
|
worthless and never brought anything good with it. The simple answer is I
|
2015-05-03 13:22:43 +03:00
|
|
|
personally love C and have nothing against people using C++ especially the new
|
2015-04-16 17:20:00 +03:00
|
|
|
iterations with C++11 and C++14.
|
2015-04-12 16:40:42 +03:00
|
|
|
While this hopefully settles my view on C vs C++ there is still ANSI C vs C99.
|
2015-04-16 21:05:43 +03:00
|
|
|
While for personal projects I only use C99 with all its niceties, libraries are
|
2015-04-16 17:20:00 +03:00
|
|
|
a little bit different. Libraries are designed to reach the highest number of
|
2015-04-17 23:28:00 +03:00
|
|
|
users possible which brings me to ANSI C as the most portable version.
|
2015-04-16 21:05:43 +03:00
|
|
|
In addition not all C compiler like the MSVC
|
2015-04-16 17:20:00 +03:00
|
|
|
compiler fully support C99, which finalized my decision to use ANSI C.
|
2015-04-12 16:40:42 +03:00
|
|
|
|
2015-04-20 23:29:31 +03:00
|
|
|
#### Why do you typedef your own types instead of using the standard types?
|
2015-04-16 21:05:43 +03:00
|
|
|
This Project uses ANSI C which does not have the header file `<stdint.h>`
|
|
|
|
and therefore does not provide the fixed sized types that I need. Therefore
|
2015-04-12 16:40:42 +03:00
|
|
|
I defined my own types which need to be set to the correct size for each
|
2015-05-03 13:22:43 +03:00
|
|
|
platform. But if your development environment provides the header file you can define
|
2015-09-18 00:09:49 +03:00
|
|
|
`ZR_USE_FIXED_SIZE_TYPES` to directly use the correct types.
|
2015-04-12 16:40:42 +03:00
|
|
|
|
2015-03-14 19:05:30 +03:00
|
|
|
## References
|
2015-09-17 18:31:43 +03:00
|
|
|
- [stb_rect_pack.h and stb_truetype.h by Sean Barret (public domain)](https:://github.com/nothings/stb/)
|
2015-04-12 16:40:42 +03:00
|
|
|
- [Tutorial from Jari Komppa about imgui libraries](http://www.johno.se/book/imgui.html)
|
2015-03-25 16:32:43 +03:00
|
|
|
- [Johannes 'johno' Norneby's article](http://iki.fi/sol/imgui/)
|
2015-09-15 19:13:43 +03:00
|
|
|
- [ImGui: The inspiration for this project from ocornut](https://github.com/ocornut/imgui)
|
2015-04-20 22:36:16 +03:00
|
|
|
- [Nvidia's imgui toolkit](https://code.google.com/p/nvidia-widgets/)
|
2015-03-14 19:05:30 +03:00
|
|
|
|
2015-03-03 19:24:02 +03:00
|
|
|
# License
|
|
|
|
(The MIT License)
|