Blame src-nuklear/nuklear_slider.c

Ivan Mahonin b53a5c
#include "nuklear.h"
Ivan Mahonin b53a5c
#include "nuklear_internal.h"
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
/* ===============================================================
Ivan Mahonin b53a5c
 *
Ivan Mahonin b53a5c
 *                              SLIDER
Ivan Mahonin b53a5c
 *
Ivan Mahonin b53a5c
 * ===============================================================*/
Ivan Mahonin b53a5c
NK_LIB float
Ivan Mahonin b53a5c
nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
Ivan Mahonin b53a5c
    struct nk_rect *visual_cursor, struct nk_input *in,
Ivan Mahonin b53a5c
    struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
Ivan Mahonin b53a5c
    float slider_step, float slider_steps)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int left_mouse_down;
Ivan Mahonin b53a5c
    int left_mouse_click_in_cursor;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* check if visual cursor is being dragged */
Ivan Mahonin b53a5c
    nk_widget_state_reset(state);
Ivan Mahonin b53a5c
    left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
Ivan Mahonin b53a5c
    left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
Ivan Mahonin b53a5c
            NK_BUTTON_LEFT, *visual_cursor, nk_true);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    if (left_mouse_down && left_mouse_click_in_cursor) {
Ivan Mahonin b53a5c
        float ratio = 0;
Ivan Mahonin b53a5c
        const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
Ivan Mahonin b53a5c
        const float pxstep = bounds.w / slider_steps;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* only update value if the next slider step is reached */
Ivan Mahonin b53a5c
        *state = NK_WIDGET_STATE_ACTIVE;
Ivan Mahonin b53a5c
        if (NK_ABS(d) >= pxstep) {
Ivan Mahonin b53a5c
            const float steps = (float)((int)(NK_ABS(d) / pxstep));
Ivan Mahonin b53a5c
            slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
Ivan Mahonin b53a5c
            slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
Ivan Mahonin b53a5c
            ratio = (slider_value - slider_min)/slider_step;
Ivan Mahonin b53a5c
            logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
Ivan Mahonin b53a5c
            in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* slider widget state */
Ivan Mahonin b53a5c
    if (nk_input_is_mouse_hovering_rect(in, bounds))
Ivan Mahonin b53a5c
        *state = NK_WIDGET_STATE_HOVERED;
Ivan Mahonin b53a5c
    if (*state & NK_WIDGET_STATE_HOVER &&
Ivan Mahonin b53a5c
        !nk_input_is_mouse_prev_hovering_rect(in, bounds))
Ivan Mahonin b53a5c
        *state |= NK_WIDGET_STATE_ENTERED;
Ivan Mahonin b53a5c
    else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
Ivan Mahonin b53a5c
        *state |= NK_WIDGET_STATE_LEFT;
Ivan Mahonin b53a5c
    return slider_value;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
Ivan Mahonin b53a5c
    const struct nk_style_slider *style, const struct nk_rect *bounds,
Ivan Mahonin b53a5c
    const struct nk_rect *visual_cursor, float min, float value, float max)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_rect fill;
Ivan Mahonin b53a5c
    struct nk_rect bar;
Ivan Mahonin b53a5c
    const struct nk_style_item *background;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* select correct slider images/colors */
Ivan Mahonin b53a5c
    struct nk_color bar_color;
Ivan Mahonin b53a5c
    const struct nk_style_item *cursor;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_UNUSED(min);
Ivan Mahonin b53a5c
    NK_UNUSED(max);
Ivan Mahonin b53a5c
    NK_UNUSED(value);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    if (state & NK_WIDGET_STATE_ACTIVED) {
Ivan Mahonin b53a5c
        background = &style->active;
Ivan Mahonin b53a5c
        bar_color = style->bar_active;
Ivan Mahonin b53a5c
        cursor = &style->cursor_active;
Ivan Mahonin b53a5c
    } else if (state & NK_WIDGET_STATE_HOVER) {
Ivan Mahonin b53a5c
        background = &style->hover;
Ivan Mahonin b53a5c
        bar_color = style->bar_hover;
Ivan Mahonin b53a5c
        cursor = &style->cursor_hover;
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        background = &style->normal;
Ivan Mahonin b53a5c
        bar_color = style->bar_normal;
Ivan Mahonin b53a5c
        cursor = &style->cursor_normal;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    /* calculate slider background bar */
Ivan Mahonin b53a5c
    bar.x = bounds->x;
Ivan Mahonin b53a5c
    bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
Ivan Mahonin b53a5c
    bar.w = bounds->w;
Ivan Mahonin b53a5c
    bar.h = bounds->h/6;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* filled background bar style */
Ivan Mahonin b53a5c
    fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
Ivan Mahonin b53a5c
    fill.x = bar.x;
Ivan Mahonin b53a5c
    fill.y = bar.y;
Ivan Mahonin b53a5c
    fill.h = bar.h;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* draw background */
Ivan Mahonin b53a5c
    switch(background->type) {
Ivan Mahonin b53a5c
        case NK_STYLE_ITEM_IMAGE:
Ivan Mahonin b53a5c
            nk_draw_image(out, *bounds, &background->data.image, nk_white);
Ivan Mahonin b53a5c
            break;
Ivan Mahonin b53a5c
        case NK_STYLE_ITEM_NINE_SLICE:
Ivan Mahonin b53a5c
            nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white);
Ivan Mahonin b53a5c
            break;
Ivan Mahonin b53a5c
        case NK_STYLE_ITEM_COLOR:
Ivan Mahonin b53a5c
            nk_fill_rect(out, *bounds, style->rounding, background->data.color);
Ivan Mahonin b53a5c
            nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
Ivan Mahonin b53a5c
            break;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* draw slider bar */
Ivan Mahonin b53a5c
    nk_fill_rect(out, bar, style->rounding, bar_color);
Ivan Mahonin b53a5c
    nk_fill_rect(out, fill, style->rounding, style->bar_filled);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* draw cursor */
Ivan Mahonin b53a5c
    if (cursor->type == NK_STYLE_ITEM_IMAGE)
Ivan Mahonin b53a5c
        nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
Ivan Mahonin b53a5c
    else
Ivan Mahonin b53a5c
        nk_fill_circle(out, *visual_cursor, cursor->data.color);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB float
Ivan Mahonin b53a5c
nk_do_slider(nk_flags *state,
Ivan Mahonin b53a5c
    struct nk_command_buffer *out, struct nk_rect bounds,
Ivan Mahonin b53a5c
    float min, float val, float max, float step,
Ivan Mahonin b53a5c
    const struct nk_style_slider *style, struct nk_input *in,
Ivan Mahonin b53a5c
    const struct nk_user_font *font)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    float slider_range;
Ivan Mahonin b53a5c
    float slider_min;
Ivan Mahonin b53a5c
    float slider_max;
Ivan Mahonin b53a5c
    float slider_value;
Ivan Mahonin b53a5c
    float slider_steps;
Ivan Mahonin b53a5c
    float cursor_offset;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    struct nk_rect visual_cursor;
Ivan Mahonin b53a5c
    struct nk_rect logical_cursor;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_ASSERT(style);
Ivan Mahonin b53a5c
    NK_ASSERT(out);
Ivan Mahonin b53a5c
    if (!out || !style)
Ivan Mahonin b53a5c
        return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* remove padding from slider bounds */
Ivan Mahonin b53a5c
    bounds.x = bounds.x + style->padding.x;
Ivan Mahonin b53a5c
    bounds.y = bounds.y + style->padding.y;
Ivan Mahonin b53a5c
    bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
Ivan Mahonin b53a5c
    bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
Ivan Mahonin b53a5c
    bounds.w -= 2 * style->padding.x;
Ivan Mahonin b53a5c
    bounds.h -= 2 * style->padding.y;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* optional buttons */
Ivan Mahonin b53a5c
    if (style->show_buttons) {
Ivan Mahonin b53a5c
        nk_flags ws;
Ivan Mahonin b53a5c
        struct nk_rect button;
Ivan Mahonin b53a5c
        button.y = bounds.y;
Ivan Mahonin b53a5c
        button.w = bounds.h;
Ivan Mahonin b53a5c
        button.h = bounds.h;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* decrement button */
Ivan Mahonin b53a5c
        button.x = bounds.x;
Ivan Mahonin b53a5c
        if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
Ivan Mahonin b53a5c
            &style->dec_button, in, font))
Ivan Mahonin b53a5c
            val -= step;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        /* increment button */
Ivan Mahonin b53a5c
        button.x = (bounds.x + bounds.w) - button.w;
Ivan Mahonin b53a5c
        if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
Ivan Mahonin b53a5c
            &style->inc_button, in, font))
