hs

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | LICENSE

nuklear_glfw_gl3.h (18855B)


      1 /*
      2  * Nuklear - 1.32.0 - public domain
      3  * no warrenty implied; use at your own risk.
      4  * authored from 2015-2016 by Micha Mettke
      5  */
      6 /*
      7  * ==============================================================
      8  *
      9  *                              API
     10  *
     11  * ===============================================================
     12  */
     13 #ifndef NK_GLFW_GL3_H_
     14 #define NK_GLFW_GL3_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 
     23 #ifndef NK_GLFW_TEXT_MAX
     24 #define NK_GLFW_TEXT_MAX 256
     25 #endif
     26 
     27 struct nk_glfw_device {
     28     struct nk_buffer cmds;
     29     struct nk_draw_null_texture null;
     30     GLuint vbo, vao, ebo;
     31     GLuint prog;
     32     GLuint vert_shdr;
     33     GLuint frag_shdr;
     34     GLint attrib_pos;
     35     GLint attrib_uv;
     36     GLint attrib_col;
     37     GLint uniform_tex;
     38     GLint uniform_proj;
     39     GLuint font_tex;
     40 };
     41 
     42 struct nk_glfw {
     43     GLFWwindow *win;
     44     int width, height;
     45     int display_width, display_height;
     46     struct nk_glfw_device ogl;
     47     struct nk_context ctx;
     48     struct nk_font_atlas atlas;
     49     struct nk_vec2 fb_scale;
     50     unsigned int text[NK_GLFW_TEXT_MAX];
     51     int text_len;
     52     struct nk_vec2 scroll;
     53     double last_button_click;
     54     int is_double_click_down;
     55     struct nk_vec2 double_click_pos;
     56 };
     57 
     58 NK_API struct nk_context*   nk_glfw3_init(struct nk_glfw* glfw, GLFWwindow *win, enum nk_glfw_init_state);
     59 NK_API void                 nk_glfw3_shutdown(struct nk_glfw* glfw);
     60 NK_API void                 nk_glfw3_font_stash_begin(struct nk_glfw* glfw, struct nk_font_atlas **atlas);
     61 NK_API void                 nk_glfw3_font_stash_end(struct nk_glfw* glfw);
     62 NK_API void                 nk_glfw3_new_frame(struct nk_glfw* glfw);
     63 NK_API void                 nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
     64 
     65 NK_API void                 nk_glfw3_device_destroy(struct nk_glfw* glfw);
     66 NK_API void                 nk_glfw3_device_create(struct nk_glfw* glfw);
     67 
     68 NK_API void                 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
     69 NK_API void                 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
     70 NK_API void                 nk_glfw3_mouse_button_callback(GLFWwindow *win, int button, int action, int mods);
     71 
     72 #endif
     73 /*
     74  * ==============================================================
     75  *
     76  *                          IMPLEMENTATION
     77  *
     78  * ===============================================================
     79  */
     80 #ifdef NK_GLFW_GL3_IMPLEMENTATION
     81 
     82 #ifndef NK_GLFW_DOUBLE_CLICK_LO
     83 #define NK_GLFW_DOUBLE_CLICK_LO 0.02
     84 #endif
     85 #ifndef NK_GLFW_DOUBLE_CLICK_HI
     86 #define NK_GLFW_DOUBLE_CLICK_HI 0.2
     87 #endif
     88 
     89 struct nk_glfw_vertex {
     90     float position[2];
     91     float uv[2];
     92     nk_byte col[4];
     93 };
     94 
     95 #ifdef __APPLE__
     96   #define NK_SHADER_VERSION "#version 150\n"
     97 #else
     98   #define NK_SHADER_VERSION "#version 300 es\n"
     99 #endif
    100 
    101 NK_API void
    102 nk_glfw3_device_create(struct nk_glfw* glfw)
    103 {
    104     GLint status;
    105     static const GLchar *vertex_shader =
    106         NK_SHADER_VERSION
    107         "uniform mat4 ProjMtx;\n"
    108         "in vec2 Position;\n"
    109         "in vec2 TexCoord;\n"
    110         "in vec4 Color;\n"
    111         "out vec2 Frag_UV;\n"
    112         "out vec4 Frag_Color;\n"
    113         "void main() {\n"
    114         "   Frag_UV = TexCoord;\n"
    115         "   Frag_Color = Color;\n"
    116         "   gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
    117         "}\n";
    118     static const GLchar *fragment_shader =
    119         NK_SHADER_VERSION
    120         "precision mediump float;\n"
    121         "uniform sampler2D Texture;\n"
    122         "in vec2 Frag_UV;\n"
    123         "in vec4 Frag_Color;\n"
    124         "out vec4 Out_Color;\n"
    125         "void main(){\n"
    126         "   Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
    127         "}\n";
    128 
    129     struct nk_glfw_device *dev = &glfw->ogl;
    130     nk_buffer_init_default(&dev->cmds);
    131     dev->prog = glCreateProgram();
    132     dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
    133     dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
    134     glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
    135     glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
    136     glCompileShader(dev->vert_shdr);
    137     glCompileShader(dev->frag_shdr);
    138     glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
    139     assert(status == GL_TRUE);
    140     glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
    141     assert(status == GL_TRUE);
    142     glAttachShader(dev->prog, dev->vert_shdr);
    143     glAttachShader(dev->prog, dev->frag_shdr);
    144     glLinkProgram(dev->prog);
    145     glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
    146     assert(status == GL_TRUE);
    147 
    148     dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
    149     dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
    150     dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
    151     dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
    152     dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
    153 
    154     {
    155         /* buffer setup */
    156         GLsizei vs = sizeof(struct nk_glfw_vertex);
    157         size_t vp = offsetof(struct nk_glfw_vertex, position);
    158         size_t vt = offsetof(struct nk_glfw_vertex, uv);
    159         size_t vc = offsetof(struct nk_glfw_vertex, col);
    160 
    161         glGenBuffers(1, &dev->vbo);
    162         glGenBuffers(1, &dev->ebo);
    163         glGenVertexArrays(1, &dev->vao);
    164 
    165         glBindVertexArray(dev->vao);
    166         glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
    167         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
    168 
    169         glEnableVertexAttribArray((GLuint)dev->attrib_pos);
    170         glEnableVertexAttribArray((GLuint)dev->attrib_uv);
    171         glEnableVertexAttribArray((GLuint)dev->attrib_col);
    172 
    173         glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
    174         glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
    175         glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
    176     }
    177 
    178     glBindTexture(GL_TEXTURE_2D, 0);
    179     glBindBuffer(GL_ARRAY_BUFFER, 0);
    180     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    181     glBindVertexArray(0);
    182 }
    183 
    184 NK_INTERN void
    185 nk_glfw3_device_upload_atlas(struct nk_glfw* glfw, const void *image, int width, int height)
    186 {
    187     struct nk_glfw_device *dev = &glfw->ogl;
    188     glGenTextures(1, &dev->font_tex);
    189     glBindTexture(GL_TEXTURE_2D, dev->font_tex);
    190     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    191     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    192     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
    193                 GL_RGBA, GL_UNSIGNED_BYTE, image);
    194 }
    195 
    196 NK_API void
    197 nk_glfw3_device_destroy(struct nk_glfw* glfw)
    198 {
    199     struct nk_glfw_device *dev = &glfw->ogl;
    200     glDetachShader(dev->prog, dev->vert_shdr);
    201     glDetachShader(dev->prog, dev->frag_shdr);
    202     glDeleteShader(dev->vert_shdr);
    203     glDeleteShader(dev->frag_shdr);
    204     glDeleteProgram(dev->prog);
    205     glDeleteTextures(1, &dev->font_tex);
    206     glDeleteBuffers(1, &dev->vbo);
    207     glDeleteBuffers(1, &dev->ebo);
    208     nk_buffer_free(&dev->cmds);
    209 }
    210 
    211 NK_API void
    212 nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
    213 {
    214     struct nk_glfw_device *dev = &glfw->ogl;
    215     struct nk_buffer vbuf, ebuf;
    216     GLfloat ortho[4][4] = {
    217         {2.0f, 0.0f, 0.0f, 0.0f},
    218         {0.0f,-2.0f, 0.0f, 0.0f},
    219         {0.0f, 0.0f,-1.0f, 0.0f},
    220         {-1.0f,1.0f, 0.0f, 1.0f},
    221     };
    222     ortho[0][0] /= (GLfloat)glfw->width;
    223     ortho[1][1] /= (GLfloat)glfw->height;
    224 
    225     /* setup global state */
    226     glEnable(GL_BLEND);
    227     glBlendEquation(GL_FUNC_ADD);
    228     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    229     glDisable(GL_CULL_FACE);
    230     glDisable(GL_DEPTH_TEST);
    231     glEnable(GL_SCISSOR_TEST);
    232     glActiveTexture(GL_TEXTURE0);
    233 
    234     /* setup program */
    235     glUseProgram(dev->prog);
    236     glUniform1i(dev->uniform_tex, 0);
    237     glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
    238     glViewport(0,0,(GLsizei)glfw->display_width,(GLsizei)glfw->display_height);
    239     {
    240         /* convert from command queue into draw list and draw to screen */
    241         const struct nk_draw_command *cmd;
    242         void *vertices, *elements;
    243         const nk_draw_index *offset = NULL;
    244 
    245         /* allocate vertex and element buffer */
    246         glBindVertexArray(dev->vao);
    247         glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
    248         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
    249 
    250         glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW);
    251         glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW);
    252 
    253         /* load draw vertices & elements directly into vertex + element buffer */
    254         vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    255         elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
    256         {
    257             /* fill convert configuration */
    258             struct nk_convert_config config;
    259             static const struct nk_draw_vertex_layout_element vertex_layout[] = {
    260                 {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
    261                 {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
    262                 {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
    263                 {NK_VERTEX_LAYOUT_END}
    264             };
    265             memset(&config, 0, sizeof(config));
    266             config.vertex_layout = vertex_layout;
    267             config.vertex_size = sizeof(struct nk_glfw_vertex);
    268             config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
    269             config.null = dev->null;
    270             config.circle_segment_count = 22;
    271             config.curve_segment_count = 22;
    272             config.arc_segment_count = 22;
    273             config.global_alpha = 1.0f;
    274             config.shape_AA = AA;
    275             config.line_AA = AA;
    276 
    277             /* setup buffers to load vertices and elements */
    278             nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer);
    279             nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer);
    280             nk_convert(&glfw->ctx, &dev->cmds, &vbuf, &ebuf, &config);
    281         }
    282         glUnmapBuffer(GL_ARRAY_BUFFER);
    283         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
    284 
    285         /* iterate over and execute each draw command */
    286         nk_draw_foreach(cmd, &glfw->ctx, &dev->cmds)
    287         {
    288             if (!cmd->elem_count) continue;
    289             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
    290             glScissor(
    291                 (GLint)(cmd->clip_rect.x * glfw->fb_scale.x),
    292                 (GLint)((glfw->height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw->fb_scale.y),
    293                 (GLint)(cmd->clip_rect.w * glfw->fb_scale.x),
    294                 (GLint)(cmd->clip_rect.h * glfw->fb_scale.y));
    295             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
    296             offset += cmd->elem_count;
    297         }
    298         nk_clear(&glfw->ctx);
    299         nk_buffer_clear(&dev->cmds);
    300     }
    301 
    302     /* default OpenGL state */
    303     glUseProgram(0);
    304     glBindBuffer(GL_ARRAY_BUFFER, 0);
    305     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    306     glBindVertexArray(0);
    307     glDisable(GL_BLEND);
    308     glDisable(GL_SCISSOR_TEST);
    309 }
    310 
    311 NK_API void
    312 nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
    313 {
    314     struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
    315     if (glfw->text_len < NK_GLFW_TEXT_MAX)
    316         glfw->text[glfw->text_len++] = codepoint;
    317 }
    318 
    319 NK_API void
    320 nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
    321 {
    322     struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
    323     (void)xoff;
    324     glfw->scroll.x += (float)xoff;
    325     glfw->scroll.y += (float)yoff;
    326 }
    327 
    328 NK_API void
    329 nk_glfw3_mouse_button_callback(GLFWwindow* win, int button, int action, int mods)
    330 {
    331     double x, y;
    332     if (button != GLFW_MOUSE_BUTTON_LEFT) return;
    333     struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
    334     glfwGetCursorPos(win, &x, &y);
    335     if (action == GLFW_PRESS)  {
    336         double dt = glfwGetTime() - glfw->last_button_click;
    337         if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI) {
    338             glfw->is_double_click_down = nk_true;
    339             glfw->double_click_pos = nk_vec2((float)x, (float)y);
    340         }
    341         glfw->last_button_click = glfwGetTime();
    342     } else glfw->is_double_click_down = nk_false;
    343 }
    344 
    345 NK_INTERN void
    346 nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
    347 {
    348     struct nk_glfw* glfw = usr.ptr;
    349     const char *text = glfwGetClipboardString(glfw->win);
    350     if (text) nk_textedit_paste(edit, text, nk_strlen(text));
    351     (void)usr;
    352 }
    353 
    354 NK_INTERN void
    355 nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len)
    356 {
    357     char *str = 0;
    358     if (!len) return;
    359     str = (char*)malloc((size_t)len+1);
    360     if (!str) return;
    361     memcpy(str, text, (size_t)len);
    362     str[len] = '\0';
    363     struct nk_glfw* glfw = usr.ptr;
    364     glfwSetClipboardString(glfw->win, str);
    365     free(str);
    366 }
    367 
    368 NK_API struct nk_context*
    369 nk_glfw3_init(struct nk_glfw* glfw, GLFWwindow *win, enum nk_glfw_init_state init_state)
    370 {
    371     glfwSetWindowUserPointer(win, glfw);
    372     glfw->win = win;
    373     if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
    374         glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
    375         glfwSetCharCallback(win, nk_glfw3_char_callback);
    376         glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
    377     }
    378     nk_init_default(&glfw->ctx, 0);
    379     glfw->ctx.clip.copy = nk_glfw3_clipboard_copy;
    380     glfw->ctx.clip.paste = nk_glfw3_clipboard_paste;
    381     glfw->ctx.clip.userdata = nk_handle_ptr(&glfw);
    382     glfw->last_button_click = 0;
    383     nk_glfw3_device_create(glfw);
    384 
    385     glfw->is_double_click_down = nk_false;
    386     glfw->double_click_pos = nk_vec2(0, 0);
    387 
    388     return &glfw->ctx;
    389 }
    390 
    391 NK_API void
    392 nk_glfw3_font_stash_begin(struct nk_glfw* glfw, struct nk_font_atlas **atlas)
    393 {
    394     nk_font_atlas_init_default(&glfw->atlas);
    395     nk_font_atlas_begin(&glfw->atlas);
    396     *atlas = &glfw->atlas;
    397 }
    398 
    399 NK_API void
    400 nk_glfw3_font_stash_end(struct nk_glfw* glfw)
    401 {
    402     const void *image; int w, h;
    403     image = nk_font_atlas_bake(&glfw->atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
    404     nk_glfw3_device_upload_atlas(glfw, image, w, h);
    405     nk_font_atlas_end(&glfw->atlas, nk_handle_id((int)glfw->ogl.font_tex), &glfw->ogl.null);
    406     if (glfw->atlas.default_font)
    407         nk_style_set_font(&glfw->ctx, &glfw->atlas.default_font->handle);
    408 }
    409 
    410 NK_API void
    411 nk_glfw3_new_frame(struct nk_glfw* glfw)
    412 {
    413     int i;
    414     double x, y;
    415     struct nk_context *ctx = &glfw->ctx;
    416     struct GLFWwindow *win = glfw->win;
    417 
    418     glfwGetWindowSize(win, &glfw->width, &glfw->height);
    419     glfwGetFramebufferSize(win, &glfw->display_width, &glfw->display_height);
    420     glfw->fb_scale.x = (float)glfw->display_width/(float)glfw->width;
    421     glfw->fb_scale.y = (float)glfw->display_height/(float)glfw->height;
    422 
    423     nk_input_begin(ctx);
    424     for (i = 0; i < glfw->text_len; ++i)
    425         nk_input_unicode(ctx, glfw->text[i]);
    426 
    427 #ifdef NK_GLFW_GL3_MOUSE_GRABBING
    428     /* optional grabbing behavior */
    429     if (ctx->input.mouse.grab)
    430         glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
    431     else if (ctx->input.mouse.ungrab)
    432         glfwSetInputMode(glfw->win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
    433 #endif
    434 
    435     nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
    436     nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
    437     nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
    438     nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
    439     nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
    440     nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
    441     nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
    442     nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
    443     nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
    444     nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
    445     nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
    446     nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
    447     nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
    448                                     glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
    449 
    450     if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
    451         glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
    452         nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
    453         nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
    454         nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
    455         nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
    456         nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
    457         nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
    458         nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
    459         nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
    460         nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
    461     } else {
    462         nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
    463         nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
    464         nk_input_key(ctx, NK_KEY_COPY, 0);
    465         nk_input_key(ctx, NK_KEY_PASTE, 0);
    466         nk_input_key(ctx, NK_KEY_CUT, 0);
    467         nk_input_key(ctx, NK_KEY_SHIFT, 0);
    468     }
    469 
    470     glfwGetCursorPos(win, &x, &y);
    471     nk_input_motion(ctx, (int)x, (int)y);
    472 #ifdef NK_GLFW_GL3_MOUSE_GRABBING
    473     if (ctx->input.mouse.grabbed) {
    474         glfwSetCursorPos(glfw->win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
    475         ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
    476         ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
    477     }
    478 #endif
    479     nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
    480     nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
    481     nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
    482     nk_input_button(ctx, NK_BUTTON_DOUBLE, (int)glfw->double_click_pos.x, (int)glfw->double_click_pos.y, glfw->is_double_click_down);
    483     nk_input_scroll(ctx, glfw->scroll);
    484     nk_input_end(&glfw->ctx);
    485     glfw->text_len = 0;
    486     glfw->scroll = nk_vec2(0,0);
    487 }
    488 
    489 NK_API
    490 void nk_glfw3_shutdown(struct nk_glfw* glfw)
    491 {
    492     nk_font_atlas_clear(&glfw->atlas);
    493     nk_free(&glfw->ctx);
    494     nk_glfw3_device_destroy(glfw);
    495     memset(glfw, 0, sizeof(*glfw));
    496 }
    497 
    498 #endif