From 6df135829cbc1b11f6de4ac9a146d9ca9bed8e55 Mon Sep 17 00:00:00 2001 From: vurtun Date: Thu, 12 Mar 2015 22:53:28 +0100 Subject: [PATCH] cleanup --- Makefile | 2 +- gui.c | 305 +++++++++++++++++++++++++++++------------------------- gui.h | 62 +++++++---- mono.font | Bin 266492 -> 0 bytes opengl.c | 33 +++--- 5 files changed, 224 insertions(+), 178 deletions(-) delete mode 100644 mono.font diff --git a/Makefile b/Makefile index 482ef26..85a9f00 100644 --- a/Makefile +++ b/Makefile @@ -31,5 +31,5 @@ gcc: $(BIN) $(BIN): @mkdir -p bin rm -f bin/$(BIN) $(OBJS) - $(CC) $(SRC) -D_POSIX_C_SOURCE=200809L $(CFLAGS) -o bin/$(BIN) -lX11 -lGL -lGLU + $(CC) $(SRC) -D_POSIX_C_SOURCE=200809L $(CFLAGS) -o bin/$(BIN) -lX11 -lGL -lGLU -lm diff --git a/gui.c b/gui.c index 68a0cd3..9877641 100644 --- a/gui.c +++ b/gui.c @@ -15,7 +15,9 @@ #define ABS(a) (((a) < 0) ? -(a) : (a)) #define UNUSED(a) ((void)(a)) #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define INBOX(x, y, x0, y0, x1, y1) (BETWEEN(x, x0, x1) && BETWEEN(y, y0, y1)) +#define INBOX(px, py, x, y, w, h) (BETWEEN(px, x, x+w) && BETWEEN(py, y, y+h)) +#define ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) +#define ALIGN(x, mask) (void*)((unsigned long)((gui_byte*)(x) + (mask-1)) & ~(mask-1)) #define ASSERT_LINE(p, l, f) \ typedef char PASTE(assertion_failed_##f##_,l)[2*!!(p)-1]; @@ -42,8 +44,8 @@ fsqrt(float x) ASSERT(sizeof(int) == sizeof(float)); val.f = x; - val.i = 0x5f375a86 - (val.i>>1); - val.f = val.f*(1.5f-xhalf*val.f*val.f); + val.i = 0x5f375a86 - (val.i >> 1); + val.f = val.f * (1.5f - xhalf * val.f * val.f); return 1.0f/val.f; } @@ -150,7 +152,7 @@ gui_default_config(struct gui_config *config) config->global_alpha = 1.0f; config->scrollbar_width = 16; config->scroll_factor = 2; - config->panel_padding = gui_make_vec2(10.0f, 10.0f); + config->panel_padding = gui_make_vec2(15.0f, 10.0f); config->panel_min_size = gui_make_vec2(32.0f, 32.0f); config->item_spacing = gui_make_vec2(8.0f, 8.0f); config->item_padding = gui_make_vec2(4.0f, 4.0f); @@ -241,48 +243,57 @@ static gui_size gui_font_text_width(const struct gui_font *font, const gui_char *t, gui_size l) { gui_long unicode; - gui_size len = 0; - const struct gui_font_glyph *g; + gui_size text_width = 0; + const struct gui_font_glyph *glyph; gui_size text_len = 0; - gui_size ulen; + gui_size glyph_len; if (!t || !l) return 0; - ulen = utf_decode(t, &unicode, l); - while (text_len <= l && ulen) { + glyph_len = utf_decode(t, &unicode, l); + while (text_len <= l && glyph_len) { if (unicode == UTF_INVALID) return 0; - g = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback; - g = (g->code == 0) ? font->fallback : g; - len += (gui_size)(g->xadvance * font->scale); - ulen = utf_decode(t + text_len, &unicode, l - text_len); - text_len += ulen; + glyph = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback; + glyph = (glyph->code == 0) ? font->fallback : glyph; + text_width += (gui_size)(glyph->xadvance * font->scale); + glyph_len = utf_decode(t + text_len, &unicode, l - text_len); + text_len += glyph_len; } - return len; + return text_width; } void -gui_begin(struct gui_draw_buffer *buffer, gui_byte *memory, gui_size size) +gui_begin(struct gui_draw_buffer *buffer, void *memory, gui_size size) { - if (!buffer || !memory || !size) return; - buffer->begin = memory + size - sizeof(struct gui_draw_command); - buffer->vertexes = memory; - buffer->end = buffer->begin; - buffer->memory = memory; - buffer->size = size; - buffer->vertex_write = 0; - buffer->vertex_count = 0; - buffer->command_count = 0; + void *vertexes, *aligned; + gui_size cmd_siz, aligning; + static const gui_size align = ALIGNOF(struct gui_vertex); + if (!buffer || !memory || !size) + return; + + cmd_siz = size / 6; + vertexes = (gui_byte*)memory + cmd_siz; + aligned = ALIGN(vertexes, align); + aligning = (gui_size)((gui_byte*)aligned - (gui_byte*)vertexes); + buffer->command_capacity = cmd_siz / sizeof(struct gui_draw_command); + buffer->vertex_capacity = (size - cmd_siz - aligning) / sizeof(struct gui_vertex); + buffer->commands = memory; + buffer->vertexes = aligned; + buffer->command_size = 0; + buffer->vertex_size = 0; buffer->allocated = 0; + buffer->needed = 0; } gui_size gui_end(struct gui_draw_buffer *buffer) { - gui_size allocated; + gui_size needed; if (!buffer) return 0; - allocated = buffer->allocated; + needed = buffer->needed; buffer->allocated = 0; - buffer->vertex_count = 0; - return allocated; + buffer->command_capacity = 0; + buffer->vertex_capacity = 0; + return needed; } static gui_int @@ -294,41 +305,24 @@ gui_push(struct gui_draw_buffer *buffer, gui_size count, gui_size cmd_memory = 0; gui_size vertex_size; gui_size current; - struct gui_draw_command cmd; + struct gui_draw_command *cmd; + + buffer->needed += count * sizeof(struct gui_vertex); + buffer->needed += sizeof(struct gui_draw_command); if (!buffer || !rect) return gui_false; - if (!buffer->end || !buffer->begin || buffer->end > buffer->begin) + if (!buffer->commands || !buffer->command_capacity || + buffer->command_size >= buffer->command_capacity) return gui_false; - vertex_size = sizeof(struct gui_vertex) * (buffer->vertex_count + count); - if (buffer->vertexes + vertex_size >= buffer->end) + if (!buffer->vertexes || !buffer->vertex_capacity || + (buffer->vertex_size + count) >= buffer->vertex_capacity) return gui_false; - cmd.vertex_count = count; - cmd.clip_rect = *rect; - cmd.texture = tex; - memcopy(buffer->end, &cmd, sizeof(struct gui_draw_command)); - - buffer->end -= sizeof(struct gui_draw_command); - buffer->vertex_count += count; + cmd = &buffer->commands[buffer->command_size++]; + cmd->vertex_count = count; + cmd->clip_rect = *rect; + cmd->texture = tex; buffer->allocated += count * sizeof(struct gui_vertex); buffer->allocated += sizeof(struct gui_draw_command); - buffer->command_count++; - return gui_true; -} - -gui_int -gui_get_command(struct gui_draw_command *cmd, const struct gui_draw_buffer *buffer, - gui_size index) -{ - gui_byte *iter; - gui_size size = 0; - if (!buffer || !buffer->memory || !buffer->begin || !buffer->end || !buffer->size) - return gui_false; - if (!cmd || buffer->begin == buffer->end) - return gui_false; - if (index >= buffer->command_count) - return gui_false; - iter = buffer->begin - (index * sizeof(struct gui_draw_command)); - memcopy(cmd, iter, sizeof(struct gui_draw_command)); return gui_true; } @@ -336,22 +330,18 @@ static void gui_vertex(struct gui_draw_buffer *buffer, gui_float x, gui_float y, struct gui_color col, gui_float u, gui_float v) { - gui_size i; - gui_byte *dst; - struct gui_vertex vertex; + struct gui_vertex *vertex; if (!buffer) return; - i = buffer->vertex_write; - if (i >= buffer->vertex_count) return; + if (!buffer->vertexes || !buffer->vertex_capacity || + buffer->vertex_size >= buffer->vertex_capacity) + return; - vertex.pos.x = x; - vertex.pos.y = y; - vertex.color = col; - vertex.uv.u = u; - vertex.uv.v = v; - - dst = buffer->vertexes + i * sizeof(struct gui_vertex); - memcopy(dst, &vertex, sizeof(struct gui_vertex)); - buffer->vertex_write++; + vertex = &buffer->vertexes[buffer->vertex_size++]; + vertex->color = col; + vertex->pos.x = x; + vertex->pos.y = y; + vertex->uv.u = u; + vertex->uv.v = v; } static void @@ -505,8 +495,8 @@ gui_button(struct gui_draw_buffer *buffer, const struct gui_button *button, bg = button->background; hc = button->highlight; - if (INBOX(mouse_x, mouse_y, x, y, x+w, y+h)) { - if (INBOX(clicked_x, clicked_y, x, y, x+w, y+h)) + if (INBOX(mouse_x, mouse_y, x, y, w, h)) { + if (INBOX(clicked_x, clicked_y, x, y, w, h)) ret = (in->mouse_down && in->mouse_clicked); fc = bg; bg = hc; } @@ -570,9 +560,7 @@ gui_toggle(struct gui_draw_buffer *buffer, const struct gui_toggle *toggle, if (!in->mouse_down && in->mouse_clicked) { const gui_float clicked_x = in->mouse_clicked_pos.x; const gui_float clicked_y = in->mouse_clicked_pos.y; - const gui_float cursor_px = cursor_x + cursor_size; - const gui_float cursor_py = cursor_y + cursor_size; - if (INBOX(clicked_x, clicked_y, cursor_x, cursor_y, cursor_px, cursor_py)) + if (INBOX(clicked_x, clicked_y, cursor_x, cursor_y, cursor_size, cursor_size)) active = !active; } @@ -617,8 +605,8 @@ gui_slider(struct gui_draw_buffer *buffer, const struct gui_slider *slider, clicked_y = in->mouse_clicked_pos.y; if (in->mouse_down && - INBOX(clicked_x, clicked_y, x, y, x + w, y + h) && - INBOX(mouse_x, mouse_y, x, y, x + w, y + h)) + INBOX(clicked_x, clicked_y, x, y, w, h) && + INBOX(mouse_x, mouse_y, x, y, w, h)) { const float d = mouse_x - (cursor_x + cursor_w / 2.0f); const float pxstep = (w - 2 * slider->pad_x) / steps; @@ -653,7 +641,7 @@ gui_progress(struct gui_draw_buffer *buffer, const struct gui_progress *prog, h = MAX(prog->h, 2 * prog->pad_y + 1); value = MIN(prog->current, prog->max); - if (prog->modifyable && in->mouse_down && INBOX(mouse_x, mouse_y, x, y, x+w, y+h)) { + if (prog->modifyable && in->mouse_down && INBOX(mouse_x, mouse_y, x, y, w, h)) { gui_float ratio = (gui_float)(mouse_x - x) / (gui_float)w; value = (gui_size)((gui_float)prog->max * ratio); } @@ -671,7 +659,8 @@ gui_progress(struct gui_draw_buffer *buffer, const struct gui_progress *prog, } gui_int -gui_input(struct gui_draw_buffer *buffer, const struct gui_input_field *input, +gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, + const struct gui_input_field *input, const struct gui_font *font, const struct gui_input *in) { gui_size offset = 0; @@ -679,7 +668,6 @@ gui_input(struct gui_draw_buffer *buffer, const struct gui_input_field *input, gui_float label_w, label_h; gui_float x, y, w, h; gui_int active; - const gui_char *t; gui_float mouse_x, mouse_y; gui_size text_width; @@ -692,49 +680,48 @@ gui_input(struct gui_draw_buffer *buffer, const struct gui_input_field *input, w = MAX(input->w, 2 * input->pad_x); h = MAX(input->h, font->height); active = input->active; - t = input->buffer; if (in->mouse_clicked && in->mouse_down) - active = INBOX(mouse_x, mouse_y, x, y, x + w, y + h); + active = INBOX(mouse_x, mouse_y, x, y, w, h); if (active) { const struct gui_key *del = &in->keys[GUI_KEY_DEL]; const struct gui_key *bs = &in->keys[GUI_KEY_BACKSPACE]; const struct gui_key *enter = &in->keys[GUI_KEY_ENTER]; const struct gui_key *esc = &in->keys[GUI_KEY_ESCAPE]; const struct gui_key *space = &in->keys[GUI_KEY_SPACE]; - if (in->text_len && *input->length < input->max) { + if (in->text_len && *length < input->max) { gui_long unicode; gui_size i = 0, l = 0; gui_size ulen = utf_decode(in->text, &unicode, in->text_len); - while (ulen && (l + ulen) <= in->text_len && *input->length < input->max) { + while (ulen && (l + ulen) <= in->text_len && *length < input->max) { for (i = 0; i < ulen; i++) - input->buffer[(*input->length)++] = in->text[l + i]; + buffer[(*length)++] = in->text[l + i]; l = l + ulen; ulen = utf_decode(in->text + l, &unicode, in->text_len - l); } } if ((del->down && del->clicked) || (bs->down && bs->clicked)) - if (*input->length > 0) *input->length = *input->length - 1; + if (*length > 0) *length = *length - 1; if ((enter->down && enter->clicked) || (esc->down && esc->clicked)) active = gui_false; - if ((space->down && space->clicked) && (*input->length < input->max)) - input->buffer[(*input->length)++] = ' '; + if ((space->down && space->clicked) && (*length < input->max)) + buffer[(*length)++] = ' '; } label_x = x + input->pad_x; label_y = y + input->pad_y; label_w = w - 2 * input->pad_x; label_h = h - 2 * input->pad_y; - text_width = gui_font_text_width(font, t, *input->length); + text_width = gui_font_text_width(font, buffer, *length); while (text_width > label_w) { offset += 1; - text_width = gui_font_text_width(font, &t[offset], *input->length - offset); + text_width = gui_font_text_width(font, &buffer[offset], *length - offset); } - gui_rectf(buffer, x, y, w, h, input->background); - gui_rect(buffer, x + 1, y, w - 1, h, input->foreground); - gui_string(buffer, font, label_x, label_y, label_w, label_h, input->font, - &t[offset], *input->length); + gui_rectf(buf, x, y, w, h, input->background); + gui_rect(buf, x + 1, y, w - 1, h, input->foreground); + gui_string(buf, font, label_x, label_y, label_w, label_h, input->font, + &buffer[offset], *length); return active; } @@ -785,10 +772,11 @@ gui_plot(struct gui_draw_buffer *buffer, const struct gui_plot *plot, ratio = (plot->values[0] - min) / range; last_x = canvas_x; last_y = (canvas_y + canvas_h) - ratio * (gui_float)canvas_h; - if (INBOX(mouse_x, mouse_y, last_x-3, last_y-3, last_x + 3, last_y + 3)) { + if (INBOX(mouse_x, mouse_y, last_x-3, last_y-3, 6, 6)) { selected = (in->mouse_down && in->mouse_clicked) ? (gui_int)i : -1; col = plot->highlight; } + gui_rectf(buffer, last_x - 3, last_y - 3, 6, 6, col); for (i = 1; i < plot->value_count; i++) { gui_float cur_x, cur_y; @@ -796,7 +784,7 @@ gui_plot(struct gui_draw_buffer *buffer, const struct gui_plot *plot, cur_x = canvas_x + (gui_float)(step * i); cur_y = (canvas_y + canvas_h) - (ratio * (gui_float)canvas_h); gui_line(buffer, last_x, last_y, cur_x, cur_y, plot->foreground); - if (INBOX(mouse_x, mouse_y, cur_x-3, cur_y-3, cur_x + 3, cur_y + 3)) { + if (INBOX(mouse_x, mouse_y, cur_x-3, cur_y-3, 6, 6)) { selected = (in->mouse_down && in->mouse_clicked) ? (gui_int)i : -1; col = plot->highlight; } else col = plot->foreground; @@ -852,7 +840,7 @@ gui_histo(struct gui_draw_buffer *buffer, const struct gui_histo *histo, const gui_float item_x = canvas_x + (j * item_w) + (j * histo->pad_y); const gui_float item_y = (canvas_y + canvas_h) - item_h; struct gui_color col = (histo->values[i] < 0) ? nc: fg; - if (INBOX(mouse_x, mouse_y, item_x, item_y, item_x + item_w, item_y + item_h)) { + if (INBOX(mouse_x, mouse_y, item_x, item_y, item_w, item_h)) { selected = (in->mouse_down && in->mouse_clicked) ? (gui_int)i : -1; col = histo->highlight; } @@ -934,7 +922,6 @@ gui_scroll(struct gui_draw_buffer *buffer, const struct gui_scroll *scroll, down.text = NULL, down.length = 0; down.font = fg, down.background = fg; down.foreground = bg, down.highlight = fg; - u = gui_button(buffer, &up, NULL, in); d = gui_button(buffer, &down, NULL, in); @@ -944,15 +931,11 @@ gui_scroll(struct gui_draw_buffer *buffer, const struct gui_scroll *scroll, xoff = x + (button_size - pad); yoff = y + (button_size - pad); boff = button_y + (button_size - pad); - gui_trianglef(buffer, xmid, y + pad, xoff, yoff, xpad, yoff, scroll->background); gui_trianglef(buffer, xpad, ypad, xoff, ypad, xmid, boff, scroll->background); - cursor_px = cursor_x + cursor_w; - cursor_py = cursor_y + cursor_h; - inscroll = INBOX(mouse_x, mouse_y, x, y, x + w, y + h); - incursor = INBOX(prev_x, prev_y, cursor_x, cursor_y, cursor_px, cursor_py); - + inscroll = INBOX(mouse_x, mouse_y, x, y, w, h); + incursor = INBOX(prev_x, prev_y, cursor_x, cursor_y, cursor_w, cursor_h); if (in->mouse_down && inscroll && incursor) { const gui_float pixel = in->mouse_delta.y; const gui_float delta = (pixel / (gui_float)bar_h) * (gui_float)target; @@ -997,6 +980,7 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out, gui_size text_len = 0; gui_float header_height = 0; gui_float label_x, label_y, label_w, label_h; + const struct gui_config *config = panel->config; const struct gui_color *header = &config->colors[GUI_COLOR_TITLEBAR]; const gui_float mouse_x = panel->in->mouse_pos.x; @@ -1021,35 +1005,43 @@ gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *out, panel->height = h; if (panel->flags & GUI_PANEL_CLOSEABLE) { - const gui_char *X = (gui_char*)"X"; - gui_size text_width = gui_font_text_width(panel->font, X, 1); + gui_size text_width; gui_float close_x, close_y, close_w, close_h; - close_x = (x + w) - (text_width + config->panel_padding.x); + const gui_char *X = (const gui_char*)"x"; + + text_width = gui_font_text_width(panel->font, X, 1); + close_x = (x + w) - ((gui_float)text_width + config->panel_padding.x); close_y = y + config->panel_padding.y; - close_w = text_width + config->panel_padding.x; + close_w = (gui_float)text_width + config->panel_padding.x; close_h = panel->font->height + 2 * config->item_padding.y; - w -= (text_width + config->panel_padding.x); + w -= ((gui_float)text_width + config->panel_padding.x); + gui_string(panel->out, panel->font, close_x, close_y, close_w, close_h, config->colors[GUI_COLOR_TEXT], X, 1); - if (INBOX(mouse_x, mouse_y, close_x, close_y, close_x+close_w, close_y+close_h)) { - if (INBOX(clicked_x, clicked_y, close_x, close_y, close_x+close_w, close_y+close_h)) + if (INBOX(mouse_x, mouse_y, close_x, close_y, close_w, close_h)) { + if (INBOX(clicked_x, clicked_y, close_x, close_y, close_w, close_h)) ret = !(panel->in->mouse_down && panel->in->mouse_clicked); } } if (panel->flags & GUI_PANEL_MINIMIZABLE) { - const gui_char *score = (gui_char*)"-"; + gui_size text_width; gui_float min_x, min_y, min_w, min_h; - gui_size text_width = gui_font_text_width(panel->font, score, 1); - min_x = (x + w) - (text_width + config->item_padding.y); + const gui_char *score = (panel->minimized) ? + (const gui_char*)"+": + (const gui_char*)"-"; + + text_width = gui_font_text_width(panel->font, score, 1); + min_x = (x + w) - ((gui_float)text_width + config->item_padding.y); min_y = y + config->panel_padding.y; - min_w = text_width; + min_w = (gui_float)text_width; min_h = panel->font->height + 2 * config->item_padding.y; - w -= text_width; + w -= (gui_float)text_width; + gui_string(panel->out, panel->font, min_x, min_y, min_w, min_h, config->colors[GUI_COLOR_TEXT], score, 1); - if (INBOX(mouse_x, mouse_y, min_x, min_y, min_x+min_w, min_y+min_h)) { - if (INBOX(clicked_x, clicked_y, min_x, min_y, min_x+min_w, min_y+min_h)) + if (INBOX(mouse_x, mouse_y, min_x, min_y, min_w, min_h)) { + if (INBOX(clicked_x, clicked_y, min_x, min_y, min_w, min_h)) if (panel->in->mouse_down && panel->in->mouse_clicked) panel->minimized = !panel->minimized; } @@ -1080,8 +1072,20 @@ gui_panel_row(struct gui_panel *panel, gui_float height, gui_size cols) height + config->panel_padding.y, *color); } +void +gui_panel_seperator(struct gui_panel *panel, gui_size cols) +{ + const struct gui_config *config; + if (!panel) return; + config = panel->config; + cols = MIN(cols, panel->row_columns - panel->index); + panel->index += cols; + if (panel->index >= panel->row_columns) + gui_panel_row(panel, panel->row_height - config->item_spacing.y, panel->row_columns); +} + static void -gui_panel_alloc(struct gui_rect *bounds, struct gui_panel *panel) +gui_panel_alloc_space(struct gui_rect *bounds, struct gui_panel *panel) { const struct gui_config *config = panel->config; gui_float padding, spacing, space; @@ -1109,9 +1113,12 @@ gui_panel_button(struct gui_panel *panel, const char *str, gui_size len) { struct gui_rect bounds; struct gui_button button; - const struct gui_config *config = panel->config; - if (panel->minimized) return 0; - gui_panel_alloc(&bounds, panel); + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return 0; + if (!panel->font || panel->minimized) return 0; + gui_panel_alloc_space(&bounds, panel); + config = panel->config; button.text = str; button.length = len; @@ -1134,9 +1141,12 @@ gui_panel_toggle(struct gui_panel *panel, const char *text, gui_size length, { struct gui_rect bounds; struct gui_toggle toggle; - const struct gui_config *config = panel->config; - if (panel->minimized) return is_active; - gui_panel_alloc(&bounds, panel); + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return is_active; + if (!panel->font || panel->minimized) return is_active; + gui_panel_alloc_space(&bounds, panel); + config = panel->config; toggle.x = bounds.x; toggle.y = bounds.y; @@ -1159,9 +1169,12 @@ gui_panel_slider(struct gui_panel *panel, gui_float min_value, gui_float value, { struct gui_rect bounds; struct gui_slider slider; - const struct gui_config *config = panel->config; + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return value; if (panel->minimized) return value; - gui_panel_alloc(&bounds, panel); + gui_panel_alloc_space(&bounds, panel); + config = panel->config; slider.x = bounds.x; slider.y = bounds.y; @@ -1184,9 +1197,12 @@ gui_panel_progress(struct gui_panel *panel, gui_size cur_value, gui_size max_val { struct gui_rect bounds; struct gui_progress prog; - const struct gui_config *config = panel->config; + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return cur_value; if (panel->minimized) return cur_value; - gui_panel_alloc(&bounds, panel); + gui_panel_alloc_space(&bounds, panel); + config = panel->config; prog.x = bounds.x; prog.y = bounds.y; @@ -1208,9 +1224,12 @@ gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *length, { struct gui_rect bounds; struct gui_input_field field; - const struct gui_config *config = panel->config; - if (panel->minimized) return gui_false; - gui_panel_alloc(&bounds, panel); + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return is_active; + if (!panel->font || panel->minimized) return is_active; + gui_panel_alloc_space(&bounds, panel); + config = panel->config; field.x = bounds.x; field.y = bounds.y; @@ -1218,14 +1237,12 @@ gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *length, field.h = bounds.h; field.pad_x = config->item_padding.x; field.pad_y = config->item_padding.y; - field.buffer = buffer; - field.length = length; field.max = max_length; field.active = is_active; field.font = config->colors[GUI_COLOR_TEXT]; field.background = config->colors[GUI_COLOR_INPUT]; field.foreground = config->colors[GUI_COLOR_INPUT_BORDER]; - return gui_input(panel->out, &field, panel->font, panel->in); + return gui_input(panel->out, buffer, length, &field, panel->font, panel->in); } gui_int @@ -1233,9 +1250,12 @@ gui_panel_plot(struct gui_panel *panel, const gui_float *values, gui_size count) { struct gui_rect bounds; struct gui_plot plot; - const struct gui_config *config = panel->config; + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return -1; if (panel->minimized) return -1; - gui_panel_alloc(&bounds, panel); + gui_panel_alloc_space(&bounds, panel); + config = panel->config; plot.x = bounds.x; plot.y = bounds.y; @@ -1256,9 +1276,12 @@ gui_panel_histo(struct gui_panel *panel, const gui_float *values, gui_size count { struct gui_rect bounds; struct gui_histo histo; - const struct gui_config *config = panel->config; + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return -1; if (panel->minimized) return -1; - gui_panel_alloc(&bounds, panel); + gui_panel_alloc_space(&bounds, panel); + config = panel->config; histo.x = bounds.x; histo.y = bounds.y; diff --git a/gui.h b/gui.h index 4623885..03fb1de 100644 --- a/gui.h +++ b/gui.h @@ -8,8 +8,19 @@ /* * ------------- TODO-List ------------ + * - cleanup + * - widgets + * o Text + * o Text Wrapped + * o Image + * o Counter + * o Image Button * - panel - * o flags + * o Moveable + * o Scaleable + * o Scrollbar + * o Tabs + * o Icon * o combobox * o listView * o treeView @@ -34,6 +45,7 @@ typedef gui_char gui_glyph[GUI_UTF_SIZE]; enum {gui_false, gui_true}; struct gui_color {gui_byte r,g,b,a;}; +struct gui_colorf {gui_float r,g,b,a;}; struct gui_texCoord {gui_float u,v;}; struct gui_vec2 {gui_float x,y;}; struct gui_rect {gui_float x,y,w,h;}; @@ -52,15 +64,14 @@ struct gui_draw_command { }; struct gui_draw_buffer { - gui_byte *vertexes; - gui_byte *begin; - gui_byte *end; - gui_byte *memory; - gui_size size; - gui_size vertex_write; - gui_size vertex_count; - gui_size command_count; + struct gui_vertex *vertexes; + gui_size vertex_capacity; + gui_size vertex_size; + struct gui_draw_command *commands; + gui_size command_capacity; + gui_size command_size; gui_size allocated; + gui_size needed; }; enum gui_keys { @@ -104,6 +115,17 @@ struct gui_font { const struct gui_font_glyph *fallback; }; +struct gui_text { + gui_float x, y; + gui_float w, h; + gui_float pad_x, pad_y; + const char *text; + gui_size length; + struct gui_color font; + struct gui_color background; + struct gui_color foreground; +}; + struct gui_button { gui_float x, y; gui_float w, h; @@ -164,8 +186,6 @@ struct gui_input_field { gui_float x, y; gui_float w, h; gui_float pad_x, pad_y; - gui_char *buffer; - gui_size *length; gui_size max; gui_bool active; struct gui_color background; @@ -237,9 +257,9 @@ struct gui_config { }; enum gui_panel_flags { - GUI_PANEL_MINIMIZABLE = 0x04, - GUI_PANEL_CLOSEABLE = 0x08, - GUI_PANEL_SCROLLBAR = 0x20 + GUI_PANEL_MINIMIZABLE = 0x01, + GUI_PANEL_CLOSEABLE = 0x02, + GUI_PANEL_SCROLLBAR = 0x04 }; struct gui_panel { @@ -271,12 +291,14 @@ void gui_input_char(struct gui_input *in, gui_glyph glyph); void gui_input_end(struct gui_input *in); /* Output */ -void gui_begin(struct gui_draw_buffer *buf, gui_byte *memory, gui_size size); +void gui_begin(struct gui_draw_buffer *buf, void *memory, gui_size size); gui_size gui_end(struct gui_draw_buffer *buf); -gui_int gui_get_command(struct gui_draw_command *cmd, - const struct gui_draw_buffer *buf, gui_size index); /* Widgets */ +void gui_text(struct gui_draw_buffer *buf, const struct gui_text *text, + const struct gui_font *font); +void gui_text_wrap(struct gui_draw_buffer *buf, const struct gui_text *text, + const struct gui_font *font); gui_int gui_button(struct gui_draw_buffer *buf, const struct gui_button *button, const struct gui_font *font, const struct gui_input *in); gui_int gui_toggle(struct gui_draw_buffer *buf, const struct gui_toggle *toggle, @@ -287,7 +309,8 @@ gui_size gui_progress(struct gui_draw_buffer *buf, const struct gui_progress *pr const struct gui_input *in); gui_size gui_scroll(struct gui_draw_buffer *buf, const struct gui_scroll *scroll, const struct gui_input *in); -gui_int gui_input(struct gui_draw_buffer *buf, const struct gui_input_field *f, +gui_int gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, + const struct gui_input_field *input, const struct gui_font *font, const struct gui_input *in); gui_int gui_histo(struct gui_draw_buffer *buf, const struct gui_histo *histo, const struct gui_input *in); @@ -301,7 +324,8 @@ gui_int gui_panel_begin(struct gui_panel *panel, struct gui_draw_buffer *q, const char *t, gui_flags f, gui_float x, gui_float y, gui_float w, gui_float h); void gui_panel_row(struct gui_panel *panel, gui_float height, gui_size cols); -void gui_panel_space(struct gui_panel *panel, gui_int cols); +void gui_panel_seperator(struct gui_panel *panel, gui_size cols); +void gui_panel_text(struct gui_panel *panel, const char *str, gui_size len); gui_int gui_panel_button(struct gui_panel *panel, const char *str, gui_size len); gui_int gui_panel_toggle(struct gui_panel *panel, const char *str, gui_size len, gui_int active); diff --git a/mono.font b/mono.font deleted file mode 100644 index 2b7b08be44a809a8321fe378f906b4cb44eff524..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 266492 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 - glVertexPointer(2, GL_FLOAT, (GLsizei)v, (void*)(vertexes + p)); - glTexCoordPointer(2, GL_FLOAT, (GLsizei)v, (void*)(vertexes + t)); - glColorPointer(4, GL_UNSIGNED_BYTE, (GLsizei)v, (void*)(vertexes + c)); + vertexes = (const gui_char*)buffer->vertexes; + glVertexPointer(2, GL_FLOAT, (GLsizei)v, (const void*)(vertexes + p)); + glTexCoordPointer(2, GL_FLOAT, (GLsizei)v, (const void*)(vertexes + t)); + glColorPointer(4, GL_UNSIGNED_BYTE, (GLsizei)v, (const void*)(vertexes + c)); - for (i = 0; i < buffer->command_count; ++i) { - gui_get_command(&cmd, buffer, i); - const int x = (int)cmd.clip_rect.x; - const int y = height - (int)(cmd.clip_rect.y + cmd.clip_rect.h); - const int w = (int)cmd.clip_rect.w; - const int h = (int)cmd.clip_rect.h; + for (i = 0; i < buffer->command_size; ++i) { + cmd = &buffer->commands[i]; + const int x = (int)cmd->clip_rect.x; + const int y = height - (int)(cmd->clip_rect.y + cmd->clip_rect.h); + const int w = (int)cmd->clip_rect.w; + const int h = (int)cmd->clip_rect.h; glScissor(x, y, w, h); - glBindTexture(GL_TEXTURE_2D, (GLuint)(unsigned long)cmd.texture); - glDrawArrays(GL_TRIANGLES, offset, (GLsizei)cmd.vertex_count); - offset += (GLint)cmd.vertex_count; + glBindTexture(GL_TEXTURE_2D, (GLuint)(unsigned long)cmd->texture); + glDrawArrays(GL_TRIANGLES, offset, (GLsizei)cmd->vertex_count); + offset += (GLint)cmd->vertex_count; } glDisableClientState(GL_COLOR_ARRAY); @@ -422,7 +422,6 @@ main(int argc, char *argv[]) struct GUI gui; long dt, started; gui_byte *buffer; - const gui_size buffer_size = MAX_BUFFER; static GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE,24, GLX_DOUBLEBUFFER, None}; gui_char input_text[INPUT_MAX]; @@ -462,7 +461,7 @@ main(int argc, char *argv[]) /* OpenGL */ xw.glc = glXCreateContext(xw.dpy, xw.vi, NULL, GL_TRUE); glXMakeCurrent(xw.dpy, xw.win, xw.glc); - buffer = xcalloc(buffer_size, 1); + buffer = xcalloc(MAX_BUFFER, 1); /* GUI */ gui.win = &xw;