Ivan Mahonin b53a5c
            val += step;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        bounds.x = bounds.x + button.w + style->spacing.x;
Ivan Mahonin b53a5c
        bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* remove one cursor size to support visual cursor */
Ivan Mahonin b53a5c
    bounds.x += style->cursor_size.x*0.5f;
Ivan Mahonin b53a5c
    bounds.w -= style->cursor_size.x;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* make sure the provided values are correct */
Ivan Mahonin b53a5c
    slider_max = NK_MAX(min, max);
Ivan Mahonin b53a5c
    slider_min = NK_MIN(min, max);
Ivan Mahonin b53a5c
    slider_value = NK_CLAMP(slider_min, val, slider_max);
Ivan Mahonin b53a5c
    slider_range = slider_max - slider_min;
Ivan Mahonin b53a5c
    slider_steps = slider_range / step;
Ivan Mahonin b53a5c
    cursor_offset = (slider_value - slider_min) / step;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* calculate cursor
Ivan Mahonin b53a5c
    Basically you have two cursors. One for visual representation and interaction
Ivan Mahonin b53a5c
    and one for updating the actual cursor value. */
Ivan Mahonin b53a5c
    logical_cursor.h = bounds.h;
Ivan Mahonin b53a5c
    logical_cursor.w = bounds.w / slider_steps;
Ivan Mahonin b53a5c
    logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
Ivan Mahonin b53a5c
    logical_cursor.y = bounds.y;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    visual_cursor.h = style->cursor_size.y;
Ivan Mahonin b53a5c
    visual_cursor.w = style->cursor_size.x;
Ivan Mahonin b53a5c
    visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
Ivan Mahonin b53a5c
    visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
Ivan Mahonin b53a5c
        in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
Ivan Mahonin b53a5c
    visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* draw slider */
Ivan Mahonin b53a5c
    if (style->draw_begin) style->draw_begin(out, style->userdata);
Ivan Mahonin b53a5c
    nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
Ivan Mahonin b53a5c
    if (style->draw_end) style->draw_end(out, style->userdata);
Ivan Mahonin b53a5c
    return slider_value;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
Ivan Mahonin b53a5c
    float value_step)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *win;
Ivan Mahonin b53a5c
    struct nk_panel *layout;
Ivan Mahonin b53a5c
    struct nk_input *in;
Ivan Mahonin b53a5c
    const struct nk_style *style;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    int ret = 0;
Ivan Mahonin b53a5c
    float old_value;
Ivan Mahonin b53a5c
    struct nk_rect bounds;
Ivan Mahonin b53a5c
    enum nk_widget_layout_states state;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current);
Ivan Mahonin b53a5c
    NK_ASSERT(ctx->current->layout);
Ivan Mahonin b53a5c
    NK_ASSERT(value);
Ivan Mahonin b53a5c
    if (!ctx || !ctx->current || !ctx->current->layout || !value)
Ivan Mahonin b53a5c
        return ret;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    win = ctx->current;
Ivan Mahonin b53a5c
    style = &ctx->style;
Ivan Mahonin b53a5c
    layout = win->layout;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    state = nk_widget(&bounds, ctx);
Ivan Mahonin b53a5c
    if (!state) return ret;
Ivan Mahonin b53a5c
    in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    old_value = *value;
Ivan Mahonin b53a5c
    *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
Ivan Mahonin b53a5c
                old_value, max_value, value_step, &style->slider, in, style->font);
Ivan Mahonin b53a5c
    return (old_value > *value || old_value < *value);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API float
Ivan Mahonin b53a5c
nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    nk_slider_float(ctx, min, &val, max, step); return val;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API int
Ivan Mahonin b53a5c
nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    float value = (float)val;
Ivan Mahonin b53a5c
    nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
Ivan Mahonin b53a5c
    return (int)value;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    int ret;
Ivan Mahonin b53a5c
    float value = (float)*val;
Ivan Mahonin b53a5c
    ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
Ivan Mahonin b53a5c
    *val =  (int)value;
Ivan Mahonin b53a5c
    return ret;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c