Parcourir la source

Merge pull request #669 from PROP65/knob

New Widget: Knobs
Rob Loach il y a 1 an
Parent
commit
b1c2227fa9
10 fichiers modifiés avec 799 ajouts et 9 suppressions
  1. 8 0
      demo/common/overview.c
  2. 20 0
      demo/common/style.c
  3. 385 3
      nuklear.h
  4. 48 0
      src/nuklear.h
  5. 6 0
      src/nuklear_internal.h
  6. 250 0
      src/nuklear_knob.c
  7. 46 0
      src/nuklear_math.c
  8. 34 3
      src/nuklear_style.c
  9. 1 1
      src/paq.bat
  10. 1 2
      src/paq.sh

+ 8 - 0
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;
@@ -264,6 +266,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);

+ 20 - 0
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);

+ 385 - 3
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);
@@ -25761,6 +25892,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

+ 48 - 0
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
 

+ 6 - 0
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);

+ 250 - 0
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;
+}

+ 46 - 0
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)
 {

+ 34 - 3
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] = {
@@ -95,6 +99,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;
@@ -303,6 +308,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);

+ 1 - 1
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

+ 1 - 2
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