payredu

Cross-platform ledger GUI written in c99
git clone git@getsh.org:payredu.git
Log | Files | Refs | README

nuklear_glfw_gl2.h (14146B)


      1 /*
      2  * Nuklear - v1.32.0 - public domain
      3  * no warrenty implied; use at your own risk.
      4  * authored from 2015-2017 by Micha Mettke
      5  */
      6 /*
      7  * ==============================================================
      8  *
      9  *                              API
     10  *
     11  * ===============================================================
     12  */
     13 #ifndef NK_GLFW_GL2_H_
     14 #define NK_GLFW_GL2_H_
     15 
     16 #include <GLFW/glfw3.h>
     17 
     18 enum nk_glfw_init_state{
     19     NK_GLFW3_DEFAULT = 0,
     20     NK_GLFW3_INSTALL_CALLBACKS
     21 };
     22 NK_API struct nk_context*   nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
     23 NK_API void                 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
     24 NK_API void                 nk_glfw3_font_stash_end(void);
     25 
     26 NK_API void                 nk_glfw3_new_frame(void);
     27 NK_API void                 nk_glfw3_render(enum nk_anti_aliasing);
     28 NK_API void                 nk_glfw3_shutdown(void);
     29 
     30 NK_API void                 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
     31 NK_API void                 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
     32 
     33 #endif
     34 
     35 /*
     36  * ==============================================================
     37  *
     38  *                          IMPLEMENTATION
     39  *
     40  * ===============================================================
     41  */
     42 #ifdef NK_GLFW_GL2_IMPLEMENTATION
     43 
     44 #ifndef NK_GLFW_TEXT_MAX
     45 #define NK_GLFW_TEXT_MAX 256
     46 #endif
     47 #ifndef NK_GLFW_DOUBLE_CLICK_LO
     48 #define NK_GLFW_DOUBLE_CLICK_LO 0.02
     49 #endif
     50 #ifndef NK_GLFW_DOUBLE_CLICK_HI
     51 #define NK_GLFW_DOUBLE_CLICK_HI 0.2
     52 #endif
     53 
     54 struct nk_glfw_device {
     55     struct nk_buffer cmds;
     56     struct nk_draw_null_texture tex_null;
     57     GLuint font_tex;
     58 };
     59 
     60 struct nk_glfw_vertex {
     61     float position[2];
     62     float uv[2];
     63     nk_byte col[4];
     64 };
     65 
     66 static struct nk_glfw {
     67     GLFWwindow *win;
     68     int width, height;
     69     int display_width, display_height;
     70     struct nk_glfw_device ogl;
     71     struct nk_context ctx;
     72     struct nk_font_atlas atlas;
     73     struct nk_vec2 fb_scale;
     74     unsigned int text[NK_GLFW_TEXT_MAX];
     75     int text_len;
     76     struct nk_vec2 scroll;
     77     double last_button_click;
     78     int is_double_click_down;
     79     struct nk_vec2 double_click_pos;
     80 } glfw;
     81 
     82 NK_INTERN void
     83 nk_glfw3_device_upload_atlas(const void *image, int width, int height)
     84 {
     85     struct nk_glfw_device *dev = &glfw.ogl;
     86     glGenTextures(1, &dev->font_tex);
     87     glBindTexture(GL_TEXTURE_2D, dev->font_tex);
     88     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     89     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     90     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
     91                 GL_RGBA, GL_UNSIGNED_BYTE, image);
     92 }
     93 
     94 NK_API void
     95 nk_glfw3_render(enum nk_anti_aliasing AA)
     96 {
     97     /* setup global state */
     98     struct nk_glfw_device *dev = &glfw.ogl;
     99     glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
    100     glDisable(GL_CULL_FACE);
    101     glDisable(GL_DEPTH_TEST);
    102     glEnable(GL_SCISSOR_TEST);
    103     glEnable(GL_BLEND);
    104     glEnable(GL_TEXTURE_2D);
    105     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    106 
    107     /* setup viewport/project */
    108     glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
    109     glMatrixMode(GL_PROJECTION);
    110     glPushMatrix();
    111     glLoadIdentity();
    112     glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
    113     glMatrixMode(GL_MODELVIEW);
    114     glPushMatrix();
    115     glLoadIdentity();
    116 
    117     glEnableClientState(GL_VERTEX_ARRAY);
    118     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    119     glEnableClientState(GL_COLOR_ARRAY);
    120     {
    121         GLsizei vs = sizeof(struct nk_glfw_vertex);
    122         size_t vp = offsetof(struct nk_glfw_vertex, position);
    123         size_t vt = offsetof(struct nk_glfw_vertex, uv);
    124         size_t vc = offsetof(struct nk_glfw_vertex, col);
    125 
    126         /* convert from command queue into draw list and draw to screen */
    127         const struct nk_draw_command *cmd;
    128         const nk_draw_index *offset = NULL;
    129         struct nk_buffer vbuf, ebuf;
    130 
    131         /* fill convert configuration */
    132         struct nk_convert_config config;
    133         static const struct nk_draw_vertex_layout_element vertex_layout[] = {
    134             {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
    135             {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
    136             {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
    137             {NK_VERTEX_LAYOUT_END}
    138         };
    139         memset(&config, 0, sizeof(config));
    140         config.vertex_layout = vertex_layout;
    141         config.vertex_size = sizeof(struct nk_glfw_vertex);
    142         config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
    143         config.tex_null = dev->tex_null;
    144         config.circle_segment_count = 22;
    145         config.curve_segment_count = 22;
    146         config.arc_segment_count = 22;
    147         config.global_alpha = 1.0f;
    148         config.shape_AA = AA;
    149         config.line_AA = AA;
    150 
    151         /* convert shapes into vertexes */
    152         nk_buffer_init_default(&vbuf);
    153         nk_buffer_init_default(&ebuf);
    154         nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
    155 
    156         /* setup vertex buffer pointer */
    157         {const void *vertices = nk_buffer_memory_const(&vbuf);
    158         glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
    159         glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
    160         glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
    161 
    162         /* iterate over and execute each draw command */
    163         offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
    164         nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
    165         {
    166             if (!cmd->elem_count) continue;
    167             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
    168             glScissor(
    169                 (GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
    170                 (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
    171                 (GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
    172                 (GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
    173             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
    174             offset += cmd->elem_count;
    175         }
    176         nk_clear(&glfw.ctx);
    177         nk_buffer_clear(&dev->cmds);
    178         nk_buffer_free(&vbuf);
    179         nk_buffer_free(&ebuf);
    180     }
    181 
    182     /* default OpenGL state */
    183     glDisableClientState(GL_VERTEX_ARRAY);
    184     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    185     glDisableClientState(GL_COLOR_ARRAY);
    186 
    187     glDisable(GL_CULL_FACE);
    188     glDisable(GL_DEPTH_TEST);
    189     glDisable(GL_SCISSOR_TEST);
    190     glDisable(GL_BLEND);
    191     glDisable(GL_TEXTURE_2D);
    192 
    193     glBindTexture(GL_TEXTURE_2D, 0);
    194     glMatrixMode(GL_MODELVIEW);
    195     glPopMatrix();
    196     glMatrixMode(GL_PROJECTION);
    197     glPopMatrix();
    198     glPopAttrib();
    199 }
    200 
    201 NK_API void
    202 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
    203 {
    204     (void)win;
    205     if (glfw.text_len < NK_GLFW_TEXT_MAX)
    206         glfw.text[glfw.text_len++] = codepoint;
    207 }
    208 
    209 NK_API void
    210 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
    211 {
    212     (void)win; (void)xoff;
    213     glfw.scroll.x += (float)xoff;
    214     glfw.scroll.y += (float)yoff;
    215 }
    216 
    217 NK_API void
    218 nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
    219 {
    220     double x, y;
    221     NK_UNUSED(mods);
    222     if (button != GLFW_MOUSE_BUTTON_LEFT) return;
    223     glfwGetCursorPos(window, &x, &y);
    224     if (action == GLFW_PRESS)  {
    225         double dt = glfwGetTime() - glfw.last_button_click;
    226         if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
    227             glfw.is_double_click_down = nk_true;
    228             glfw.double_click_pos = nk_vec2((float)x, (float)y);
    229         }
    230         glfw.last_button_click = glfwGetTime();
    231     } else glfw.is_double_click_down = nk_false;
    232 }
    233 
    234 NK_INTERN void
    235 nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
    236 {
    237     const char *text = glfwGetClipboardString(glfw.win);
    238     if (text) nk_textedit_paste(edit, text, nk_strlen(text));
    239     (void)usr;
    240 }
    241 
    242 NK_INTERN void
    243 nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len)
    244 {
    245     char *str = 0;
    246     (void)usr;
    247     if (!len) return;
    248     str = (char*)malloc((size_t)len+1);
    249     if (!str) return;
    250     memcpy(str, text, (size_t)len);
    251     str[len] = '\0';
    252     glfwSetClipboardString(glfw.win, str);
    253     free(str);
    254 }
    255 
    256 NK_API struct nk_context*
    257 nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
    258 {
    259     glfw.win = win;
    260     if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
    261         glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
    262         glfwSetCharCallback(win, nk_glfw3_char_callback);
    263         glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
    264     }
    265     nk_init_default(&glfw.ctx, 0);
    266     glfw.ctx.clip.copy = nk_glfw3_clipboard_copy;
    267     glfw.ctx.clip.paste = nk_glfw3_clipboard_paste;
    268     glfw.ctx.clip.userdata = nk_handle_ptr(0);
    269     nk_buffer_init_default(&glfw.ogl.cmds);
    270 
    271     glfw.is_double_click_down = nk_false;
    272     glfw.double_click_pos = nk_vec2(0, 0);
    273 
    274     return &glfw.ctx;
    275 }
    276 
    277 NK_API void
    278 nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
    279 {
    280     nk_font_atlas_init_default(&glfw.atlas);
    281     nk_font_atlas_begin(&glfw.atlas);
    282     *atlas = &glfw.atlas;
    283 }
    284 
    285 NK_API void
    286 nk_glfw3_font_stash_end(void)
    287 {
    288     const void *image; int w, h;
    289     image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
    290     nk_glfw3_device_upload_atlas(image, w, h);
    291     nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.tex_null);
    292     if (glfw.atlas.default_font)
    293         nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
    294 }
    295 
    296 NK_API void
    297 nk_glfw3_new_frame(void)
    298 {
    299     int i;
    300     double x, y;
    301     struct nk_context *ctx = &glfw.ctx;
    302     struct GLFWwindow *win = glfw.win;
    303 
    304     glfwGetWindowSize(win, &glfw.width, &glfw.height);
    305     glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
    306     glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
    307     glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
    308 
    309     nk_input_begin(ctx);
    310     for (i = 0; i < glfw.text_len; ++i)
    311         nk_input_unicode(ctx, glfw.text[i]);
    312 
    313     /* optional grabbing behavior */
    314     if (ctx->input.mouse.grab)
    315         glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
    316     else if (ctx->input.mouse.ungrab)
    317         glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    318 
    319     nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
    320     nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
    321     nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
    322     nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
    323     nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
    324     nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
    325     nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
    326     nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
    327     nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
    328     nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
    329     nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
    330     nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
    331     nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
    332                                     glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
    333 
    334     if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
    335         glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
    336         nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
    337         nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
    338         nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
    339         nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
    340         nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
    341         nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
    342         nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
    343         nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
    344         nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
    345     } else {
    346         nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
    347         nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
    348         nk_input_key(ctx, NK_KEY_COPY, 0);
    349         nk_input_key(ctx, NK_KEY_PASTE, 0);
    350         nk_input_key(ctx, NK_KEY_CUT, 0);
    351         nk_input_key(ctx, NK_KEY_SHIFT, 0);
    352     }
    353 
    354     glfwGetCursorPos(win, &x, &y);
    355     nk_input_motion(ctx, (int)x, (int)y);
    356     if (ctx->input.mouse.grabbed) {
    357         glfwSetCursorPos(glfw.win, (double)ctx->input.mouse.prev.x, (double)ctx->input.mouse.prev.y);
    358         ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
    359         ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
    360     }
    361 
    362     nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
    363     nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
    364     nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
    365     nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw.double_click_pos.x, (int)glfw.double_click_pos.y, glfw.is_double_click_down);
    366     nk_input_scroll(ctx, glfw.scroll);
    367     nk_input_end(&glfw.ctx);
    368     glfw.text_len = 0;
    369     glfw.scroll = nk_vec2(0,0);
    370 }
    371 
    372 NK_API
    373 void nk_glfw3_shutdown(void)
    374 {
    375     struct nk_glfw_device *dev = &glfw.ogl;
    376     nk_font_atlas_clear(&glfw.atlas);
    377     nk_free(&glfw.ctx);
    378     glDeleteTextures(1, &dev->font_tex);
    379     nk_buffer_free(&dev->cmds);
    380     memset(&glfw, 0, sizeof(glfw));
    381 }
    382 
    383 #endif