From c048d6fbc3c85ad5d9c0e0bc278501c197a266eb Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:44:47 +0000 Subject: [PATCH 01/13] add knobs --- demo/common/overview.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/demo/common/overview.c b/demo/common/overview.c index dfc6fcb..a743975 100644 --- a/demo/common/overview.c +++ b/demo/common/overview.c @@ -264,6 +264,12 @@ overview(struct nk_context *ctx) nk_labelf(ctx, NK_TEXT_LEFT, "Progressbar: %u" , (int)prog_value); nk_progress(ctx, &prog_value, 100, NK_MODIFIABLE); + nk_layout_row(ctx, NK_STATIC, 40, 2, ratio); + nk_labelf(ctx, NK_TEXT_LEFT, "Knob int: %d", int_knob); + nk_knob_int(ctx, 0, &int_knob, 10, 1, NK_DOWN, 60.0f); + nk_labelf(ctx, NK_TEXT_LEFT, "Knob float: %.2f", float_knob); + nk_knob_float(ctx, 0, &float_knob, 5.0, 0.5f, NK_DOWN, 60.0f); + nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); nk_label(ctx, "Property float:", NK_TEXT_LEFT); nk_property_float(ctx, "Float:", 0, &property_float, 64.0f, 0.1f, 0.2f); From 728e44b0a2f0cb3f4ec8813be6e8c5fab39809f6 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:47:45 +0000 Subject: [PATCH 02/13] Update paq.bat --- src/paq.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paq.bat b/src/paq.bat index eb258b5..f42a168 100644 --- a/src/paq.bat +++ b/src/paq.bat @@ -1 +1 @@ -build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ..\nuklear.h +build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ..\nuklear.h From d0c557dd3439bc6701033b1af1b78a40474f8bd6 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:47:46 +0000 Subject: [PATCH 03/13] Update paq.sh --- src/paq.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/paq.sh b/src/paq.sh index 45ce4b7..7effee7 100755 --- a/src/paq.sh +++ b/src/paq.sh @@ -1,3 +1,2 @@ #!/bin/sh -python build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h - +python build.py --macro NK --intro HEADER --pub nuklear.h --priv1 nuklear_internal.h,nuklear_math.c,nuklear_util.c,nuklear_color.c,nuklear_utf8.c,nuklear_buffer.c,nuklear_string.c,nuklear_draw.c,nuklear_vertex.c --extern stb_rect_pack.h,stb_truetype.h --priv2 nuklear_font.c,nuklear_input.c,nuklear_style.c,nuklear_context.c,nuklear_pool.c,nuklear_page_element.c,nuklear_table.c,nuklear_panel.c,nuklear_window.c,nuklear_popup.c,nuklear_contextual.c,nuklear_menu.c,nuklear_layout.c,nuklear_tree.c,nuklear_group.c,nuklear_list_view.c,nuklear_widget.c,nuklear_text.c,nuklear_image.c,nuklear_9slice.c,nuklear_button.c,nuklear_toggle.c,nuklear_selectable.c,nuklear_slider.c,nuklear_knob.c,nuklear_progress.c,nuklear_scrollbar.c,nuklear_text_editor.c,nuklear_edit.c,nuklear_property.c,nuklear_chart.c,nuklear_color_picker.c,nuklear_combo.c,nuklear_tooltip.c --outro LICENSE,CHANGELOG,CREDITS > ../nuklear.h From 3d5eb27f852cd4025f2dcb42012d2e900a8036d3 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:48:39 +0000 Subject: [PATCH 04/13] add knob widget --- src/nuklear_knob.c | 250 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/nuklear_knob.c diff --git a/src/nuklear_knob.c b/src/nuklear_knob.c new file mode 100644 index 0000000..328f48b --- /dev/null +++ b/src/nuklear_knob.c @@ -0,0 +1,250 @@ +#include "nuklear.h" +#include "nuklear_internal.h" + +/* =============================================================== + * + * KNOB + * + * ===============================================================*/ + +NK_LIB float +nk_knob_behavior(nk_flags *state, struct nk_input *in, + struct nk_rect bounds, float knob_min, float knob_max, float knob_value, + float knob_step, float knob_steps, + enum nk_heading zero_direction, float dead_zone_percent) +{ + struct nk_vec2 origin; + float angle = 0.0f; + origin.x = bounds.x + (bounds.w / 2); + origin.y = bounds.y + (bounds.h / 2); + + nk_widget_state_reset(state); + + /* handle click and drag input */ + if(in && + in->mouse.buttons[NK_BUTTON_LEFT].down && + nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, bounds, nk_true)){ + /* calculate angle from origin and rotate */ + const float direction_rads[4] = { + NK_PI * 2.5f, /* 90 NK_UP */ + NK_PI * 2.0f, /* 0 NK_RIGHT */ + NK_PI * 1.5f, /* 270 NK_DOWN */ + NK_PI, /* 180 NK_LEFT */ + }; + *state = NK_WIDGET_STATE_ACTIVE; + + angle = NK_ATAN2(in->mouse.pos.y - origin.y, in->mouse.pos.x - origin.x) + direction_rads[zero_direction]; + angle -= (angle > NK_PI * 2) ? NK_PI * 3 : NK_PI; + + /* account for dead space applied when drawing */ + angle *= 1.0f / (1.0f - dead_zone_percent); + angle = NK_CLAMP(-NK_PI, angle, NK_PI); + + /* convert -pi -> pi range to 0.0 -> 1.0 */ + angle = (angle + NK_PI) / (NK_PI * 2); + + /* click to closest step */ + knob_value = knob_min + ( (int)(angle * knob_steps + (knob_step / 2)) ) * knob_step; + knob_value = NK_CLAMP(knob_min, knob_value, knob_max); + } + + /* knob widget state */ + if (nk_input_is_mouse_hovering_rect(in, bounds)){ + *state = NK_WIDGET_STATE_HOVERED; + if (in) { + /* handle scroll and arrow inputs */ + if (in->mouse.scroll_delta.y > 0 || + (in->keyboard.keys[NK_KEY_UP].down && in->keyboard.keys[NK_KEY_UP].clicked)) + knob_value += knob_step; + + if (in->mouse.scroll_delta.y < 0 || + (in->keyboard.keys[NK_KEY_DOWN].down && in->keyboard.keys[NK_KEY_DOWN].clicked)) + knob_value -= knob_step; + } + knob_value = NK_CLAMP(knob_min, knob_value, knob_max); + } + if (*state & NK_WIDGET_STATE_HOVER && + !nk_input_is_mouse_prev_hovering_rect(in, bounds)) + *state |= NK_WIDGET_STATE_ENTERED; + else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) + *state |= NK_WIDGET_STATE_LEFT; + + return knob_value; +} +NK_LIB void +nk_draw_knob(struct nk_command_buffer *out, nk_flags state, + const struct nk_style_knob *style, const struct nk_rect *bounds, float min, float value, float max, + enum nk_heading zero_direction, float dead_zone_percent) +{ + const struct nk_style_item *background; + struct nk_color knob_color, cursor; + + NK_UNUSED(min); + NK_UNUSED(max); + NK_UNUSED(value); + + if (state & NK_WIDGET_STATE_ACTIVED) { + background = &style->active; + knob_color = style->knob_active; + cursor = style->cursor_active; + } else if (state & NK_WIDGET_STATE_HOVER) { + background = &style->hover; + knob_color = style->knob_hover; + cursor = style->cursor_hover; + } else { + background = &style->normal; + knob_color = style->knob_normal; + cursor = style->cursor_normal; + } + + /* draw background */ + switch(background->type) { + case NK_STYLE_ITEM_IMAGE: + nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor)); + break; + case NK_STYLE_ITEM_NINE_SLICE: + nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor)); + break; + case NK_STYLE_ITEM_COLOR: + nk_fill_rect(out, *bounds, 0, nk_rgb_factor(background->data.color, style->color_factor)); + nk_stroke_rect(out, *bounds, 0, style->border, nk_rgb_factor(style->border_color, style->color_factor)); + break; + } + + /* draw knob */ + nk_fill_circle(out, *bounds, nk_rgb_factor(knob_color, style->color_factor)); + if(style->knob_border > 0){ + struct nk_rect border_bounds = *bounds; + border_bounds.x += style->knob_border / 2; + border_bounds.y += style->knob_border / 2; + border_bounds.w -= style->knob_border; + border_bounds.h -= style->knob_border; + nk_stroke_circle(out, border_bounds, style->knob_border, nk_rgb_factor(style->knob_border_color, style->color_factor)); + } + { /* calculate cursor line cords */ + float half_circle_size = (bounds->w / 2); + float angle = (value - min) / (max - min); + float alive_zone = 1.0f - dead_zone_percent; + struct nk_vec2 cursor_start, cursor_end; + const float direction_rads[4] = { + NK_PI * 1.5f, /* 90 NK_UP */ + 0.0f, /* 0 NK_RIGHT */ + NK_PI * 0.5f, /* 270 NK_DOWN */ + NK_PI, /* 180 NK_LEFT */ + }; + /* calculate + apply dead zone */ + angle = (angle * alive_zone) + (dead_zone_percent / 2); + + /* percentage 0.0 -> 1.0 to radians, rads are 0.0 to (2*pi) NOT -pi to pi */ + angle *= NK_PI * 2; + + /* apply zero angle */ + angle += direction_rads[zero_direction]; + if(angle > NK_PI * 2) + angle -= NK_PI * 2; + + cursor_start.x = bounds->x + half_circle_size + (angle > NK_PI); + cursor_start.y = bounds->y + half_circle_size + (angle < NK_PI_HALF || angle > (NK_PI * 1.5f)); + + cursor_end.x = cursor_start.x + (half_circle_size * NK_COS(angle)); + cursor_end.y = cursor_start.y + (half_circle_size * NK_SIN(angle)); + + /* cut off half of the cursor */ + cursor_start.x = (cursor_start.x + cursor_end.x) / 2; + cursor_start.y = (cursor_start.y + cursor_end.y) / 2; + + /* draw cursor */ + nk_stroke_line(out, cursor_start.x, cursor_start.y, cursor_end.x, cursor_end.y, 2, nk_rgb_factor(cursor, style->color_factor)); + } +} +NK_LIB float +nk_do_knob(nk_flags *state, + struct nk_command_buffer *out, struct nk_rect bounds, + float min, float val, float max, float step, + enum nk_heading zero_direction, float dead_zone_percent, + const struct nk_style_knob *style, struct nk_input *in) +{ + float knob_range; + float knob_min; + float knob_max; + float knob_value; + float knob_steps; + + NK_ASSERT(style); + NK_ASSERT(out); + if (!out || !style) + return 0; + + /* remove padding from knob bounds */ + bounds.y = bounds.y + style->padding.y; + bounds.x = bounds.x + style->padding.x; + bounds.h = NK_MAX(bounds.h, 2*style->padding.y); + bounds.w = NK_MAX(bounds.w, 2*style->padding.x); + bounds.w -= 2 * style->padding.x; + bounds.h -= 2 * style->padding.y; + if(bounds.h < bounds.w){ + bounds.x += (bounds.w - bounds.h) / 2; + bounds.w = bounds.h; + } + + /* make sure the provided values are correct */ + knob_max = NK_MAX(min, max); + knob_min = NK_MIN(min, max); + knob_value = NK_CLAMP(knob_min, val, knob_max); + knob_range = knob_max - knob_min; + knob_steps = knob_range / step; + + knob_value = nk_knob_behavior(state, in, bounds, knob_min, knob_max, knob_value, step, knob_steps, zero_direction, dead_zone_percent); + + /* draw knob */ + if (style->draw_begin) style->draw_begin(out, style->userdata); + nk_draw_knob(out, *state, style, &bounds, knob_min, knob_value, knob_max, zero_direction, dead_zone_percent); + if (style->draw_end) style->draw_end(out, style->userdata); + return knob_value; +} +NK_API nk_bool +nk_knob_float(struct nk_context *ctx, float min_value, float *value, float max_value, + float value_step, enum nk_heading zero_direction, float dead_zone_degrees) +{ + struct nk_window *win; + struct nk_panel *layout; + struct nk_input *in; + const struct nk_style *style; + + int ret = 0; + float old_value; + struct nk_rect bounds; + enum nk_widget_layout_states state; + + NK_ASSERT(ctx); + NK_ASSERT(ctx->current); + NK_ASSERT(ctx->current->layout); + NK_ASSERT(value); + NK_ASSERT(NK_BETWEEN(dead_zone_degrees, 0.0f, 360.0f)); + if (!ctx || !ctx->current || !ctx->current->layout || !value) + return ret; + + win = ctx->current; + style = &ctx->style; + layout = win->layout; + + state = nk_widget(&bounds, ctx); + if (!state) return ret; + in = (state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; + + old_value = *value; + *value = nk_do_knob(&ctx->last_widget_state, &win->buffer, bounds, min_value, + old_value, max_value, value_step, zero_direction, dead_zone_degrees / 360.0f, &style->knob, in); + + return (old_value > *value || old_value < *value); +} +NK_API nk_bool +nk_knob_int(struct nk_context *ctx, int min, int *val, int max, int step, + enum nk_heading zero_direction, float dead_zone_degrees) +{ + int ret; + float value = (float)*val; + ret = nk_knob_float(ctx, (float)min, &value, (float)max, (float)step, zero_direction, dead_zone_degrees); + *val = (int)value; + return ret; +} From 76ad5ebd3b0a28dde8c1f04612d3232318d0a222 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:54:52 +0000 Subject: [PATCH 05/13] add knobs --- src/nuklear.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/nuklear.h b/src/nuklear.h index 7c627e9..a2babc8 100644 --- a/src/nuklear.h +++ b/src/nuklear.h @@ -3039,6 +3039,15 @@ NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); NK_API nk_bool nk_slider_float(struct nk_context*, float min, float *val, float max, float step); NK_API nk_bool nk_slider_int(struct nk_context*, int min, int *val, int max, int step); + +/* ============================================================================= + * + * KNOB + * + * ============================================================================= */ +NK_API nk_bool nk_knob_float(struct nk_context*, float min, float *val, float max, float step, enum nk_heading zero_direction, float dead_zone_degrees); +NK_API nk_bool nk_knob_int(struct nk_context*, int min, int *val, int max, int step, enum nk_heading zero_direction, float dead_zone_degrees); + /* ============================================================================= * * PROGRESSBAR @@ -3445,6 +3454,10 @@ enum nk_style_colors { NK_COLOR_SCROLLBAR_CURSOR_HOVER, NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, NK_COLOR_TAB_HEADER, + NK_COLOR_KNOB, + NK_COLOR_KNOB_CURSOR, + NK_COLOR_KNOB_CURSOR_HOVER, + NK_COLOR_KNOB_CURSOR_ACTIVE, NK_COLOR_COUNT }; enum nk_style_cursor { @@ -4857,6 +4870,39 @@ struct nk_style_slider { void(*draw_end)(struct nk_command_buffer*, nk_handle); }; +struct nk_style_knob { + /* background */ + struct nk_style_item normal; + struct nk_style_item hover; + struct nk_style_item active; + struct nk_color border_color; + + /* knob */ + struct nk_color knob_normal; + struct nk_color knob_hover; + struct nk_color knob_active; + struct nk_color knob_border_color; + + /* cursor */ + struct nk_color cursor_normal; + struct nk_color cursor_hover; + struct nk_color cursor_active; + + /* properties */ + float border; + float knob_border; + struct nk_vec2 padding; + struct nk_vec2 spacing; + float cursor_width; + float color_factor; + float disabled_factor; + + /* optional user callbacks */ + nk_handle userdata; + void(*draw_begin)(struct nk_command_buffer*, nk_handle); + void(*draw_end)(struct nk_command_buffer*, nk_handle); +}; + struct nk_style_progress { /* background */ struct nk_style_item normal; @@ -5143,6 +5189,7 @@ struct nk_style { struct nk_style_toggle checkbox; struct nk_style_selectable selectable; struct nk_style_slider slider; + struct nk_style_knob knob; struct nk_style_progress progress; struct nk_style_property property; struct nk_style_edit edit; @@ -5534,6 +5581,7 @@ struct nk_context { * MATH * =============================================================== */ #define NK_PI 3.141592654f +#define NK_PI_HALF 1.570796326f #define NK_UTF_INVALID 0xFFFD #define NK_MAX_FLOAT_PRECISION 2 From b7125d9b102a7691e62479071440338cda0cd023 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:58:22 +0000 Subject: [PATCH 06/13] add atan(x) and atan2(y,x) --- src/nuklear_math.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/nuklear_math.c b/src/nuklear_math.c index 672fd81..d9b981e 100644 --- a/src/nuklear_math.c +++ b/src/nuklear_math.c @@ -84,6 +84,52 @@ nk_cos(float x) return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8))))))); } #endif +#ifndef NK_ATAN +#define NK_ATAN nk_atan +NK_LIB float +nk_atan(float x) +{ + /* ./lolremez --progress --float -d 9 -r "0:pi*2" "atan(x)" */ + float u = -1.0989005e-05f; + NK_ASSERT(x >= 0.0f && "TODO support negative floats"); + u = u * x + 0.00034117949f; + u = u * x + -0.0044932296f; + u = u * x + 0.032596264f; + u = u * x + -0.14088021f; + u = u * x + 0.36040401f; + u = u * x + -0.47017866f; + u = u * x + 0.00050198776f; + u = u * x + 1.0077682f; + u = u * x + -0.0004765437f; + return u; +} +#endif +#ifndef NK_ATAN2 +#define NK_ATAN2 nk_atan2 +NK_LIB float +nk_atan2(float y, float x) +{ + float ax = NK_ABS(x), + ay = NK_ABS(y); + /* 0 = +y +x 1 = -y +x + 2 = +y -x 3 = -y -x */ + nk_uint signs = (y < 0) | ((x < 0) << 1); + + float a; + if(y == 0.0 && x == 0.0) return 0.0f; + a = (ay > ax) + ? NK_PI_HALF - NK_ATAN(ax / ay) + : NK_ATAN(ay / ax); + + switch(signs){ + case 0: return a; + case 1: return -a; + case 2: return -a + NK_PI; + case 3: return a - NK_PI; + } + return 0.0f; /* prevents warning */ +} +#endif NK_LIB nk_uint nk_round_up_pow2(nk_uint v) { From 0ddaeb70438a76e16f59023e9cc71c813ce1e156 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:00:05 +0000 Subject: [PATCH 07/13] add atan(x) and atan2(y,x) --- src/nuklear_internal.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nuklear_internal.h b/src/nuklear_internal.h index e0de763..e945d74 100644 --- a/src/nuklear_internal.h +++ b/src/nuklear_internal.h @@ -103,6 +103,12 @@ NK_LIB float nk_sin(float x); #ifndef NK_COS NK_LIB float nk_cos(float x); #endif +#ifndef NK_ATAN +NK_LIB float nk_atan(float x); +#endif +#ifndef NK_ATAN2 +NK_LIB float nk_atan2(float y, float x); +#endif NK_LIB nk_uint nk_round_up_pow2(nk_uint v); NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount); NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad); From 820eca58582344a3061baf7da8113e3305deddef Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:03:06 +0000 Subject: [PATCH 08/13] Update overview.c --- demo/common/overview.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demo/common/overview.c b/demo/common/overview.c index a743975..056f97a 100644 --- a/demo/common/overview.c +++ b/demo/common/overview.c @@ -225,6 +225,8 @@ overview(struct nk_context *ctx) /* Basic widgets */ static int int_slider = 5; static float float_slider = 2.5f; + static int int_knob = 5; + static float float_knob = 2.5f; static nk_size prog_value = 40; static float property_float = 2; static int property_int = 10; From 48434308c60b8c240df15e7566b27cd64be1b1a4 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:06:30 +0000 Subject: [PATCH 09/13] Update nuklear_style.c --- src/nuklear_style.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/nuklear_style.c b/src/nuklear_style.c index 709fe68..94d2191 100644 --- a/src/nuklear_style.c +++ b/src/nuklear_style.c @@ -303,6 +303,32 @@ nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) button->draw_end = 0; style->slider.dec_button = style->slider.inc_button; + /* knob */ + knob = &style->knob; + nk_zero_struct(*knob); + knob->normal = nk_style_item_hide(); + knob->hover = nk_style_item_hide(); + knob->active = nk_style_item_hide(); + knob->knob_normal = table[NK_COLOR_KNOB]; + knob->knob_hover = table[NK_COLOR_KNOB]; + knob->knob_active = table[NK_COLOR_KNOB]; + knob->cursor_normal = table[NK_COLOR_KNOB_CURSOR]; + knob->cursor_hover = table[NK_COLOR_KNOB_CURSOR_HOVER]; + knob->cursor_active = table[NK_COLOR_KNOB_CURSOR_ACTIVE]; + + knob->knob_border_color = table[NK_COLOR_BORDER]; + knob->knob_border = 1.0f; + + knob->padding = nk_vec2(2,2); + knob->spacing = nk_vec2(2,2); + knob->cursor_width = 2; + knob->color_factor = 1.0f; + knob->disabled_factor = NK_WIDGET_DISABLED_FACTOR; + + knob->userdata = nk_handle_ptr(0); + knob->draw_begin = 0; + knob->draw_end = 0; + /* progressbar */ prog = &style->progress; nk_zero_struct(*prog); From a6973c2d64ea88b608669417726176b9295a619e Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:08:17 +0000 Subject: [PATCH 10/13] Update nuklear_style.c --- src/nuklear_style.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nuklear_style.c b/src/nuklear_style.c index 94d2191..fb9be0e 100644 --- a/src/nuklear_style.c +++ b/src/nuklear_style.c @@ -95,6 +95,7 @@ nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) struct nk_style_toggle *toggle; struct nk_style_selectable *select; struct nk_style_slider *slider; + struct nk_style_knob *knob; struct nk_style_progress *prog; struct nk_style_scrollbar *scroll; struct nk_style_edit *edit; From 8306b324650d761ac590324756ba54c0c2f788a8 Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:10:19 +0000 Subject: [PATCH 11/13] Update nuklear_style.c --- src/nuklear_style.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/nuklear_style.c b/src/nuklear_style.c index fb9be0e..acd1278 100644 --- a/src/nuklear_style.c +++ b/src/nuklear_style.c @@ -19,13 +19,13 @@ NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0) NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ + NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ - NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ + NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ @@ -35,7 +35,11 @@ NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0) NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \ NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \ - NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) + NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) \ + NK_COLOR(NK_COLOR_KNOB, 38, 38, 38, 255) \ + NK_COLOR(NK_COLOR_KNOB_CURSOR, 100,100,100,255) \ + NK_COLOR(NK_COLOR_KNOB_CURSOR_HOVER, 120,120,120,255) \ + NK_COLOR(NK_COLOR_KNOB_CURSOR_ACTIVE, 150,150,150,255) NK_GLOBAL const struct nk_color nk_default_color_style[NK_COLOR_COUNT] = { From 97fb6fffd6e8df1e7cd4b129bb20c874ec044a2b Mon Sep 17 00:00:00 2001 From: PROP 65 <132837123+PROP65@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:13:57 +0000 Subject: [PATCH 12/13] Rebuild nuklear.h --- nuklear.h | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 385 insertions(+), 3 deletions(-) diff --git a/nuklear.h b/nuklear.h index 12fa7ab..19dc937 100644 --- a/nuklear.h +++ b/nuklear.h @@ -3261,6 +3261,15 @@ NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); NK_API nk_bool nk_slider_float(struct nk_context*, float min, float *val, float max, float step); NK_API nk_bool nk_slider_int(struct nk_context*, int min, int *val, int max, int step); + +/* ============================================================================= + * + * KNOB + * + * ============================================================================= */ +NK_API nk_bool nk_knob_float(struct nk_context*, float min, float *val, float max, float step, enum nk_heading zero_direction, float dead_zone_degrees); +NK_API nk_bool nk_knob_int(struct nk_context*, int min, int *val, int max, int step, enum nk_heading zero_direction, float dead_zone_degrees); + /* ============================================================================= * * PROGRESSBAR @@ -3667,6 +3676,10 @@ enum nk_style_colors { NK_COLOR_SCROLLBAR_CURSOR_HOVER, NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, NK_COLOR_TAB_HEADER, + NK_COLOR_KNOB, + NK_COLOR_KNOB_CURSOR, + NK_COLOR_KNOB_CURSOR_HOVER, + NK_COLOR_KNOB_CURSOR_ACTIVE, NK_COLOR_COUNT }; enum nk_style_cursor { @@ -5079,6 +5092,39 @@ struct nk_style_slider { void(*draw_end)(struct nk_command_buffer*, nk_handle); }; +struct nk_style_knob { + /* background */ + struct nk_style_item normal; + struct nk_style_item hover; + struct nk_style_item active; + struct nk_color border_color; + + /* knob */ + struct nk_color knob_normal; + struct nk_color knob_hover; + struct nk_color knob_active; + struct nk_color knob_border_color; + + /* cursor */ + struct nk_color cursor_normal; + struct nk_color cursor_hover; + struct nk_color cursor_active; + + /* properties */ + float border; + float knob_border; + struct nk_vec2 padding; + struct nk_vec2 spacing; + float cursor_width; + float color_factor; + float disabled_factor; + + /* optional user callbacks */ + nk_handle userdata; + void(*draw_begin)(struct nk_command_buffer*, nk_handle); + void(*draw_end)(struct nk_command_buffer*, nk_handle); +}; + struct nk_style_progress { /* background */ struct nk_style_item normal; @@ -5365,6 +5411,7 @@ struct nk_style { struct nk_style_toggle checkbox; struct nk_style_selectable selectable; struct nk_style_slider slider; + struct nk_style_knob knob; struct nk_style_progress progress; struct nk_style_property property; struct nk_style_edit edit; @@ -5756,6 +5803,7 @@ struct nk_context { * MATH * =============================================================== */ #define NK_PI 3.141592654f +#define NK_PI_HALF 1.570796326f #define NK_UTF_INVALID 0xFFFD #define NK_MAX_FLOAT_PRECISION 2 @@ -5939,6 +5987,12 @@ NK_LIB float nk_sin(float x); #ifndef NK_COS NK_LIB float nk_cos(float x); #endif +#ifndef NK_ATAN +NK_LIB float nk_atan(float x); +#endif +#ifndef NK_ATAN2 +NK_LIB float nk_atan2(float y, float x); +#endif NK_LIB nk_uint nk_round_up_pow2(nk_uint v); NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount); NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad); @@ -6292,6 +6346,52 @@ nk_cos(float x) return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8))))))); } #endif +#ifndef NK_ATAN +#define NK_ATAN nk_atan +NK_LIB float +nk_atan(float x) +{ + /* ./lolremez --progress --float -d 9 -r "0:pi*2" "atan(x)" */ + float u = -1.0989005e-05f; + NK_ASSERT(x >= 0.0f && "TODO support negative floats"); + u = u * x + 0.00034117949f; + u = u * x + -0.0044932296f; + u = u * x + 0.032596264f; + u = u * x + -0.14088021f; + u = u * x + 0.36040401f; + u = u * x + -0.47017866f; + u = u * x + 0.00050198776f; + u = u * x + 1.0077682f; + u = u * x + -0.0004765437f; + return u; +} +#endif +#ifndef NK_ATAN2 +#define NK_ATAN2 nk_atan2 +NK_LIB float +nk_atan2(float y, float x) +{ + float ax = NK_ABS(x), + ay = NK_ABS(y); + /* 0 = +y +x 1 = -y +x + 2 = +y -x 3 = -y -x */ + nk_uint signs = (y < 0) | ((x < 0) << 1); + + float a; + if(y == 0.0 && x == 0.0) return 0.0f; + a = (ay > ax) + ? NK_PI_HALF - NK_ATAN(ax / ay) + : NK_ATAN(ay / ax); + + switch(signs){ + case 0: return a; + case 1: return -a; + case 2: return -a + NK_PI; + case 3: return a - NK_PI; + } + return 0.0f; /* prevents warning */ +} +#endif NK_LIB nk_uint nk_round_up_pow2(nk_uint v) { @@ -18219,13 +18319,13 @@ NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0) NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ + NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ - NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ + NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ @@ -18235,7 +18335,11 @@ NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0) NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \ NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \ - NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) + NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) \ + NK_COLOR(NK_COLOR_KNOB, 38, 38, 38, 255) \ + NK_COLOR(NK_COLOR_KNOB_CURSOR, 100,100,100,255) \ + NK_COLOR(NK_COLOR_KNOB_CURSOR_HOVER, 120,120,120,255) \ + NK_COLOR(NK_COLOR_KNOB_CURSOR_ACTIVE, 150,150,150,255) NK_GLOBAL const struct nk_color nk_default_color_style[NK_COLOR_COUNT] = { @@ -18295,6 +18399,7 @@ nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) struct nk_style_toggle *toggle; struct nk_style_selectable *select; struct nk_style_slider *slider; + struct nk_style_knob *knob; struct nk_style_progress *prog; struct nk_style_scrollbar *scroll; struct nk_style_edit *edit; @@ -18503,6 +18608,32 @@ nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) button->draw_end = 0; style->slider.dec_button = style->slider.inc_button; + /* knob */ + knob = &style->knob; + nk_zero_struct(*knob); + knob->normal = nk_style_item_hide(); + knob->hover = nk_style_item_hide(); + knob->active = nk_style_item_hide(); + knob->knob_normal = table[NK_COLOR_KNOB]; + knob->knob_hover = table[NK_COLOR_KNOB]; + knob->knob_active = table[NK_COLOR_KNOB]; + knob->cursor_normal = table[NK_COLOR_KNOB_CURSOR]; + knob->cursor_hover = table[NK_COLOR_KNOB_CURSOR_HOVER]; + knob->cursor_active = table[NK_COLOR_KNOB_CURSOR_ACTIVE]; + + knob->knob_border_color = table[NK_COLOR_BORDER]; + knob->knob_border = 1.0f; + + knob->padding = nk_vec2(2,2); + knob->spacing = nk_vec2(2,2); + knob->cursor_width = 2; + knob->color_factor = 1.0f; + knob->disabled_factor = NK_WIDGET_DISABLED_FACTOR; + + knob->userdata = nk_handle_ptr(0); + knob->draw_begin = 0; + knob->draw_end = 0; + /* progressbar */ prog = &style->progress; nk_zero_struct(*prog); @@ -25762,6 +25893,257 @@ nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) +/* =============================================================== + * + * KNOB + * + * ===============================================================*/ + +NK_LIB float +nk_knob_behavior(nk_flags *state, struct nk_input *in, + struct nk_rect bounds, float knob_min, float knob_max, float knob_value, + float knob_step, float knob_steps, + enum nk_heading zero_direction, float dead_zone_percent) +{ + struct nk_vec2 origin; + float angle = 0.0f; + origin.x = bounds.x + (bounds.w / 2); + origin.y = bounds.y + (bounds.h / 2); + + nk_widget_state_reset(state); + + /* handle click and drag input */ + if(in && + in->mouse.buttons[NK_BUTTON_LEFT].down && + nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, bounds, nk_true)){ + /* calculate angle from origin and rotate */ + const float direction_rads[4] = { + NK_PI * 2.5f, /* 90 NK_UP */ + NK_PI * 2.0f, /* 0 NK_RIGHT */ + NK_PI * 1.5f, /* 270 NK_DOWN */ + NK_PI, /* 180 NK_LEFT */ + }; + *state = NK_WIDGET_STATE_ACTIVE; + + angle = NK_ATAN2(in->mouse.pos.y - origin.y, in->mouse.pos.x - origin.x) + direction_rads[zero_direction]; + angle -= (angle > NK_PI * 2) ? NK_PI * 3 : NK_PI; + + /* account for dead space applied when drawing */ + angle *= 1.0f / (1.0f - dead_zone_percent); + angle = NK_CLAMP(-NK_PI, angle, NK_PI); + + /* convert -pi -> pi range to 0.0 -> 1.0 */ + angle = (angle + NK_PI) / (NK_PI * 2); + + /* click to closest step */ + knob_value = knob_min + ( (int)(angle * knob_steps + (knob_step / 2)) ) * knob_step; + knob_value = NK_CLAMP(knob_min, knob_value, knob_max); + } + + /* knob widget state */ + if (nk_input_is_mouse_hovering_rect(in, bounds)){ + *state = NK_WIDGET_STATE_HOVERED; + if (in) { + /* handle scroll and arrow inputs */ + if (in->mouse.scroll_delta.y > 0 || + (in->keyboard.keys[NK_KEY_UP].down && in->keyboard.keys[NK_KEY_UP].clicked)) + knob_value += knob_step; + + if (in->mouse.scroll_delta.y < 0 || + (in->keyboard.keys[NK_KEY_DOWN].down && in->keyboard.keys[NK_KEY_DOWN].clicked)) + knob_value -= knob_step; + } + knob_value = NK_CLAMP(knob_min, knob_value, knob_max); + } + if (*state & NK_WIDGET_STATE_HOVER && + !nk_input_is_mouse_prev_hovering_rect(in, bounds)) + *state |= NK_WIDGET_STATE_ENTERED; + else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) + *state |= NK_WIDGET_STATE_LEFT; + + return knob_value; +} +NK_LIB void +nk_draw_knob(struct nk_command_buffer *out, nk_flags state, + const struct nk_style_knob *style, const struct nk_rect *bounds, float min, float value, float max, + enum nk_heading zero_direction, float dead_zone_percent) +{ + const struct nk_style_item *background; + struct nk_color knob_color, cursor; + + NK_UNUSED(min); + NK_UNUSED(max); + NK_UNUSED(value); + + if (state & NK_WIDGET_STATE_ACTIVED) { + background = &style->active; + knob_color = style->knob_active; + cursor = style->cursor_active; + } else if (state & NK_WIDGET_STATE_HOVER) { + background = &style->hover; + knob_color = style->knob_hover; + cursor = style->cursor_hover; + } else { + background = &style->normal; + knob_color = style->knob_normal; + cursor = style->cursor_normal; + } + + /* draw background */ + switch(background->type) { + case NK_STYLE_ITEM_IMAGE: + nk_draw_image(out, *bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor)); + break; + case NK_STYLE_ITEM_NINE_SLICE: + nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor)); + break; + case NK_STYLE_ITEM_COLOR: + nk_fill_rect(out, *bounds, 0, nk_rgb_factor(background->data.color, style->color_factor)); + nk_stroke_rect(out, *bounds, 0, style->border, nk_rgb_factor(style->border_color, style->color_factor)); + break; + } + + /* draw knob */ + nk_fill_circle(out, *bounds, nk_rgb_factor(knob_color, style->color_factor)); + if(style->knob_border > 0){ + struct nk_rect border_bounds = *bounds; + border_bounds.x += style->knob_border / 2; + border_bounds.y += style->knob_border / 2; + border_bounds.w -= style->knob_border; + border_bounds.h -= style->knob_border; + nk_stroke_circle(out, border_bounds, style->knob_border, nk_rgb_factor(style->knob_border_color, style->color_factor)); + } + { /* calculate cursor line cords */ + float half_circle_size = (bounds->w / 2); + float angle = (value - min) / (max - min); + float alive_zone = 1.0f - dead_zone_percent; + struct nk_vec2 cursor_start, cursor_end; + const float direction_rads[4] = { + NK_PI * 1.5f, /* 90 NK_UP */ + 0.0f, /* 0 NK_RIGHT */ + NK_PI * 0.5f, /* 270 NK_DOWN */ + NK_PI, /* 180 NK_LEFT */ + }; + /* calculate + apply dead zone */ + angle = (angle * alive_zone) + (dead_zone_percent / 2); + + /* percentage 0.0 -> 1.0 to radians, rads are 0.0 to (2*pi) NOT -pi to pi */ + angle *= NK_PI * 2; + + /* apply zero angle */ + angle += direction_rads[zero_direction]; + if(angle > NK_PI * 2) + angle -= NK_PI * 2; + + cursor_start.x = bounds->x + half_circle_size + (angle > NK_PI); + cursor_start.y = bounds->y + half_circle_size + (angle < NK_PI_HALF || angle > (NK_PI * 1.5f)); + + cursor_end.x = cursor_start.x + (half_circle_size * NK_COS(angle)); + cursor_end.y = cursor_start.y + (half_circle_size * NK_SIN(angle)); + + /* cut off half of the cursor */ + cursor_start.x = (cursor_start.x + cursor_end.x) / 2; + cursor_start.y = (cursor_start.y + cursor_end.y) / 2; + + /* draw cursor */ + nk_stroke_line(out, cursor_start.x, cursor_start.y, cursor_end.x, cursor_end.y, 2, nk_rgb_factor(cursor, style->color_factor)); + } +} +NK_LIB float +nk_do_knob(nk_flags *state, + struct nk_command_buffer *out, struct nk_rect bounds, + float min, float val, float max, float step, + enum nk_heading zero_direction, float dead_zone_percent, + const struct nk_style_knob *style, struct nk_input *in) +{ + float knob_range; + float knob_min; + float knob_max; + float knob_value; + float knob_steps; + + NK_ASSERT(style); + NK_ASSERT(out); + if (!out || !style) + return 0; + + /* remove padding from knob bounds */ + bounds.y = bounds.y + style->padding.y; + bounds.x = bounds.x + style->padding.x; + bounds.h = NK_MAX(bounds.h, 2*style->padding.y); + bounds.w = NK_MAX(bounds.w, 2*style->padding.x); + bounds.w -= 2 * style->padding.x; + bounds.h -= 2 * style->padding.y; + if(bounds.h < bounds.w){ + bounds.x += (bounds.w - bounds.h) / 2; + bounds.w = bounds.h; + } + + /* make sure the provided values are correct */ + knob_max = NK_MAX(min, max); + knob_min = NK_MIN(min, max); + knob_value = NK_CLAMP(knob_min, val, knob_max); + knob_range = knob_max - knob_min; + knob_steps = knob_range / step; + + knob_value = nk_knob_behavior(state, in, bounds, knob_min, knob_max, knob_value, step, knob_steps, zero_direction, dead_zone_percent); + + /* draw knob */ + if (style->draw_begin) style->draw_begin(out, style->userdata); + nk_draw_knob(out, *state, style, &bounds, knob_min, knob_value, knob_max, zero_direction, dead_zone_percent); + if (style->draw_end) style->draw_end(out, style->userdata); + return knob_value; +} +NK_API nk_bool +nk_knob_float(struct nk_context *ctx, float min_value, float *value, float max_value, + float value_step, enum nk_heading zero_direction, float dead_zone_degrees) +{ + struct nk_window *win; + struct nk_panel *layout; + struct nk_input *in; + const struct nk_style *style; + + int ret = 0; + float old_value; + struct nk_rect bounds; + enum nk_widget_layout_states state; + + NK_ASSERT(ctx); + NK_ASSERT(ctx->current); + NK_ASSERT(ctx->current->layout); + NK_ASSERT(value); + NK_ASSERT(NK_BETWEEN(dead_zone_degrees, 0.0f, 360.0f)); + if (!ctx || !ctx->current || !ctx->current->layout || !value) + return ret; + + win = ctx->current; + style = &ctx->style; + layout = win->layout; + + state = nk_widget(&bounds, ctx); + if (!state) return ret; + in = (state == NK_WIDGET_DISABLED || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; + + old_value = *value; + *value = nk_do_knob(&ctx->last_widget_state, &win->buffer, bounds, min_value, + old_value, max_value, value_step, zero_direction, dead_zone_degrees / 360.0f, &style->knob, in); + + return (old_value > *value || old_value < *value); +} +NK_API nk_bool +nk_knob_int(struct nk_context *ctx, int min, int *val, int max, int step, + enum nk_heading zero_direction, float dead_zone_degrees) +{ + int ret; + float value = (float)*val; + ret = nk_knob_float(ctx, (float)min, &value, (float)max, (float)step, zero_direction, dead_zone_degrees); + *val = (int)value; + return ret; +} + + + + /* =============================================================== * * PROGRESS From 29b7be6de01640d6ff804c36f9288ff640cc8991 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Tue, 27 Aug 2024 11:43:39 -0400 Subject: [PATCH 13/13] knob: Add color styles --- demo/common/style.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/demo/common/style.c b/demo/common/style.c index c31fa2d..b7d8f1c 100644 --- a/demo/common/style.c +++ b/demo/common/style.c @@ -33,6 +33,10 @@ set_style(struct nk_context *ctx, enum theme theme) table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(150, 150, 150, 255); table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(160, 160, 160, 255); table[NK_COLOR_TAB_HEADER] = nk_rgba(180, 180, 180, 255); + table[NK_COLOR_KNOB] = table[NK_COLOR_SLIDER]; + table[NK_COLOR_KNOB_CURSOR] = table[NK_COLOR_SLIDER_CURSOR]; + table[NK_COLOR_KNOB_CURSOR_HOVER] = table[NK_COLOR_SLIDER_CURSOR_HOVER]; + table[NK_COLOR_KNOB_CURSOR_ACTIVE] = table[NK_COLOR_SLIDER_CURSOR_ACTIVE]; nk_style_from_table(ctx, table); } else if (theme == THEME_RED) { table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255); @@ -63,6 +67,10 @@ set_style(struct nk_context *ctx, enum theme theme) table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255); table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255); table[NK_COLOR_TAB_HEADER] = nk_rgba(181, 45, 69, 220); + table[NK_COLOR_KNOB] = table[NK_COLOR_SLIDER]; + table[NK_COLOR_KNOB_CURSOR] = table[NK_COLOR_SLIDER_CURSOR]; + table[NK_COLOR_KNOB_CURSOR_HOVER] = table[NK_COLOR_SLIDER_CURSOR_HOVER]; + table[NK_COLOR_KNOB_CURSOR_ACTIVE] = table[NK_COLOR_SLIDER_CURSOR_ACTIVE]; nk_style_from_table(ctx, table); } else if (theme == THEME_BLUE) { table[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255); @@ -93,6 +101,10 @@ set_style(struct nk_context *ctx, enum theme theme) table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255); table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255); table[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255); + table[NK_COLOR_KNOB] = table[NK_COLOR_SLIDER]; + table[NK_COLOR_KNOB_CURSOR] = table[NK_COLOR_SLIDER_CURSOR]; + table[NK_COLOR_KNOB_CURSOR_HOVER] = table[NK_COLOR_SLIDER_CURSOR_HOVER]; + table[NK_COLOR_KNOB_CURSOR_ACTIVE] = table[NK_COLOR_SLIDER_CURSOR_ACTIVE]; nk_style_from_table(ctx, table); } else if (theme == THEME_DARK) { table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255); @@ -123,6 +135,10 @@ set_style(struct nk_context *ctx, enum theme theme) table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255); table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255); table[NK_COLOR_TAB_HEADER] = nk_rgba(48, 83, 111, 255); + table[NK_COLOR_KNOB] = table[NK_COLOR_SLIDER]; + table[NK_COLOR_KNOB_CURSOR] = table[NK_COLOR_SLIDER_CURSOR]; + table[NK_COLOR_KNOB_CURSOR_HOVER] = table[NK_COLOR_SLIDER_CURSOR_HOVER]; + table[NK_COLOR_KNOB_CURSOR_ACTIVE] = table[NK_COLOR_SLIDER_CURSOR_ACTIVE]; nk_style_from_table(ctx, table); } else if (theme == THEME_DRACULA) { struct nk_color background = nk_rgba(40, 42, 54, 255); @@ -164,6 +180,10 @@ set_style(struct nk_context *ctx, enum theme theme) table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = comment; table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = purple; table[NK_COLOR_TAB_HEADER] = currentline; + table[NK_COLOR_KNOB] = table[NK_COLOR_SLIDER]; + table[NK_COLOR_KNOB_CURSOR] = table[NK_COLOR_SLIDER_CURSOR]; + table[NK_COLOR_KNOB_CURSOR_HOVER] = table[NK_COLOR_SLIDER_CURSOR_HOVER]; + table[NK_COLOR_KNOB_CURSOR_ACTIVE] = table[NK_COLOR_SLIDER_CURSOR_ACTIVE]; nk_style_from_table(ctx, table); } else { nk_style_default(ctx);