diff --git a/demo/demo.c b/demo/demo.c index d960088..bbbcd24 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -569,6 +569,8 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * static zr_size prog_value = 40; static zr_float float_spinner = 2.5f; static zr_int int_spinner = 20; + static zr_float drag_float = 2; + static zr_int drag_int = 10; static zr_state spinneri_active, spinnerf_active; static const zr_float ratio[] = {100, 150}; const struct zr_input *in = zr_input(&layout); @@ -589,12 +591,17 @@ show_test_window(struct zr_window *window, struct zr_style *config, enum theme * zr_tooltip(&layout, "This is a tooltip"); zr_layout_row(&layout, ZR_STATIC, 30, 2, ratio); - zr_labelf(&layout, ZR_TEXT_LEFT, "Slider(%d):", int_slider); + zr_labelf(&layout, ZR_TEXT_LEFT, "Slider int: %d", int_slider); zr_slider_int(&layout, 0, &int_slider, 10, 1); - zr_labelf(&layout, ZR_TEXT_LEFT, "Slider(%.2f):", float_slider); + zr_labelf(&layout, ZR_TEXT_LEFT, "Slider float: %.2f", float_slider); zr_slider_float(&layout, 0, &float_slider, 5.0, 0.5f); zr_labelf(&layout, ZR_TEXT_LEFT, "Progressbar: %lu:" , prog_value); zr_progress(&layout, &prog_value, 100, ZR_MODIFYABLE); + zr_label(&layout, "Drag float:", ZR_TEXT_LEFT); + zr_drag_float(&layout, 0, &drag_float, 64.0f, 0.1f); + zr_label(&layout, "Drag int:", ZR_TEXT_LEFT); + zr_drag_int(&layout, 0, &drag_int, 100, 1); + zr_label(&layout, "Spinner int:", ZR_TEXT_LEFT); zr_spinner_int(&layout, 0, &int_spinner, 50.0, 1, &spinneri_active); zr_label(&layout, "Spinner float:", ZR_TEXT_LEFT); @@ -1117,6 +1124,9 @@ init_demo(struct demo *gui) gui->config_white.colors[ZR_COLOR_PROGRESS_CURSOR] = zr_rgba(80, 80, 80, 255); gui->config_white.colors[ZR_COLOR_PROGRESS_CURSOR_HOVER] = zr_rgba(70, 70, 70, 255); gui->config_white.colors[ZR_COLOR_PROGRESS_CURSOR_ACTIVE] = zr_rgba(60, 60, 60, 255); + gui->config_white.colors[ZR_COLOR_DRAG] = zr_rgba(150, 150, 150, 255); + gui->config_white.colors[ZR_COLOR_DRAG_HOVER] = zr_rgba(160, 160, 160, 255); + gui->config_white.colors[ZR_COLOR_DRAG_ACTIVE] = zr_rgba(165, 165, 165, 255); gui->config_white.colors[ZR_COLOR_INPUT] = zr_rgba(150, 150, 150, 255); gui->config_white.colors[ZR_COLOR_INPUT_CURSOR] = zr_rgba(0, 0, 0, 255); gui->config_white.colors[ZR_COLOR_INPUT_TEXT] = zr_rgba(0, 0, 0, 255); diff --git a/zahnrad.c b/zahnrad.c index 2fd17f3..307037e 100644 --- a/zahnrad.c +++ b/zahnrad.c @@ -789,6 +789,27 @@ zr_triangle_from_direction(struct zr_vec2 *result, struct zr_rect r, result[2] = zr_vec2(r.x + r.w, r.y + r.h); } } + +static zr_size +zr_string_float_limit(char *string, zr_int prec) +{ + zr_int dot = 0; + char *c = string; + while (*c) { + if (*c == '.') { + dot = 1; + c++; + continue; + } + if (dot == (prec+1)) { + *c = 0; + break; + } + if (dot > 0) dot++; + c++; + } + return (zr_size)(c - string); +} /* * ============================================================== * @@ -4489,6 +4510,78 @@ zr_widget_slider(struct zr_command_buffer *out, struct zr_rect slider, return slider_value; } +zr_float +zr_widget_drag(struct zr_command_buffer *out, struct zr_rect drag, + zr_float min, zr_float val, zr_float max, + zr_float inc_per_pixel, const struct zr_drag *d, + const struct zr_input *in, const struct zr_user_font *f) +{ + struct zr_text t; + struct zr_color col; + struct zr_color background; + + zr_float drag_range; + zr_float drag_min, drag_max; + zr_float drag_value, drag_steps; + zr_float cursor_offset; + char string[ZR_MAX_NUMBER_BUFFER]; + zr_size len; + + zr_bool left_mouse_down; + zr_bool left_mouse_click_in_cursor; + + ZR_ASSERT(d); + ZR_ASSERT(out); + ZR_ASSERT(f); + if (!out || !d) + return 0; + + /* make sure the provided values are correct */ + drag.x = drag.x + d->padding.x; + drag.y = drag.y + d->padding.y; + drag.h = MAX(drag.h, 2 * d->padding.y); + drag.w = MAX(drag.w, 1 + drag.h + 2 * d->padding.x); + drag.h -= 2 * d->padding.y; + drag.w -= 2 * d->padding.y; + drag_max = MAX(min, max); + drag_min = MIN(min, max); + drag_value = CLAMP(drag_min, val, drag_max); + + /* update value user input */ + left_mouse_down = in && in->mouse.buttons[ZR_BUTTON_LEFT].down; + left_mouse_click_in_cursor = in && zr_input_has_mouse_click_down_in_rect(in, + ZR_BUTTON_LEFT, drag, zr_true); + + t.text = d->text; + background = d->normal; + if (zr_input_is_mouse_hovering_rect(in, drag)) + background = d->hover; + + if (left_mouse_down && left_mouse_click_in_cursor) { + zr_float delta, pixels; + background = d->active; + t.text = d->text_active; + + pixels = in->mouse.delta.x; + delta = pixels * inc_per_pixel; + drag_value += delta; + drag_value = CLAMP(drag_min, drag_value, drag_max); + } + + /* draw border + background */ + zr_command_buffer_push_rect(out, drag, d->rounding, d->border); + drag = zr_shrink_rect(drag, d->border_width); + zr_command_buffer_push_rect(out, drag, d->rounding, background); + + /* draw value as text */ + t.background = background; + t.padding = zr_vec2(0,0); + len = zr_dtos(string, drag_value); + len = zr_string_float_limit(string, ZR_MAX_FLOAT_PRECISION); + zr_widget_text(out, drag, string, len, &t, ZR_TEXT_CENTERED, f); + return drag_value; +} + zr_size zr_widget_progress(struct zr_command_buffer *out, struct zr_rect r, zr_size value, zr_size max, zr_bool modifyable, @@ -5034,7 +5127,6 @@ zr_widget_spinner_base(struct zr_command_buffer *out, struct zr_rect r, return ret; } - zr_int zr_widget_spinner_int(struct zr_command_buffer *out, struct zr_rect r, const struct zr_spinner *s, zr_int min, zr_int value, @@ -5069,27 +5161,6 @@ zr_widget_spinner_int(struct zr_command_buffer *out, struct zr_rect r, return value; } -static zr_size -zr_string_float_limit(char *string, zr_int prec) -{ - zr_int dot = 0; - char *c = string; - while (*c) { - if (*c == '.') { - dot = 1; - c++; - continue; - } - if (dot == (prec+1)) { - *c = 0; - break; - } - if (dot > 0) dot++; - c++; - } - return (zr_size)(c - string); -} - zr_float zr_widget_spinner_float(struct zr_command_buffer *out, struct zr_rect r, const struct zr_spinner *s, zr_float min, zr_float value, zr_float max, @@ -5177,6 +5248,9 @@ zr_widget_spinner_float(struct zr_command_buffer *out, struct zr_rect r, COLOR(PROGRESS_CURSOR, 100, 100, 100, 255)\ COLOR(PROGRESS_CURSOR_HOVER, 120, 120, 120, 255)\ COLOR(PROGRESS_CURSOR_ACTIVE, 150, 150, 150, 255)\ + COLOR(DRAG, 38, 38, 38, 255)\ + COLOR(DRAG_HOVER, 50, 50, 50, 255)\ + COLOR(DRAG_ACTIVE, 60, 60, 60, 255)\ COLOR(INPUT, 45, 45, 45, 255)\ COLOR(INPUT_CURSOR, 100, 100, 100, 255)\ COLOR(INPUT_TEXT, 135, 135, 135, 255)\ @@ -7286,6 +7360,46 @@ zr_slider_int(struct zr_context *layout, zr_int min_value, zr_int *value, *value = (zr_int)val; } +void +zr_drag_float(struct zr_context *layout, zr_float min, zr_float *val, + zr_float max, zr_float inc_per_pixel) +{ + struct zr_rect bounds; + struct zr_drag drag; + const struct zr_style *config; + struct zr_vec2 item_padding; + + const struct zr_input *i; + enum zr_widget_state state; + state = zr_widget(&bounds, layout); + if (!state) return; + i = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : layout->input; + + config = layout->style; + item_padding = zr_style_property(config, ZR_PROPERTY_ITEM_PADDING); + + drag.padding.x = item_padding.x; + drag.padding.y = item_padding.y; + drag.border = config->colors[ZR_COLOR_BORDER]; + drag.normal = config->colors[ZR_COLOR_DRAG]; + drag.hover = config->colors[ZR_COLOR_DRAG_HOVER]; + drag.active = config->colors[ZR_COLOR_DRAG_ACTIVE]; + drag.text = config->colors[ZR_COLOR_TEXT]; + drag.text_active = config->colors[ZR_COLOR_TEXT_ACTIVE]; + drag.rounding = config->rounding[ZR_ROUNDING_SLIDER]; + *val = zr_widget_drag(layout->buffer, bounds, min, *val, max, + inc_per_pixel, &drag, i, &config->font); +} + +void zr_drag_int(struct zr_context *layout, zr_int min, zr_int *val, + zr_int max, zr_int inc_per_pixel) +{ + zr_float value = (zr_float)*val; + zr_drag_float(layout, (zr_float)min, &value, + (zr_float)max, (zr_float)inc_per_pixel); + *val = (zr_int)value; +} + void zr_progress(struct zr_context *layout, zr_size *cur_value, zr_size max_value, zr_bool is_modifyable) diff --git a/zahnrad.h b/zahnrad.h index 2277d91..688d56c 100644 --- a/zahnrad.h +++ b/zahnrad.h @@ -1800,8 +1800,6 @@ zr_size zr_edit_box_len(struct zr_edit_box*); zr_widget_edit_filtered -- Editbox with utf8 gylph filter capabilities zr_widget_spinner_int -- integer spinner widget zr_widget_spinner_float -- float spinner widget - zr_widget_drag_int -- integer dragging widget - zr_widget_drag_float -- float dragging widget zr_widget_scrollbarv -- vertical scrollbar widget imeplementation zr_widget_scrollbarh -- horizontal scrollbar widget imeplementation */ @@ -1950,6 +1948,27 @@ struct zr_slider { /* slider rounding */ }; +struct zr_drag { + struct zr_vec2 padding; + /* padding between bounds and content */ + struct zr_color border; + /* dragging widget cursor border color */ + struct zr_color normal; + /* dragging widget cursor color */ + struct zr_color hover; + /* dragging widget cursor color */ + struct zr_color active; + /* dragging widget cursor color */ + struct zr_color text; + /* dragging widget text color */ + struct zr_color text_active; + /* dragging widget active widget text color */ + zr_float rounding; + /* dragging widget rounding */ + zr_float border_width; + /* dragging widget border width */ +}; + struct zr_scrollbar { zr_float rounding; /* scrollbar rectangle rounding */ @@ -2170,6 +2189,23 @@ zr_float zr_widget_slider(struct zr_command_buffer*, struct zr_rect, Output: - returns the from the user input updated value */ +zr_float zr_widget_drag(struct zr_command_buffer*, struct zr_rect, + zr_float min, zr_float val, zr_float max, + zr_float inc_per_pixel, const struct zr_drag*, + const struct zr_input*, const struct zr_user_font*); +/* this function executes a dragging widget + Input: + - output command buffer for drawing + - bounds of the slider + - minimal draging value that will not be underflown + - dragging value to be updated by the user + - maximal draggin value that will not be overflown + - incrementing value per dragged pixel + - visual style structure describing the dragging widget + - input structure to update the dragging widget with + Output: + - returns the from the user input updated value +*/ zr_size zr_widget_progress(struct zr_command_buffer*, struct zr_rect, zr_size value, zr_size max, zr_bool modifyable, const struct zr_progress*, const struct zr_input*); @@ -2374,6 +2410,9 @@ enum zr_style_colors { ZR_COLOR_PROGRESS_CURSOR, ZR_COLOR_PROGRESS_CURSOR_HOVER, ZR_COLOR_PROGRESS_CURSOR_ACTIVE, + ZR_COLOR_DRAG, + ZR_COLOR_DRAG_HOVER, + ZR_COLOR_DRAG_ACTIVE, ZR_COLOR_INPUT, ZR_COLOR_INPUT_CURSOR, ZR_COLOR_INPUT_TEXT, @@ -2404,6 +2443,7 @@ enum zr_style_rounding { ZR_ROUNDING_BUTTON, ZR_ROUNDING_SLIDER, ZR_ROUNDING_PROGRESS, + ZR_ROUNDING_DRAG, ZR_ROUNDING_CHECK, ZR_ROUNDING_INPUT, ZR_ROUNDING_GRAPH, @@ -3379,6 +3419,31 @@ void zr_slider_int(struct zr_context*, zr_int min, zr_int *val, zr_int max, Output: - the from user input updated slider value */ + +void zr_drag_float(struct zr_context*, zr_float min, zr_float *val, + zr_float max, zr_float inc_per_pixel); +/* this function executes a dragable float widget + Input: + - minimal dragging value that will not be underflown + - slider dragging which shall be updated + - maximal dragging value that will not be overflown + - value increment per dragged pixel delta + - dragging axis with either ZR_AXIS_X or ZR_AXIS_Y + Output: + - returns the from the user input updated value +*/ +void zr_drag_int(struct zr_context*, zr_int min, zr_int *val, + zr_int max, zr_int inc_per_pixel); +/* this function executes a dragable int value widget + Input: + - minimal dragging value that will not be underflown + - slider dragging which shall be updated + - maximal dragging value that will not be overflown + - value increment per dragged pixel delta + - dragging axis with either ZR_AXIS_X or ZR_AXIS_Y + Output: + - returns the from the user input updated value +*/ void zr_progress(struct zr_context*, zr_size *cur, zr_size max, zr_bool modifyable); /* this function creates an either user or program controlled progressbar Input: