Blame src-nuklear/nuklear_context.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
 *                          CONTEXT
Ivan Mahonin b53a5c
 *
Ivan Mahonin b53a5c
 * ===============================================================*/
Ivan Mahonin b53a5c
NK_INTERN void
Ivan Mahonin b53a5c
nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
    nk_zero_struct(*ctx);
Ivan Mahonin b53a5c
    nk_style_default(ctx);
Ivan Mahonin b53a5c
    ctx->seq = 1;
Ivan Mahonin b53a5c
    if (font) ctx->style.font = font;
Ivan Mahonin b53a5c
#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
Ivan Mahonin b53a5c
    nk_draw_list_init(&ctx->draw_list);
Ivan Mahonin b53a5c
#endif
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_allocator alloc;
Ivan Mahonin b53a5c
    alloc.userdata.ptr = 0;
Ivan Mahonin b53a5c
    alloc.alloc = nk_malloc;
Ivan Mahonin b53a5c
    alloc.free = nk_mfree;
Ivan Mahonin b53a5c
    return nk_init(ctx, &alloc, font);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
#endif
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
Ivan Mahonin b53a5c
    const struct nk_user_font *font)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(memory);
Ivan Mahonin b53a5c
    if (!memory) return 0;
Ivan Mahonin b53a5c
    nk_setup(ctx, font);
Ivan Mahonin b53a5c
    nk_buffer_init_fixed(&ctx->memory, memory, size);
Ivan Mahonin b53a5c
    ctx->use_pool = nk_false;
Ivan Mahonin b53a5c
    return 1;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
Ivan Mahonin b53a5c
    struct nk_buffer *pool, const struct nk_user_font *font)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(cmds);
Ivan Mahonin b53a5c
    NK_ASSERT(pool);
Ivan Mahonin b53a5c
    if (!cmds || !pool) return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    nk_setup(ctx, font);
Ivan Mahonin b53a5c
    ctx->memory = *cmds;
Ivan Mahonin b53a5c
    if (pool->type == NK_BUFFER_FIXED) {
Ivan Mahonin b53a5c
        /* take memory from buffer and alloc fixed pool */
Ivan Mahonin b53a5c
        nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
Ivan Mahonin b53a5c
    } else {
Ivan Mahonin b53a5c
        /* create dynamic pool from buffer allocator */
Ivan Mahonin b53a5c
        struct nk_allocator *alloc = &pool->pool;
Ivan Mahonin b53a5c
        nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    ctx->use_pool = nk_true;
Ivan Mahonin b53a5c
    return 1;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API nk_bool
Ivan Mahonin b53a5c
nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
Ivan Mahonin b53a5c
    const struct nk_user_font *font)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(alloc);
Ivan Mahonin b53a5c
    if (!alloc) return 0;
Ivan Mahonin b53a5c
    nk_setup(ctx, font);
Ivan Mahonin b53a5c
    nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
Ivan Mahonin b53a5c
    nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
Ivan Mahonin b53a5c
    ctx->use_pool = nk_true;
Ivan Mahonin b53a5c
    return 1;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
#ifdef NK_INCLUDE_COMMAND_USERDATA
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_set_user_data(struct nk_context *ctx, nk_handle handle)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
    ctx->userdata = handle;
Ivan Mahonin b53a5c
    if (ctx->current)
Ivan Mahonin b53a5c
        ctx->current->buffer.userdata = handle;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
#endif
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_free(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
    nk_buffer_free(&ctx->memory);
Ivan Mahonin b53a5c
    if (ctx->use_pool)
Ivan Mahonin b53a5c
        nk_pool_free(&ctx->pool);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    nk_zero(&ctx->input, sizeof(ctx->input));
Ivan Mahonin b53a5c
    nk_zero(&ctx->style, sizeof(ctx->style));
Ivan Mahonin b53a5c
    nk_zero(&ctx->memory, sizeof(ctx->memory));
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    ctx->seq = 0;
Ivan Mahonin b53a5c
    ctx->build = 0;
Ivan Mahonin b53a5c
    ctx->begin = 0;
Ivan Mahonin b53a5c
    ctx->end = 0;
Ivan Mahonin b53a5c
    ctx->active = 0;
Ivan Mahonin b53a5c
    ctx->current = 0;
Ivan Mahonin b53a5c
    ctx->freelist = 0;
Ivan Mahonin b53a5c
    ctx->count = 0;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API void
Ivan Mahonin b53a5c
nk_clear(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *iter;
Ivan Mahonin b53a5c
    struct nk_window *next;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    if (!ctx) return;
Ivan Mahonin b53a5c
    if (ctx->use_pool)
Ivan Mahonin b53a5c
        nk_buffer_clear(&ctx->memory);
Ivan Mahonin b53a5c
    else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    ctx->build = 0;
Ivan Mahonin b53a5c
    ctx->memory.calls = 0;
Ivan Mahonin b53a5c
    ctx->last_widget_state = 0;
Ivan Mahonin b53a5c
    ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
Ivan Mahonin b53a5c
    NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* garbage collector */
Ivan Mahonin b53a5c
    iter = ctx->begin;
Ivan Mahonin b53a5c
    while (iter) {
Ivan Mahonin b53a5c
        /* make sure valid minimized windows do not get removed */
Ivan Mahonin b53a5c
        if ((iter->flags & NK_WINDOW_MINIMIZED) &&
Ivan Mahonin b53a5c
            !(iter->flags & NK_WINDOW_CLOSED) &&
Ivan Mahonin b53a5c
            iter->seq == ctx->seq) {
Ivan Mahonin b53a5c
            iter = iter->next;
Ivan Mahonin b53a5c
            continue;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        /* remove hotness from hidden or closed windows*/
Ivan Mahonin b53a5c
        if (((iter->flags & NK_WINDOW_HIDDEN) ||
Ivan Mahonin b53a5c
            (iter->flags & NK_WINDOW_CLOSED)) &&
Ivan Mahonin b53a5c
            iter == ctx->active) {
Ivan Mahonin b53a5c
            ctx->active = iter->prev;
Ivan Mahonin b53a5c
            ctx->end = iter->prev;
Ivan Mahonin b53a5c
            if (!ctx->end)
Ivan Mahonin b53a5c
                ctx->begin = 0;
Ivan Mahonin b53a5c
            if (ctx->active)
Ivan Mahonin b53a5c
                ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        /* free unused popup windows */
Ivan Mahonin b53a5c
        if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
Ivan Mahonin b53a5c
            nk_free_window(ctx, iter->popup.win);
Ivan Mahonin b53a5c
            iter->popup.win = 0;
Ivan Mahonin b53a5c
        }
Ivan Mahonin b53a5c
        /* remove unused window state tables */
Ivan Mahonin b53a5c
        {struct nk_table *n, *it = iter->tables;
Ivan Mahonin b53a5c
        while (it) {
Ivan Mahonin b53a5c
            n = it->next;
Ivan Mahonin b53a5c
            if (it->seq != ctx->seq) {
Ivan Mahonin b53a5c
                nk_remove_table(iter, it);
Ivan Mahonin b53a5c
                nk_zero(it, sizeof(union nk_page_data));
Ivan Mahonin b53a5c
                nk_free_table(ctx, it);
Ivan Mahonin b53a5c
                if (it == iter->tables)
Ivan Mahonin b53a5c
                    iter->tables = n;
Ivan Mahonin b53a5c
            } it = n;
Ivan Mahonin b53a5c
        }}
Ivan Mahonin b53a5c
        /* window itself is not used anymore so free */
Ivan Mahonin b53a5c
        if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
Ivan Mahonin b53a5c
            next = iter->next;
Ivan Mahonin b53a5c
            nk_remove_window(ctx, iter);
Ivan Mahonin b53a5c
            nk_free_window(ctx, iter);
Ivan Mahonin b53a5c
            iter = next;
Ivan Mahonin b53a5c
        } else iter = iter->next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    ctx->seq++;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(buffer);
Ivan Mahonin b53a5c
    if (!ctx || !buffer) return;
Ivan Mahonin b53a5c
    buffer->begin = ctx->memory.allocated;
Ivan Mahonin b53a5c
    buffer->end = buffer->begin;
Ivan Mahonin b53a5c
    buffer->last = buffer->begin;
Ivan Mahonin b53a5c
    buffer->clip = nk_null_rect;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_start(struct nk_context *ctx, struct nk_window *win)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(win);
Ivan Mahonin b53a5c
    nk_start_buffer(ctx, &win->buffer);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_start_popup(struct nk_context *ctx, struct nk_window *win)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_popup_buffer *buf;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(win);
Ivan Mahonin b53a5c
    if (!ctx || !win) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* save buffer fill state for popup */
Ivan Mahonin b53a5c
    buf = &win->popup.buf;
Ivan Mahonin b53a5c
    buf->begin = win->buffer.end;
Ivan Mahonin b53a5c
    buf->end = win->buffer.end;
Ivan Mahonin b53a5c
    buf->parent = win->buffer.last;
Ivan Mahonin b53a5c
    buf->last = buf->begin;
Ivan Mahonin b53a5c
    buf->active = nk_true;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_popup_buffer *buf;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(win);
Ivan Mahonin b53a5c
    if (!ctx || !win) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    buf = &win->popup.buf;
Ivan Mahonin b53a5c
    buf->last = win->buffer.last;
Ivan Mahonin b53a5c
    buf->end = win->buffer.end;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(buffer);
Ivan Mahonin b53a5c
    if (!ctx || !buffer) return;
Ivan Mahonin b53a5c
    buffer->end = ctx->memory.allocated;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_finish(struct nk_context *ctx, struct nk_window *win)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_popup_buffer *buf;
Ivan Mahonin b53a5c
    struct nk_command *parent_last;
Ivan Mahonin b53a5c
    void *memory;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    NK_ASSERT(win);
Ivan Mahonin b53a5c
    if (!ctx || !win) return;
Ivan Mahonin b53a5c
    nk_finish_buffer(ctx, &win->buffer);
Ivan Mahonin b53a5c
    if (!win->popup.buf.active) return;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    buf = &win->popup.buf;
Ivan Mahonin b53a5c
    memory = ctx->memory.memory.ptr;
Ivan Mahonin b53a5c
    parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
Ivan Mahonin b53a5c
    parent_last->next = buf->end;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_LIB void
Ivan Mahonin b53a5c
nk_build(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *it = 0;
Ivan Mahonin b53a5c
    struct nk_command *cmd = 0;
Ivan Mahonin b53a5c
    nk_byte *buffer = 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    /* draw cursor overlay */
Ivan Mahonin b53a5c
    if (!ctx->style.cursor_active)
Ivan Mahonin b53a5c
        ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
Ivan Mahonin b53a5c
    if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
Ivan Mahonin b53a5c
        struct nk_rect mouse_bounds;
Ivan Mahonin b53a5c
        const struct nk_cursor *cursor = ctx->style.cursor_active;
Ivan Mahonin b53a5c
        nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
Ivan Mahonin b53a5c
        nk_start_buffer(ctx, &ctx->overlay);
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
Ivan Mahonin b53a5c
        mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
Ivan Mahonin b53a5c
        mouse_bounds.w = cursor->size.x;
Ivan Mahonin b53a5c
        mouse_bounds.h = cursor->size.y;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
Ivan Mahonin b53a5c
        nk_finish_buffer(ctx, &ctx->overlay);
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    /* build one big draw command list out of all window buffers */
Ivan Mahonin b53a5c
    it = ctx->begin;
Ivan Mahonin b53a5c
    buffer = (nk_byte*)ctx->memory.memory.ptr;
Ivan Mahonin b53a5c
    while (it != 0) {
Ivan Mahonin b53a5c
        struct nk_window *next = it->next;
Ivan Mahonin b53a5c
        if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)||
Ivan Mahonin b53a5c
            it->seq != ctx->seq)
Ivan Mahonin b53a5c
            goto cont;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last);
Ivan Mahonin b53a5c
        while (next && ((next->buffer.last == next->buffer.begin) ||
Ivan Mahonin b53a5c
            (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq))
Ivan Mahonin b53a5c
            next = next->next; /* skip empty command buffers */
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        if (next) cmd->next = next->buffer.begin;
Ivan Mahonin b53a5c
        cont: it = next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    /* append all popup draw commands into lists */
Ivan Mahonin b53a5c
    it = ctx->begin;
Ivan Mahonin b53a5c
    while (it != 0) {
Ivan Mahonin b53a5c
        struct nk_window *next = it->next;
Ivan Mahonin b53a5c
        struct nk_popup_buffer *buf;
Ivan Mahonin b53a5c
        if (!it->popup.buf.active)
Ivan Mahonin b53a5c
            goto skip;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
        buf = &it->popup.buf;
Ivan Mahonin b53a5c
        cmd->next = buf->begin;
Ivan Mahonin b53a5c
        cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
Ivan Mahonin b53a5c
        buf->active = nk_false;
Ivan Mahonin b53a5c
        skip: it = next;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    if (cmd) {
Ivan Mahonin b53a5c
        /* append overlay commands */
Ivan Mahonin b53a5c
        if (ctx->overlay.end != ctx->overlay.begin)
Ivan Mahonin b53a5c
            cmd->next = ctx->overlay.begin;
Ivan Mahonin b53a5c
        else cmd->next = ctx->memory.allocated;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
NK_API const struct nk_command*
Ivan Mahonin b53a5c
nk__begin(struct nk_context *ctx)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    struct nk_window *iter;
Ivan Mahonin b53a5c
    nk_byte *buffer;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx) return 0;
Ivan Mahonin b53a5c
    if (!ctx->count) return 0;
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
    buffer = (nk_byte*)ctx->memory.memory.ptr;
Ivan Mahonin b53a5c
    if (!ctx->build) {
Ivan Mahonin b53a5c
        nk_build(ctx);
Ivan Mahonin b53a5c
        ctx->build = nk_true;
Ivan Mahonin b53a5c
    }
Ivan Mahonin b53a5c
    iter = ctx->begin;
Ivan Mahonin b53a5c
    while (iter && ((iter->buffer.begin == iter->buffer.end) ||
Ivan Mahonin b53a5c
        (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq))
Ivan Mahonin b53a5c
        iter = iter->next;
Ivan Mahonin b53a5c
    if (!iter) return 0;
Ivan Mahonin b53a5c
    return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c
NK_API const struct nk_command*
Ivan Mahonin b53a5c
nk__next(struct nk_context *ctx, const struct nk_command *cmd)
Ivan Mahonin b53a5c
{
Ivan Mahonin b53a5c
    nk_byte *buffer;
Ivan Mahonin b53a5c
    const struct nk_command *next;
Ivan Mahonin b53a5c
    NK_ASSERT(ctx);
Ivan Mahonin b53a5c
    if (!ctx || !cmd || !ctx->count) return 0;
Ivan Mahonin b53a5c
    if (cmd->next >= ctx->memory.allocated) return 0;
Ivan Mahonin b53a5c
    buffer = (nk_byte*)ctx->memory.memory.ptr;
Ivan Mahonin b53a5c
    next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
Ivan Mahonin b53a5c
    return next;
Ivan Mahonin b53a5c
}
Ivan Mahonin b53a5c
Ivan Mahonin b53a5c