updated Readme
This commit is contained in:
parent
322bb21b9c
commit
f5b4bd73f3
152
Readme.md
152
Readme.md
@ -18,11 +18,11 @@ WORK IN PROGRESS: I do not garantee that everything works right now
|
||||
- Does NOT provide platform independent window management
|
||||
- Does NOT provide platform independent input handling
|
||||
- Does NOT provide a renderer backend
|
||||
- Does NOT implement a font library
|
||||
- Does NOT implement a font library
|
||||
Summary: It is only responsible for the actual user interface
|
||||
|
||||
## Layer
|
||||
The gui toolkit consists of three level of abstraction. First the basic widget layer
|
||||
The gui toolkit consists of three levels of abstraction. First the basic widget layer
|
||||
for a as pure functional as possible set of widgets functions without
|
||||
any kind of internal state, with the tradeoff off of a lot of boilerplate code.
|
||||
Second the panel layer for a static grouping of widgets into a panel with a reduced need for
|
||||
@ -34,6 +34,117 @@ over the panel management and therefore needs the most amount of internal state.
|
||||
Each higher level of abstraction uses the lower level(s) internally to build
|
||||
on but offers a little bit different API.
|
||||
|
||||
#### Widgets
|
||||
The widget layer provides the most basic way of creating graphical user interface
|
||||
elements. It consist only of functions and only operates on the given data. Each
|
||||
widgets takes in the current input state, font and the basic element configuration
|
||||
and returns an updated draw buffer and the state of the element.
|
||||
With each widget the buffer gets filled with a number of primitives that need be
|
||||
drawn to screen. The main reason for the command buffer to queue up the draw
|
||||
calls instead of just using a callback to directly draw the primitive lies in
|
||||
the context which needs control over the drawing order. For a more limited scope
|
||||
of functionality it would have been better to just use draw callbacks and to not
|
||||
rely on memory allocation at all. The API will change if I find a way to
|
||||
combine the buffer needed by the context with the drawing callbacks.
|
||||
|
||||
```c
|
||||
struct gui_input input = {0};
|
||||
struct gui_command_buffer buffer;
|
||||
struct gui_command_list list;
|
||||
struct gui_memory_status status;
|
||||
const struct gui_font font = {...};
|
||||
const struct gui_buffer button = {...};
|
||||
struct gui_memory memory = {...};
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
gui_output_begin(&buffer, &memory);
|
||||
if (gui_widget_button(&buffer, &button, "button", &font, &input))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_output_end(&buffer, &status, &list);
|
||||
/* execute command list */
|
||||
}
|
||||
```
|
||||
|
||||
#### Panels
|
||||
Panels provide an easy way to group together a number of widgets and reduce
|
||||
some of the boilerplate code of the widget layer. Most of the boilerplate code
|
||||
gets reduced by introducing a configration structure to provide a common look.
|
||||
Instead of having a fixed layout and owning and holding widgets like in classic
|
||||
graphical user interfaces, panels use an immediate mode approach of just setting
|
||||
the layout of one row of the panel at a time and filling each row with widgets.
|
||||
Therefore the only state that is being modfied over the course of setting up the
|
||||
panel is an index descriping the current position of the next widget and the
|
||||
current height and number of columns of the current row. In addition panels
|
||||
provide a number of grouping functionality for widgets with groups, tabs and
|
||||
shelfs and provide a minimizing and closing functionality.
|
||||
|
||||
```c
|
||||
struct gui_config config;
|
||||
struct gui_command_buffer buffer;
|
||||
struct gui_command_list list;
|
||||
struct gui_memory_status status;
|
||||
const struct gui_font font = {...};
|
||||
struct gui_memory memory = {...};
|
||||
struct gui_panel panel = {0};
|
||||
gui_default_config(&config);
|
||||
gui_panel_init(&panel, &config, &font);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
gui_output_begin(&buffer, &memory);
|
||||
gui_panel_begin(&panel, &buffer, &input, "Demo", 50, 50, 400, 300, 0);
|
||||
gui_panel_layout(&panel, 30, 1);
|
||||
if (gui_panel_button_text(&panel, "button", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_panel_end(&panel);
|
||||
gui_output_end(&buffer, &status, &list);
|
||||
/* execute command list */
|
||||
}
|
||||
```
|
||||
|
||||
#### Context
|
||||
The context extends the panel functionality with moving, scaling and overlapping
|
||||
panels which are quite a bit more complicated than just minimzing and closing of
|
||||
panels. For panel overlapping to work as intented the context needs complete control
|
||||
over all created panels to control the drawing order. OVerall the expense to
|
||||
provide overlapping panels is quite hight since draw calls, the context and
|
||||
all panels need to be managed and allocated.
|
||||
|
||||
```c
|
||||
struct gui_config config;
|
||||
struct gui_output output;
|
||||
struct gui_memory_status status;
|
||||
const struct gui_font font = {...};
|
||||
struct gui_memory memory = {...};
|
||||
struct gui_panel *panel;
|
||||
struct gui_context *ctx;
|
||||
gui_default_config(&config);
|
||||
ctx = gui_new(&memory, &input);
|
||||
panel = gui_new_panel(ctx, 50, 50, 400, 300, &config, &font);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
gui_begin(ctx, 800, 600);
|
||||
gui_begin_panel(ctx, panel, "demo", 0);
|
||||
gui_panel_layout(&panel, 30, 1);
|
||||
if (gui_panel_button_text(&panel, "button", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_end_panel(ctx, &panel, NULL);
|
||||
gui_end(ctx, &output, NULL);
|
||||
/* execute output lists */
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
The gui toolkit provides a number of different attributes that can be
|
||||
configured, like spacing, padding, size and color.
|
||||
@ -59,7 +170,7 @@ iterations with C++11 and C++14.
|
||||
While this hopefully settles my view on C vs C++ there is still ANSI C vs C99.
|
||||
While for personal projects I only use C99 with all its niceties, libraries are
|
||||
a little bit different. Libraries are designed to reach the highest number of
|
||||
users possible which brings me to ANSI C which is the most portable version.
|
||||
users possible which brings me to ANSI C as the most portable version.
|
||||
In addition not all C compiler like the MSVC
|
||||
compiler fully support C99, which finalized my decision to use ANSI C.
|
||||
|
||||
@ -70,6 +181,41 @@ I defined my own types which need to be set to the correct size for each
|
||||
plaform. But if your development environment provides the header file you can define
|
||||
`GUI_USE_FIXED_SIZE_TYPES` to directly use the correct types.
|
||||
|
||||
#### Why is the font/input/window management not provided
|
||||
As for window and input management it is a ton of work to abstract over
|
||||
all possible platforms and there are already libraries like SDL or SFML or even
|
||||
the platform itself which provide you with the functionality.
|
||||
So instead of reinventing the wheel and trying to do everything the project tries
|
||||
to be as indepenedent and out of the users way as possible.
|
||||
This means in practice a litte bit more work on the users behalf but grants a
|
||||
lot more freedom especially because the toolkit is designed to be embeddable.
|
||||
|
||||
The font management on the other hand is a more tricky subject. In the beginning
|
||||
the toolkit had some basic font handling but it got later removed. This is mainly
|
||||
a question of if font handling should be part of a gui toolkit or not. As for a
|
||||
framework the question would definitely be yes but for a toolkit library the
|
||||
question is not as easy. In the end the project does not have font handling
|
||||
since there are already a number of font handling libraries in existence or even the
|
||||
platform (Xlib, Win32) itself already provides a solution.
|
||||
|
||||
#### Why do you use fixed size memory management
|
||||
This is one of the more controversial decision in the toolkit and it comes down
|
||||
to some preference that I personally build up. There are two general
|
||||
ways to allocate memory, the standard way of callbacks and preallocation.
|
||||
Personally I am not a big fan of callbacks even though they have their use cases
|
||||
for abstraction purposes but are greatly overused in my experience. The biggest
|
||||
misuse of callbacks are asynchrounous callbacks with resulting state changes which are
|
||||
hell to grasp and truly comprehend in a big system.
|
||||
Memory callbacks are an edge case for me and definitly shine in cases where a lot
|
||||
of unpredictable allocation with varying life cycles take place. This toolkit on
|
||||
the other hand has a relative stable memory allocation behavior. In the worse
|
||||
case on the highst abstraction layer only the context, panels and the command
|
||||
buffer need memory. In addition the general memory consumption is not that high
|
||||
and could even be described as insignificant for the modern memory size. For a
|
||||
system with a low amount of memory it is even better since there is only a small
|
||||
limited amount of memory which is easier to optimize for as a fixed amount of memory than
|
||||
a number of unrelated allocation calls.
|
||||
|
||||
## References
|
||||
- [Tutorial from Jari Komppa about imgui libraries](http://www.johno.se/book/imgui.html)
|
||||
- [Johannes 'johno' Norneby's article](http://iki.fi/sol/imgui/)
|
||||
|
11
demo/xlib.c
11
demo/xlib.c
@ -65,9 +65,6 @@ struct demo {
|
||||
gui_char in_buf[MAX_BUFFER];
|
||||
gui_size in_len;
|
||||
gui_bool in_act;
|
||||
gui_char cmd_buf[MAX_BUFFER];
|
||||
gui_size cmd_len;
|
||||
gui_bool cmd_act;
|
||||
gui_bool check;
|
||||
gui_int option;
|
||||
gui_float slider;
|
||||
@ -428,7 +425,7 @@ gui_draw(XSurface *surf, const struct gui_output *out)
|
||||
static gui_bool
|
||||
demo_panel(struct gui_context *ctx, struct gui_panel *panel, struct demo *demo)
|
||||
{
|
||||
enum {PLOT, HISTO};
|
||||
enum {HISTO, PLOT};
|
||||
const char *shelfs[] = {"Histogram", "Lines"};
|
||||
const gui_float values[] = {8.0f, 15.0f, 20.0f, 12.0f, 30.0f};
|
||||
const char *items[] = {"Fist", "Pistol", "Shotgun", "Railgun", "BFG"};
|
||||
@ -452,7 +449,7 @@ demo_panel(struct gui_context *ctx, struct gui_panel *panel, struct demo *demo)
|
||||
gui_panel_layout(panel, 200, 2);
|
||||
demo->current = gui_panel_shelf_begin(panel, &demo->shelf, shelfs, LEN(shelfs), demo->current);
|
||||
gui_panel_layout(&demo->shelf, 100, 1);
|
||||
if (demo->current == PLOT) {
|
||||
if (demo->current == HISTO) {
|
||||
gui_panel_histo(&demo->shelf, values, LEN(values));
|
||||
} else {
|
||||
gui_panel_plot(&demo->shelf, values, LEN(values));
|
||||
@ -483,8 +480,8 @@ message_panel(struct gui_context *ctx, struct gui_panel *panel)
|
||||
gui_int ret = -1;
|
||||
gui_begin_panel(ctx, panel, "Error", GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
gui_panel_layout(panel, 30, 2);
|
||||
if (gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT)) ret = 1;
|
||||
if (gui_panel_button_text(panel, "cancel", GUI_BUTTON_DEFAULT)) ret = 0;
|
||||
gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT);
|
||||
gui_panel_button_text(panel, "cancel", GUI_BUTTON_DEFAULT);
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
}
|
||||
|
||||
|
72
gui.c
72
gui.c
@ -479,14 +479,14 @@ gui_buffer_push_triangle(struct gui_command_buffer *buffer, struct gui_vec2 *pos
|
||||
}
|
||||
|
||||
static void
|
||||
gui_buffer_push_bitmap(struct gui_command_buffer *buffer, gui_float x, gui_float y,
|
||||
gui_float w, gui_float h, gui_texture texture)
|
||||
gui_buffer_push_bitmap(struct gui_command_buffer *buffer, const struct gui_rect *src,
|
||||
const struct gui_rect *dst, gui_texture texture)
|
||||
{
|
||||
struct gui_command_bitmap *bitmap;
|
||||
bitmap = gui_buffer_push(buffer, GUI_COMMAND_BITMAP, sizeof(*bitmap));
|
||||
if (!bitmap) return;
|
||||
bitmap->x = x; bitmap->y = y;
|
||||
bitmap->w = w; bitmap->h = h;
|
||||
bitmap->src = *src;
|
||||
bitmap->dst = *dst;
|
||||
bitmap->texture = texture;
|
||||
}
|
||||
|
||||
@ -566,29 +566,22 @@ gui_widget_text(struct gui_command_buffer *buffer, const struct gui_text *text,
|
||||
(const gui_char*)text->string, text->length, text->background, text->foreground);
|
||||
}
|
||||
|
||||
/*
|
||||
void
|
||||
gui_widget_image(struct gui_draw_buffer *buffer, const struct gui_image *image)
|
||||
gui_widget_image(struct gui_command_buffer *buffer, const struct gui_image *image)
|
||||
{
|
||||
gui_float image_x;
|
||||
gui_float image_y;
|
||||
gui_float image_w;
|
||||
gui_float image_h;
|
||||
|
||||
struct gui_rect dst;
|
||||
assert(buffer);
|
||||
assert(image);
|
||||
if (!buffer || !image) return;
|
||||
|
||||
image_x = image->x + image->pad_x;
|
||||
image_y = image->y + image->pad_y;
|
||||
image_w = MAX(0, image->w - 2 * image->pad_x);
|
||||
image_h = MAX(0, image->h - 2 * image->pad_y);
|
||||
dst.x = image->dst.x + image->pad_x;
|
||||
dst.y = image->dst.y + image->pad_y;
|
||||
dst.w = MAX(0, image->dst.w - 2 * image->pad_x);
|
||||
dst.h = MAX(0, image->dst.h - 2 * image->pad_y);
|
||||
|
||||
gui_draw_rectf(buffer, image->x, image->y, image->w, image->h, image->background);
|
||||
gui_draw_image(buffer, image_x, image_y, image_w, image_h,
|
||||
image->texture, image->uv[0], image->uv[1], image->color);
|
||||
gui_buffer_push_rect(buffer, image->dst.x, image->dst.y, image->dst.w, image->dst.h, image->background);
|
||||
gui_buffer_push_bitmap(buffer, &image->src, &dst, image->texture);
|
||||
}
|
||||
*/
|
||||
|
||||
static gui_bool
|
||||
gui_widget_button(struct gui_command_buffer *buffer, const struct gui_button *button,
|
||||
@ -623,8 +616,7 @@ gui_widget_button(struct gui_command_buffer *buffer, const struct gui_button *bu
|
||||
|
||||
gui_bool
|
||||
gui_widget_button_text(struct gui_command_buffer *buffer, const struct gui_button *button,
|
||||
const char *string, gui_size length, const struct gui_font *font,
|
||||
const struct gui_input *in)
|
||||
const char *string, const struct gui_font *font, const struct gui_input *in)
|
||||
{
|
||||
gui_bool ret = gui_false;
|
||||
gui_float button_w, button_h;
|
||||
@ -656,7 +648,7 @@ gui_widget_button_text(struct gui_command_buffer *buffer, const struct gui_butto
|
||||
text.pad_x = button->pad_x;
|
||||
text.pad_y = button->pad_y;
|
||||
text.string = string;
|
||||
text.length = length;
|
||||
text.length = strsiz(string);
|
||||
text.align = GUI_TEXT_CENTERED;
|
||||
text.font = font->user;
|
||||
text.background = bg_color;
|
||||
@ -682,11 +674,9 @@ gui_widget_button_triangle(struct gui_command_buffer *buffer, struct gui_button*
|
||||
return pressed;
|
||||
}
|
||||
|
||||
/*
|
||||
gui_bool
|
||||
gui_widget_button_icon(struct gui_command_buffer *buffer, struct gui_button* button,
|
||||
gui_texture tex, struct gui_texCoord from, struct gui_texCoord to,
|
||||
const struct gui_input *in)
|
||||
gui_texture texture, const struct gui_rect *src, const struct gui_input *in)
|
||||
{
|
||||
gui_bool pressed;
|
||||
struct gui_image image;
|
||||
@ -698,23 +688,20 @@ gui_widget_button_icon(struct gui_command_buffer *buffer, struct gui_button* but
|
||||
return gui_false;
|
||||
|
||||
pressed = gui_widget_button(buffer, button, in);
|
||||
image.x = button->x + button->pad_x;
|
||||
image.y = button->y + button->pad_y;
|
||||
image.w = button->w - 2 * button->pad_x;
|
||||
image.h = button->h - 2 * button->pad_y;
|
||||
image.dst.x = button->x + button->pad_x;
|
||||
image.dst.y = button->y + button->pad_y;
|
||||
image.dst.w = button->w - 2 * button->pad_x;
|
||||
image.dst.h = button->h - 2 * button->pad_y;
|
||||
image.pad_x = button->pad_x;
|
||||
image.pad_y = button->pad_y;
|
||||
image.texture = tex;
|
||||
image.uv[0] = from;
|
||||
image.uv[1] = to;
|
||||
image.texture = texture;
|
||||
image.src = *src;
|
||||
col = (in && INBOX(in->mouse_pos.x,in->mouse_pos.y,button->x,button->y,button->w,button->h)) ?
|
||||
button->highlight: button->background;
|
||||
image.background = col;
|
||||
image.color = color;
|
||||
gui_widget_image(buffer, &image);
|
||||
return pressed;
|
||||
}
|
||||
*/
|
||||
|
||||
gui_bool
|
||||
gui_widget_toggle(struct gui_command_buffer *buffer, const struct gui_toggle *toggle,
|
||||
@ -1540,7 +1527,6 @@ gui_panel_button_text(struct gui_panel *panel, const char *str,
|
||||
struct gui_rect bounds;
|
||||
struct gui_button button;
|
||||
const struct gui_config *config;
|
||||
gui_size len;
|
||||
|
||||
assert(panel);
|
||||
assert(panel->config);
|
||||
@ -1550,7 +1536,6 @@ gui_panel_button_text(struct gui_panel *panel, const char *str,
|
||||
if (panel->minimized || (panel->flags & GUI_PANEL_HIDDEN)) return 0;
|
||||
gui_panel_alloc_space(&bounds, panel);
|
||||
config = panel->config;
|
||||
len = strsiz(str);
|
||||
|
||||
button.x = bounds.x;
|
||||
button.y = bounds.y;
|
||||
@ -1565,7 +1550,7 @@ gui_panel_button_text(struct gui_panel *panel, const char *str,
|
||||
button.content = config->colors[GUI_COLOR_TEXT];
|
||||
button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
|
||||
button.highlight_content = config->colors[GUI_COLOR_BUTTON_HOVER_FONT];
|
||||
return gui_widget_button_text(panel->out, &button, str, len, &panel->font, panel->in);
|
||||
return gui_widget_button_text(panel->out, &button, str, &panel->font, panel->in);
|
||||
}
|
||||
|
||||
gui_bool gui_panel_button_color(struct gui_panel *panel, const struct gui_color color,
|
||||
@ -1632,11 +1617,9 @@ gui_panel_button_triangle(struct gui_panel *panel, enum gui_heading heading,
|
||||
return gui_widget_button_triangle(panel->out, &button, heading, panel->in);
|
||||
}
|
||||
|
||||
/*
|
||||
gui_bool
|
||||
gui_panel_button_icon(struct gui_panel *panel, gui_texture tex,
|
||||
struct gui_texCoord from, struct gui_texCoord to,
|
||||
enum gui_button_behavior behavior)
|
||||
const struct gui_rect *src, enum gui_button_behavior behavior)
|
||||
{
|
||||
struct gui_rect bounds;
|
||||
struct gui_button button;
|
||||
@ -1663,9 +1646,8 @@ gui_panel_button_icon(struct gui_panel *panel, gui_texture tex,
|
||||
button.content = config->colors[GUI_COLOR_TEXT];
|
||||
button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
|
||||
button.highlight_content = config->colors[GUI_COLOR_BUTTON_HOVER];
|
||||
return gui_widget_button_icon(panel->out, &button, tex, from, to, panel->in);
|
||||
return gui_widget_button_icon(panel->out, &button, tex, src, panel->in);
|
||||
}
|
||||
*/
|
||||
|
||||
gui_bool
|
||||
gui_panel_button_toggle(struct gui_panel *panel, const char *str, gui_bool value)
|
||||
@ -1673,7 +1655,6 @@ gui_panel_button_toggle(struct gui_panel *panel, const char *str, gui_bool value
|
||||
struct gui_rect bounds;
|
||||
struct gui_button button;
|
||||
const struct gui_config *config;
|
||||
gui_size len;
|
||||
|
||||
assert(panel);
|
||||
assert(panel->config);
|
||||
@ -1684,7 +1665,6 @@ gui_panel_button_toggle(struct gui_panel *panel, const char *str, gui_bool value
|
||||
if (panel->minimized || (panel->flags & GUI_PANEL_HIDDEN)) return 0;
|
||||
gui_panel_alloc_space(&bounds, panel);
|
||||
config = panel->config;
|
||||
len = strsiz(str);
|
||||
|
||||
button.x = bounds.x;
|
||||
button.y = bounds.y;
|
||||
@ -1708,7 +1688,7 @@ gui_panel_button_toggle(struct gui_panel *panel, const char *str, gui_bool value
|
||||
button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
|
||||
button.highlight_content = config->colors[GUI_COLOR_BUTTON];
|
||||
}
|
||||
if (gui_widget_button_text(panel->out, &button, str, len, &panel->font, panel->in))
|
||||
if (gui_widget_button_text(panel->out, &button, str, &panel->font, panel->in))
|
||||
value = !value;
|
||||
return value;
|
||||
}
|
||||
@ -2202,7 +2182,7 @@ gui_panel_shelf_begin(struct gui_panel *panel, gui_shelf *shelf,
|
||||
button.y += config->item_padding.y;
|
||||
button.h -= config->item_padding.y;
|
||||
}
|
||||
if (gui_widget_button_text(panel->out, &button, tabs[i], strsiz(tabs[i]),
|
||||
if (gui_widget_button_text(panel->out, &button, tabs[i],
|
||||
&panel->font, panel->in)) active = i;
|
||||
}
|
||||
|
||||
|
13
gui.h
13
gui.h
@ -145,8 +145,8 @@ struct gui_command_circle {
|
||||
struct gui_command_bitmap {
|
||||
struct gui_command header;
|
||||
gui_texture texture;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
struct gui_rect src;
|
||||
struct gui_rect dst;
|
||||
};
|
||||
|
||||
struct gui_command_triangle {
|
||||
@ -206,8 +206,8 @@ struct gui_text {
|
||||
};
|
||||
|
||||
struct gui_image {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
struct gui_rect src;
|
||||
struct gui_rect dst;
|
||||
gui_float pad_x, pad_y;
|
||||
struct gui_color color;
|
||||
gui_texture texture;
|
||||
@ -425,12 +425,11 @@ void gui_widget_text(struct gui_command_buffer*, const struct gui_text*,
|
||||
const struct gui_font*);
|
||||
void gui_widget_image(struct gui_command_buffer*, const struct gui_image*);
|
||||
gui_bool gui_widget_button_text(struct gui_command_buffer*, const struct gui_button*,
|
||||
const char *text, gui_size len, const struct gui_font*,
|
||||
const struct gui_input*);
|
||||
const char *text, const struct gui_font*, const struct gui_input*);
|
||||
gui_bool gui_widget_button_triangle(struct gui_command_buffer*, struct gui_button*,
|
||||
enum gui_heading, const struct gui_input*);
|
||||
gui_bool gui_widget_button_icon(struct gui_command_buffer*, struct gui_button*,
|
||||
gui_texture, struct gui_rect *source, const struct gui_input*);
|
||||
gui_texture, const struct gui_rect *source, const struct gui_input*);
|
||||
gui_bool gui_widget_toggle(struct gui_command_buffer*, const struct gui_toggle*,
|
||||
gui_bool active, const struct gui_font*, const struct gui_input*);
|
||||
gui_float gui_widget_slider(struct gui_command_buffer*, const struct gui_slider*,
|
||||
|
Loading…
Reference in New Issue
Block a user