Browse Source

Restructured demos and examples

All platform and renderbackend independent examples are now optional
demos for all platforms in `demo/`. Moving some demos from `example/`
provides an easier way to test GUI concepts for users and simplifies
maintenance.
vurtun 9 years ago
parent
commit
8a01de120a

+ 30 - 0
demo/allegro5/main.c

@@ -30,6 +30,24 @@
 #include "nuklear_allegro.h"
 #include "nuklear_allegro.h"
 #include "nuklear_allegro.c"
 #include "nuklear_allegro.c"
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 int
 int
 main(void)
 main(void)
 {
 {
@@ -65,6 +83,12 @@ main(void)
     nk_allegro_font_stash_end();
     nk_allegro_font_stash_end();
     /*nk_style_set_font(ctx, &droid->handle);*/}
     /*nk_style_set_font(ctx, &droid->handle);*/}
 
 
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     background = nk_rgb(28,48,62);
     background = nk_rgb(28,48,62);
     while (running)
     while (running)
     {
     {
@@ -113,6 +137,12 @@ main(void)
         }
         }
         nk_end(ctx);}
         nk_end(ctx);}
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         {float bg[4];
         {float bg[4];
         nk_color_fv(bg, background);
         nk_color_fv(bg, background);

+ 66 - 0
demo/calculator.c

@@ -0,0 +1,66 @@
+/* nuklear - v1.00 - public domain */
+static void
+calculator(struct nk_context *ctx)
+{
+    struct nk_panel layout;
+    if (nk_begin(ctx, &layout, "Calculator", nk_rect(10, 10, 180, 250),
+        NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE))
+    {
+        static int set = 0, prev = 0, op = 0;
+        static const char numbers[] = "789456123";
+        static const char ops[] = "+-*/";
+        static double a = 0, b = 0;
+        static double *current = &a;
+
+        size_t i = 0;
+        int solve = 0;
+        {int len; char buffer[256];
+        nk_layout_row_dynamic(ctx, 35, 1);
+        len = snprintf(buffer, 256, "%.2f", *current);
+        nk_edit_string(ctx, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_float);
+        buffer[len] = 0;
+        *current = atof(buffer);}
+
+        nk_layout_row_dynamic(ctx, 35, 4);
+        for (i = 0; i < 16; ++i) {
+            if (i >= 12 && i < 15) {
+                if (i > 12) continue;
+                if (nk_button_label(ctx, "C", NK_BUTTON_DEFAULT)) {
+                    a = b = op = 0; current = &a; set = 0;
+                } if (nk_button_label(ctx, "0", NK_BUTTON_DEFAULT)) {
+                    *current = *current*10.0f; set = 0;
+                }
+                if (nk_button_label(ctx, "=", NK_BUTTON_DEFAULT)) {
+                    solve = 1; prev = op; op = 0;
+                }
+            } else if (((i+1) % 4)) {
+                if (nk_button_text(ctx, &numbers[(i/4)*3+i%4], 1, NK_BUTTON_DEFAULT)) {
+                    *current = *current * 10.0f + numbers[(i/4)*3+i%4] - '0';
+                    set = 0;
+                }
+            } else if (nk_button_text(ctx, &ops[i/4], 1, NK_BUTTON_DEFAULT)) {
+                if (!set) {
+                    if (current != &b) {
+                        current = &b;
+                    } else {
+                        prev = op;
+                        solve = 1;
+                    }
+                }
+                op = ops[i/4];
+                set = 1;
+            }
+        }
+        if (solve) {
+            if (prev == '+') a = a + b;
+            if (prev == '-') a = a - b;
+            if (prev == '*') a = a * b;
+            if (prev == '/') a = a / b;
+            current = &a;
+            if (set) current = &b;
+            b = 0; set = 0;
+        }
+    }
+    nk_end(ctx);
+}
+

+ 46 - 23
demo/d3d11/main.c

@@ -24,6 +24,24 @@
 #include "nuklear_d3d11.h"
 #include "nuklear_d3d11.h"
 #include "nuklear_d3d11.c"
 #include "nuklear_d3d11.c"
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 static IDXGISwapChain *swap_chain;
 static IDXGISwapChain *swap_chain;
 static ID3D11Device *device;
 static ID3D11Device *device;
 static ID3D11DeviceContext *context;
 static ID3D11DeviceContext *context;
@@ -160,12 +178,17 @@ int main(void)
     nk_d3d11_font_stash_end();
     nk_d3d11_font_stash_end();
     /*nk_style_set_font(ctx, &droid->handle)*/;}
     /*nk_style_set_font(ctx, &droid->handle)*/;}
 
 
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     background = nk_rgb(28,48,62);
     background = nk_rgb(28,48,62);
     while (running)
     while (running)
     {
     {
-        MSG msg;
-
         /* Input */
         /* Input */
+        MSG msg;
         nk_input_begin(ctx);
         nk_input_begin(ctx);
         while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
         while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
         {
         {
@@ -213,28 +236,28 @@ int main(void)
         nk_end(ctx);}
         nk_end(ctx);}
         if (nk_window_is_closed(ctx, "Demo")) break;
         if (nk_window_is_closed(ctx, "Demo")) break;
 
 
-        /* Draw */
-        {
-            float bg[4];
-            nk_color_fv(bg, background);
-            ID3D11DeviceContext_ClearRenderTargetView(context, rt_view, bg);
-            ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rt_view, NULL);
-            nk_d3d11_render(context, NK_ANTI_ALIASING_ON);
-
-            hr = IDXGISwapChain_Present(swap_chain, 1, 0);
-            if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED)
-            {
-                /* to recover from this, you'll need to recreate device and all the resources */
-                MessageBoxW(NULL, L"D3D11 device is lost or removed!", L"Error", 0);
-                break;
-            }
-            else if (hr == DXGI_STATUS_OCCLUDED)
-            {
-                /* window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage */
-                Sleep(10);
-            }
-            assert(SUCCEEDED(hr));
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
+        {/* Draw */
+        float bg[4];
+        nk_color_fv(bg, background);
+        ID3D11DeviceContext_ClearRenderTargetView(context, rt_view, bg);
+        ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rt_view, NULL);
+        nk_d3d11_render(context, NK_ANTI_ALIASING_ON);
+        hr = IDXGISwapChain_Present(swap_chain, 1, 0);
+        if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED) {
+            /* to recover from this, you'll need to recreate device and all the resources */
+            MessageBoxW(NULL, L"D3D11 device is lost or removed!", L"Error", 0);
+            break;
+        } else if (hr == DXGI_STATUS_OCCLUDED) {
+            /* window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage */
+            Sleep(10);
         }
         }
+        assert(SUCCEEDED(hr));}
     }
     }
 
 
     ID3D11DeviceContext_ClearState(context);
     ID3D11DeviceContext_ClearState(context);

+ 37 - 15
demo/gdi/main.c

@@ -12,6 +12,24 @@
 #include "nuklear_gdi.h"
 #include "nuklear_gdi.h"
 #include "nuklear_gdi.c"
 #include "nuklear_gdi.c"
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 static LRESULT CALLBACK
 static LRESULT CALLBACK
 WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
 WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
 {
 {
@@ -63,31 +81,29 @@ int main(void)
     /* GUI */
     /* GUI */
     font = nk_gdifont_create("Arial", 14);
     font = nk_gdifont_create("Arial", 14);
     ctx = nk_gdi_init(font, dc, WINDOW_WIDTH, WINDOW_HEIGHT);
     ctx = nk_gdi_init(font, dc, WINDOW_WIDTH, WINDOW_HEIGHT);
+
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     while (running)
     while (running)
     {
     {
-        MSG msg;
-
         /* Input */
         /* Input */
+        MSG msg;
         nk_input_begin(ctx);
         nk_input_begin(ctx);
-        if (needs_refresh == 0)
-        {
+        if (needs_refresh == 0) {
             if (GetMessageW(&msg, NULL, 0, 0) <= 0)
             if (GetMessageW(&msg, NULL, 0, 0) <= 0)
-            {
                 running = 0;
                 running = 0;
-            }
-            else
-            {
+            else {
                 TranslateMessage(&msg);
                 TranslateMessage(&msg);
                 DispatchMessageW(&msg);
                 DispatchMessageW(&msg);
             }
             }
             needs_refresh = 1;
             needs_refresh = 1;
-        }
-        else
-        {
-            needs_refresh = 0;
-        }
-        while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
-        {
+        } else needs_refresh = 0;
+
+        while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
             if (msg.message == WM_QUIT)
             if (msg.message == WM_QUIT)
                 running = 0;
                 running = 0;
             TranslateMessage(&msg);
             TranslateMessage(&msg);
@@ -118,6 +134,12 @@ int main(void)
         nk_end(ctx);}
         nk_end(ctx);}
         if (nk_window_is_closed(ctx, "Demo")) break;
         if (nk_window_is_closed(ctx, "Demo")) break;
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         nk_gdi_render(nk_rgb(30,30,30));
         nk_gdi_render(nk_rgb(30,30,30));
     }
     }

+ 37 - 19
demo/gdip/main.c

@@ -12,19 +12,34 @@
 #include "nuklear_gdip.h"
 #include "nuklear_gdip.h"
 #include "nuklear_gdip.c"
 #include "nuklear_gdip.c"
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 static LRESULT CALLBACK
 static LRESULT CALLBACK
 WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
 WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
 {
 {
-    switch (msg)
-    {
+    switch (msg) {
     case WM_DESTROY:
     case WM_DESTROY:
         PostQuitMessage(0);
         PostQuitMessage(0);
         return 0;
         return 0;
     }
     }
-
     if (nk_gdip_handle_event(wnd, msg, wparam, lparam))
     if (nk_gdip_handle_event(wnd, msg, wparam, lparam))
         return 0;
         return 0;
-
     return DefWindowProcW(wnd, msg, wparam, lparam);
     return DefWindowProcW(wnd, msg, wparam, lparam);
 }
 }
 
 
@@ -61,31 +76,28 @@ int main(void)
     ctx = nk_gdip_init(wnd, WINDOW_WIDTH, WINDOW_HEIGHT);
     ctx = nk_gdip_init(wnd, WINDOW_WIDTH, WINDOW_HEIGHT);
     font = nk_gdipfont_create("Arial", 12);
     font = nk_gdipfont_create("Arial", 12);
     nk_gdip_set_font(font);
     nk_gdip_set_font(font);
+
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     while (running)
     while (running)
     {
     {
-        MSG msg;
-
         /* Input */
         /* Input */
+        MSG msg;
         nk_input_begin(ctx);
         nk_input_begin(ctx);
-        if (needs_refresh == 0)
-        {
+        if (needs_refresh == 0) {
             if (GetMessageW(&msg, NULL, 0, 0) <= 0)
             if (GetMessageW(&msg, NULL, 0, 0) <= 0)
-            {
                 running = 0;
                 running = 0;
-            }
-            else
-            {
+            else {
                 TranslateMessage(&msg);
                 TranslateMessage(&msg);
                 DispatchMessageW(&msg);
                 DispatchMessageW(&msg);
             }
             }
             needs_refresh = 1;
             needs_refresh = 1;
-        }
-        else
-        {
-            needs_refresh = 0;
-        }
-        while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
-        {
+        } else needs_refresh = 0;
+        while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
             if (msg.message == WM_QUIT)
             if (msg.message == WM_QUIT)
                 running = 0;
                 running = 0;
             TranslateMessage(&msg);
             TranslateMessage(&msg);
@@ -116,6 +128,12 @@ int main(void)
         nk_end(ctx);}
         nk_end(ctx);}
         if (nk_window_is_closed(ctx, "Demo")) break;
         if (nk_window_is_closed(ctx, "Demo")) break;
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         nk_gdip_render(NK_ANTI_ALIASING_ON, nk_rgb(30,30,30));
         nk_gdip_render(NK_ANTI_ALIASING_ON, nk_rgb(30,30,30));
     }
     }

+ 40 - 5
demo/glfw/main.c

@@ -23,15 +23,37 @@
 #include "nuklear_glfw.h"
 #include "nuklear_glfw.h"
 #include "nuklear_glfw.c"
 #include "nuklear_glfw.c"
 
 
-#define WINDOW_WIDTH 800
-#define WINDOW_HEIGHT 600
+#define WINDOW_WIDTH 1200
+#define WINDOW_HEIGHT 800
 
 
 #define MAX_VERTEX_BUFFER 512 * 1024
 #define MAX_VERTEX_BUFFER 512 * 1024
 #define MAX_ELEMENT_BUFFER 128 * 1024
 #define MAX_ELEMENT_BUFFER 128 * 1024
 
 
-static void error_callback(int e, const char *d){
-    printf("Error %d: %s\n", e, d);
-}
+#define UNUSED(a) (void)a
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) < (b) ? (b) : (a))
+#define LEN(a) (sizeof(a)/sizeof(a)[0])
+
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
+static void error_callback(int e, const char *d)
+{printf("Error %d: %s\n", e, d);}
 
 
 int main(void)
 int main(void)
 {
 {
@@ -78,6 +100,12 @@ int main(void)
     nk_glfw3_font_stash_end();
     nk_glfw3_font_stash_end();
     /*nk_style_set_font(ctx, &droid->handle);*/}
     /*nk_style_set_font(ctx, &droid->handle);*/}
 
 
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     background = nk_rgb(28,48,62);
     background = nk_rgb(28,48,62);
     while (!glfwWindowShouldClose(win))
     while (!glfwWindowShouldClose(win))
     {
     {
@@ -97,6 +125,7 @@ int main(void)
             nk_layout_row_static(ctx, 30, 80, 1);
             nk_layout_row_static(ctx, 30, 80, 1);
             if (nk_button_label(ctx, "button", NK_BUTTON_DEFAULT))
             if (nk_button_label(ctx, "button", NK_BUTTON_DEFAULT))
                 fprintf(stdout, "button pressed\n");
                 fprintf(stdout, "button pressed\n");
+
             nk_layout_row_dynamic(ctx, 30, 2);
             nk_layout_row_dynamic(ctx, 30, 2);
             if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
             if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
             if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
             if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
@@ -121,6 +150,12 @@ int main(void)
         }
         }
         nk_end(ctx);}
         nk_end(ctx);}
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         {float bg[4];
         {float bg[4];
         nk_color_fv(bg, background);
         nk_color_fv(bg, background);

+ 22 - 12
demo/glfw/nuklear_glfw.c

@@ -1,4 +1,13 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
 #include <string.h>
 #include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <math.h>
+#include <time.h>
+#include <limits.h>
 
 
 #define NK_IMPLEMENTATION
 #define NK_IMPLEMENTATION
 #include "nuklear_glfw.h"
 #include "nuklear_glfw.h"
@@ -27,6 +36,7 @@ static struct nk_glfw {
     struct nk_glfw_device ogl;
     struct nk_glfw_device ogl;
     struct nk_context ctx;
     struct nk_context ctx;
     struct nk_font_atlas atlas;
     struct nk_font_atlas atlas;
+    struct nk_vec2 fb_scale;
     unsigned int text[NK_GLFW_TEXT_MAX];
     unsigned int text[NK_GLFW_TEXT_MAX];
     int text_len;
     int text_len;
     float scroll;
     float scroll;
@@ -152,16 +162,14 @@ NK_API void
 nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
 nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
 {
 {
     struct nk_glfw_device *dev = &glfw.ogl;
     struct nk_glfw_device *dev = &glfw.ogl;
-    int width, height;
     GLfloat ortho[4][4] = {
     GLfloat ortho[4][4] = {
         {2.0f, 0.0f, 0.0f, 0.0f},
         {2.0f, 0.0f, 0.0f, 0.0f},
         {0.0f,-2.0f, 0.0f, 0.0f},
         {0.0f,-2.0f, 0.0f, 0.0f},
         {0.0f, 0.0f,-1.0f, 0.0f},
         {0.0f, 0.0f,-1.0f, 0.0f},
         {-1.0f,1.0f, 0.0f, 1.0f},
         {-1.0f,1.0f, 0.0f, 1.0f},
     };
     };
-    glfwGetWindowSize(glfw.win, &width, &height);
-    ortho[0][0] /= (GLfloat)width;
-    ortho[1][1] /= (GLfloat)height;
+    ortho[0][0] /= (GLfloat)glfw.width;
+    ortho[1][1] /= (GLfloat)glfw.height;
 
 
     /* setup global state */
     /* setup global state */
     glEnable(GL_BLEND);
     glEnable(GL_BLEND);
@@ -176,6 +184,7 @@ nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element
     glUseProgram(dev->prog);
     glUseProgram(dev->prog);
     glUniform1i(dev->uniform_tex, 0);
     glUniform1i(dev->uniform_tex, 0);
     glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
     glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
+    glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
     {
     {
         /* convert from command queue into draw list and draw to screen */
         /* convert from command queue into draw list and draw to screen */
         const struct nk_draw_command *cmd;
         const struct nk_draw_command *cmd;
@@ -215,12 +224,15 @@ nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element
         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
 
 
         /* iterate over and execute each draw command */
         /* iterate over and execute each draw command */
-        nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds) {
+        nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
+        {
             if (!cmd->elem_count) continue;
             if (!cmd->elem_count) continue;
             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
-            glScissor((GLint)cmd->clip_rect.x,
-                height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h),
-                (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h);
+            glScissor(
+                (GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
+                (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
+                (GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
+                (GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
             offset += cmd->elem_count;
             offset += cmd->elem_count;
         }
         }
@@ -319,6 +331,8 @@ nk_glfw3_new_frame(void)
 
 
     glfwGetWindowSize(win, &glfw.width, &glfw.height);
     glfwGetWindowSize(win, &glfw.width, &glfw.height);
     glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
     glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
+    glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
+    glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
 
 
     nk_input_begin(ctx);
     nk_input_begin(ctx);
     for (i = 0; i < glfw.text_len; ++i)
     for (i = 0; i < glfw.text_len; ++i)
@@ -356,16 +370,12 @@ nk_glfw3_new_frame(void)
     }
     }
 
 
     glfwGetCursorPos(win, &x, &y);
     glfwGetCursorPos(win, &x, &y);
-    x *= (double)(int)((float)glfw.display_width/(float)glfw.width);
-    y *= (double)(int)((float)glfw.display_height/(float)glfw.height);
     nk_input_motion(ctx, (int)x, (int)y);
     nk_input_motion(ctx, (int)x, (int)y);
-
     nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
     nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
     nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
     nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
     nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
     nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
     nk_input_scroll(ctx, glfw.scroll);
     nk_input_scroll(ctx, glfw.scroll);
     nk_input_end(&glfw.ctx);
     nk_input_end(&glfw.ctx);
-
     glfw.text_len = 0;
     glfw.text_len = 0;
     glfw.scroll = 0;
     glfw.scroll = 0;
 }
 }

+ 345 - 0
demo/node_editor.c

@@ -0,0 +1,345 @@
+/* nuklear - v1.00 - public domain */
+/* This is a simple node editor just to show a simple implementation and that
+ * it is possible to achieve it with this library. While all nodes inside this
+ * example use a simple color modifier as content you could change them
+ * to have your custom content depending on the node time.
+ * Biggest difference to most usual implementation is that this example does
+ * not have connectors on the right position of the property that it links.
+ * This is mainly done out of laziness and could be implemented as well but
+ * requires calculating the position of all rows and add connectors.
+ * In addition adding and removing nodes is quite limited at the
+ * moment since it is based on a simple fixed array. If this is to be converted
+ * into something more serious it is probably best to extend it.*/
+struct node {
+    int ID;
+    char name[32];
+    struct nk_rect bounds;
+    float value;
+    struct nk_color color;
+    int input_count;
+    int output_count;
+    struct node *next;
+    struct node *prev;
+};
+
+struct node_link {
+    int input_id;
+    int input_slot;
+    int output_id;
+    int output_slot;
+    struct nk_vec2 in;
+    struct nk_vec2 out;
+};
+
+struct node_linking {
+    int active;
+    struct node *node;
+    int input_id;
+    int input_slot;
+};
+
+struct node_editor {
+    int initialized;
+    struct node node_buf[32];
+    struct node_link links[64];
+    struct node *begin;
+    struct node *end;
+    int node_count;
+    int link_count;
+    struct nk_rect bounds;
+    struct node *selected;
+    int show_grid;
+    struct nk_vec2 scrolling;
+    struct node_linking linking;
+};
+static struct node_editor nodeEditor;
+
+static void
+node_editor_push(struct node_editor *editor, struct node *node)
+{
+    if (!editor->begin) {
+        node->next = NULL;
+        node->prev = NULL;
+        editor->begin = node;
+        editor->end = node;
+    } else {
+        node->prev = editor->end;
+        if (editor->end)
+            editor->end->next = node;
+        node->next = NULL;
+        editor->end = node;
+    }
+}
+
+static void
+node_editor_pop(struct node_editor *editor, struct node *node)
+{
+    if (node->next)
+        node->next->prev = node->prev;
+    if (node->prev)
+        node->prev->next = node->next;
+    if (editor->end == node)
+        editor->end = node->prev;
+    if (editor->begin == node)
+        editor->begin = node->next;
+    node->next = NULL;
+    node->prev = NULL;
+}
+
+static struct node*
+node_editor_find(struct node_editor *editor, int ID)
+{
+    struct node *iter = editor->begin;
+    while (iter) {
+        if (iter->ID == ID)
+            return iter;
+        iter = iter->next;
+    }
+    return NULL;
+}
+
+static void
+node_editor_add(struct node_editor *editor, const char *name, struct nk_rect bounds,
+    struct nk_color col, int in_count, int out_count)
+{
+    static int IDs = 0;
+    struct node *node;
+    assert((nk_size)editor->node_count < LEN(editor->node_buf));
+    node = &editor->node_buf[editor->node_count++];
+    node->ID = IDs++;
+    node->value = 0;
+    node->color = nk_rgb(255, 0, 0);
+    node->input_count = in_count;
+    node->output_count = out_count;
+    node->color = col;
+    node->bounds = bounds;
+    strcpy(node->name, name);
+    node_editor_push(editor, node);
+}
+
+static void
+node_editor_link(struct node_editor *editor, int in_id, int in_slot,
+    int out_id, int out_slot)
+{
+    struct node_link *link;
+    assert((nk_size)editor->link_count < LEN(editor->links));
+    link = &editor->links[editor->link_count++];
+    link->input_id = in_id;
+    link->input_slot = in_slot;
+    link->output_id = out_id;
+    link->output_slot = out_slot;
+}
+
+static void
+node_editor_init(struct node_editor *editor)
+{
+    memset(editor, 0, sizeof(*editor));
+    editor->begin = NULL;
+    editor->end = NULL;
+    node_editor_add(editor, "Source", nk_rect(40, 10, 180, 220), nk_rgb(255, 0, 0), 0, 1);
+    node_editor_add(editor, "Source", nk_rect(40, 260, 180, 220), nk_rgb(0, 255, 0), 0, 1);
+    node_editor_add(editor, "Combine", nk_rect(400, 100, 180, 220), nk_rgb(0,0,255), 2, 2);
+    node_editor_link(editor, 0, 0, 2, 0);
+    node_editor_link(editor, 1, 0, 2, 1);
+    editor->show_grid = nk_true;
+}
+
+static int
+node_editor(struct nk_context *ctx)
+{
+    int n = 0;
+    struct nk_rect total_space;
+    const struct nk_input *in = &ctx->input;
+    struct nk_command_buffer *canvas;
+    struct node *updated = 0;
+    struct nk_panel layout;
+    struct node_editor *nodedit = &nodeEditor;
+
+    if (!nodeEditor.initialized) {
+        node_editor_init(&nodeEditor);
+        nodeEditor.initialized = 1;
+    }
+
+    if (nk_begin(ctx, &layout, "NodeEdit", nk_rect(0, 0, 800, 600),
+        NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE))
+    {
+        /* allocate complete window space */
+        canvas = nk_window_get_canvas(ctx);
+        total_space = nk_window_get_content_region(ctx);
+        nk_layout_space_begin(ctx, NK_STATIC, total_space.h, nodedit->node_count);
+        {
+            struct nk_panel node, menu;
+            struct node *it = nodedit->begin;
+            struct nk_rect size = nk_layout_space_bounds(ctx);
+
+            if (nodedit->show_grid) {
+                /* display grid */
+                float x, y;
+                const float grid_size = 32.0f;
+                const struct nk_color grid_color = nk_rgb(50, 50, 50);
+                for (x = (float)fmod(size.x - nodedit->scrolling.x, grid_size); x < size.w; x += grid_size)
+                    nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, 1.0f, grid_color);
+                for (y = (float)fmod(size.y - nodedit->scrolling.y, grid_size); y < size.h; y += grid_size)
+                    nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, 1.0f, grid_color);
+            }
+
+            /* execute each node as a movable group */
+            while (it) {
+                /* calculate scrolled node window position and size */
+                nk_layout_space_push(ctx, nk_rect(it->bounds.x - nodedit->scrolling.x,
+                    it->bounds.y - nodedit->scrolling.y, it->bounds.w, it->bounds.h));
+
+                /* execute node window */
+                if (nk_group_begin(ctx, &node, it->name, NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE))
+                {
+                    /* always have last selected node on top */
+                    if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, node.bounds) &&
+                        (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT,
+                        nk_layout_space_rect_to_screen(ctx, node.bounds)))) &&
+                        nodedit->end != it)
+                    {
+                        updated = it;
+                    }
+
+                    /* ================= NODE CONTENT =====================*/
+                    nk_layout_row_dynamic(ctx, 25, 1);
+                    nk_button_color(ctx, it->color, NK_BUTTON_DEFAULT);
+                    it->color.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, it->color.r, 255, 1,1);
+                    it->color.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, it->color.g, 255, 1,1);
+                    it->color.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, it->color.b, 255, 1,1);
+                    it->color.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, it->color.a, 255, 1,1);
+                    /* ====================================================*/
+                    nk_group_end(ctx);
+                }
+                {
+                    /* node connector and linking */
+                    float space;
+                    struct nk_rect bounds;
+                    bounds = nk_layout_space_rect_to_local(ctx, node.bounds);
+                    bounds.x += nodedit->scrolling.x - ctx->style.window.border;
+                    bounds.y += nodedit->scrolling.y - ctx->style.window.border;
+                    bounds.w += 2*ctx->style.window.border;
+                    bounds.h += 2*ctx->style.window.border;
+
+                    it->bounds = bounds;
+
+                    /* output connector */
+                    space = node.bounds.h / (float)((it->output_count) + 1);
+                    for (n = 0; n < it->output_count; ++n) {
+                        struct nk_rect circle;
+                        circle.x = node.bounds.x + node.bounds.w-4;
+                        circle.y = node.bounds.y + space * (float)(n+1);
+                        circle.w = 8; circle.h = 8;
+                        nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100));
+
+                        /* start linking process */
+                        if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) {
+                            nodedit->linking.active = nk_true;
+                            nodedit->linking.node = it;
+                            nodedit->linking.input_id = it->ID;
+                            nodedit->linking.input_slot = n;
+                        }
+
+                        /* draw curve from linked node slot to mouse position */
+                        if (nodedit->linking.active && nodedit->linking.node == it &&
+                            nodedit->linking.input_slot == n) {
+                            struct nk_vec2 l0 = nk_vec2(circle.x + 3, circle.y + 3);
+                            struct nk_vec2 l1 = in->mouse.pos;
+                            nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y,
+                                l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100));
+                        }
+                    }
+
+                    /* input connector */
+                    space = node.bounds.h / (float)((it->input_count) + 1);
+                    for (n = 0; n < it->input_count; ++n) {
+                        struct nk_rect circle;
+                        circle.x = node.bounds.x-4;
+                        circle.y = node.bounds.y + space * (float)(n+1);
+                        circle.w = 8; circle.h = 8;
+                        nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100));
+                        if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) &&
+                            nk_input_is_mouse_hovering_rect(in, circle) &&
+                            nodedit->linking.active && nodedit->linking.node != it) {
+                            nodedit->linking.active = nk_false;
+                            node_editor_link(nodedit, nodedit->linking.input_id,
+                                nodedit->linking.input_slot, it->ID, n);
+                        }
+                    }
+                }
+                it = it->next;
+            }
+
+            /* reset linking connection */
+            if (nodedit->linking.active && nk_input_is_mouse_released(in, NK_BUTTON_LEFT)) {
+                nodedit->linking.active = nk_false;
+                nodedit->linking.node = NULL;
+                fprintf(stdout, "linking failed\n");
+            }
+
+            /* draw each link */
+            for (n = 0; n < nodedit->link_count; ++n) {
+                struct node_link *link = &nodedit->links[n];
+                struct node *ni = node_editor_find(nodedit, link->input_id);
+                struct node *no = node_editor_find(nodedit, link->output_id);
+                float spacei = node.bounds.h / (float)((ni->output_count) + 1);
+                float spaceo = node.bounds.h / (float)((no->input_count) + 1);
+                struct nk_vec2 l0 = nk_layout_space_to_screen(ctx,
+                    nk_vec2(ni->bounds.x + ni->bounds.w, 3.0f + ni->bounds.y + spacei * (float)(link->input_slot+1)));
+                struct nk_vec2 l1 = nk_layout_space_to_screen(ctx,
+                    nk_vec2(no->bounds.x, 3.0f + no->bounds.y + spaceo * (float)(link->output_slot+1)));
+
+                l0.x -= nodedit->scrolling.x;
+                l0.y -= nodedit->scrolling.y;
+                l1.x -= nodedit->scrolling.x;
+                l1.y -= nodedit->scrolling.y;
+                nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y,
+                    l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100));
+            }
+
+            if (updated) {
+                /* reshuffle nodes to have least recently selected node on top */
+                node_editor_pop(nodedit, updated);
+                node_editor_push(nodedit, updated);
+            }
+
+            /* node selection */
+            if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ctx))) {
+                it = nodedit->begin;
+                nodedit->selected = NULL;
+                nodedit->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200);
+                while (it) {
+                    struct nk_rect b = nk_layout_space_rect_to_screen(ctx, it->bounds);
+                    b.x -= nodedit->scrolling.x;
+                    b.y -= nodedit->scrolling.y;
+                    if (nk_input_is_mouse_hovering_rect(in, b))
+                        nodedit->selected = it;
+                    it = it->next;
+                }
+            }
+
+            /* contextual menu */
+            if (nk_contextual_begin(ctx, &menu, 0, nk_vec2(100, 220), nk_window_get_bounds(ctx))) {
+                const char *grid_option[] = {"Show Grid", "Hide Grid"};
+                nk_layout_row_dynamic(ctx, 25, 1);
+                if (nk_contextual_item_label(ctx, "New", NK_TEXT_CENTERED))
+                    node_editor_add(nodedit, "New", nk_rect(400, 260, 180, 220),
+                            nk_rgb(255, 255, 255), 1, 2);
+                if (nk_contextual_item_label(ctx, grid_option[nodedit->show_grid],NK_TEXT_CENTERED))
+                    nodedit->show_grid = !nodedit->show_grid;
+                nk_contextual_end(ctx);
+            }
+        }
+        nk_layout_space_end(ctx);
+
+        /* window content scrolling */
+        if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ctx)) &&
+            nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) {
+            nodedit->scrolling.x += in->mouse.delta.x;
+            nodedit->scrolling.y += in->mouse.delta.y;
+        }
+    }
+    nk_end(ctx);
+    return !nk_window_is_closed(ctx, "NodeEdit");
+}
+

+ 3 - 390
example/overview.c → demo/overview.c

@@ -1,52 +1,5 @@
-/* nuklear - v1.00 - public domain */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <math.h>
-#include <time.h>
-#include <limits.h>
-
-#include <GL/glew.h>
-#include <GLFW/glfw3.h>
-
-#define NK_INCLUDE_FIXED_TYPES
-#define NK_INCLUDE_STANDARD_IO
-#define NK_INCLUDE_DEFAULT_ALLOCATOR
-#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
-#define NK_INCLUDE_FONT_BAKING
-#define NK_INCLUDE_DEFAULT_FONT
-#define NK_IMPLEMENTATION
-#include "../nuklear.h"
-
-/* macros */
-#define WINDOW_WIDTH 800
-#define WINDOW_HEIGHT 600
-
-#define MAX_VERTEX_MEMORY 512 * 1024
-#define MAX_ELEMENT_MEMORY 128 * 1024
-
-#define UNUSED(a) (void)a
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) < (b) ? (b) : (a))
-#define LEN(a) (sizeof(a)/sizeof(a)[0])
-
-#ifdef __APPLE__
-  #define NK_SHADER_VERSION "#version 150\n"
-#else
-  #define NK_SHADER_VERSION "#version 300 es\n"
-#endif
-
-/* ===============================================================
- *
- *                          GUI
- *
- * ===============================================================*/
 static int
 static int
-overview_window(struct nk_context *ctx)
+overview(struct nk_context *ctx)
 {
 {
     struct nk_panel menu;
     struct nk_panel menu;
 
 
@@ -76,7 +29,7 @@ overview_window(struct nk_context *ctx)
     if (minimizable) window_flags |= NK_WINDOW_MINIMIZABLE;
     if (minimizable) window_flags |= NK_WINDOW_MINIMIZABLE;
     if (close) window_flags |= NK_WINDOW_CLOSABLE;
     if (close) window_flags |= NK_WINDOW_CLOSABLE;
 
 
-    if (nk_begin(ctx, &layout, "Demo", nk_rect(10, 10, 400, 750), window_flags))
+    if (nk_begin(ctx, &layout, "Overview", nk_rect(10, 10, 400, 750), window_flags))
     {
     {
         if (show_menu)
         if (show_menu)
         {
         {
@@ -1130,346 +1083,6 @@ overview_window(struct nk_context *ctx)
         }
         }
     }
     }
     nk_end(ctx);
     nk_end(ctx);
-    return !nk_window_is_closed(ctx, "Demo");
-}
-
-/* ===============================================================
- *
- *                          DEVICE
- *
- * ===============================================================*/
-struct device {
-    struct nk_buffer cmds;
-    struct nk_draw_null_texture null;
-    GLuint vbo, vao, ebo;
-    GLuint prog;
-    GLuint vert_shdr;
-    GLuint frag_shdr;
-    GLint attrib_pos;
-    GLint attrib_uv;
-    GLint attrib_col;
-    GLint uniform_tex;
-    GLint uniform_proj;
-    GLuint font_tex;
-};
-
-static void
-device_init(struct device *dev)
-{
-    GLint status;
-    static const GLchar *vertex_shader =
-        NK_SHADER_VERSION
-        "uniform mat4 ProjMtx;\n"
-        "in vec2 Position;\n"
-        "in vec2 TexCoord;\n"
-        "in vec4 Color;\n"
-        "out vec2 Frag_UV;\n"
-        "out vec4 Frag_Color;\n"
-        "void main() {\n"
-        "   Frag_UV = TexCoord;\n"
-        "   Frag_Color = Color;\n"
-        "   gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
-        "}\n";
-    static const GLchar *fragment_shader =
-        NK_SHADER_VERSION
-        "precision mediump float;\n"
-        "uniform sampler2D Texture;\n"
-        "in vec2 Frag_UV;\n"
-        "in vec4 Frag_Color;\n"
-        "out vec4 Out_Color;\n"
-        "void main(){\n"
-        "   Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
-        "}\n";
-
-    nk_buffer_init_default(&dev->cmds);
-    dev->prog = glCreateProgram();
-    dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
-    dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
-    glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
-    glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
-    glCompileShader(dev->vert_shdr);
-    glCompileShader(dev->frag_shdr);
-    glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
-    assert(status == GL_TRUE);
-    glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
-    assert(status == GL_TRUE);
-    glAttachShader(dev->prog, dev->vert_shdr);
-    glAttachShader(dev->prog, dev->frag_shdr);
-    glLinkProgram(dev->prog);
-    glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
-    assert(status == GL_TRUE);
-
-    dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
-    dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
-    dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
-    dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
-    dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
-
-    {
-        /* buffer setup */
-        GLsizei vs = sizeof(struct nk_draw_vertex);
-        size_t vp = offsetof(struct nk_draw_vertex, position);
-        size_t vt = offsetof(struct nk_draw_vertex, uv);
-        size_t vc = offsetof(struct nk_draw_vertex, col);
-
-        glGenBuffers(1, &dev->vbo);
-        glGenBuffers(1, &dev->ebo);
-        glGenVertexArrays(1, &dev->vao);
-
-        glBindVertexArray(dev->vao);
-        glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
-
-        glEnableVertexAttribArray((GLuint)dev->attrib_pos);
-        glEnableVertexAttribArray((GLuint)dev->attrib_uv);
-        glEnableVertexAttribArray((GLuint)dev->attrib_col);
-
-        glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
-        glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
-        glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
-    }
-
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glBindVertexArray(0);
-}
-
-static void
-device_upload_atlas(struct device *dev, const void *image, int width, int height)
-{
-    glGenTextures(1, &dev->font_tex);
-    glBindTexture(GL_TEXTURE_2D, dev->font_tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, image);
-}
-
-static void
-device_shutdown(struct device *dev)
-{
-    glDetachShader(dev->prog, dev->vert_shdr);
-    glDetachShader(dev->prog, dev->frag_shdr);
-    glDeleteShader(dev->vert_shdr);
-    glDeleteShader(dev->frag_shdr);
-    glDeleteProgram(dev->prog);
-    glDeleteTextures(1, &dev->font_tex);
-    glDeleteBuffers(1, &dev->vbo);
-    glDeleteBuffers(1, &dev->ebo);
-    nk_buffer_free(&dev->cmds);
-}
-
-static void
-device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
-    enum nk_anti_aliasing AA)
-{
-    GLint last_prog, last_tex;
-    GLint last_ebo, last_vbo, last_vao;
-    GLfloat ortho[4][4] = {
-        {2.0f, 0.0f, 0.0f, 0.0f},
-        {0.0f,-2.0f, 0.0f, 0.0f},
-        {0.0f, 0.0f,-1.0f, 0.0f},
-        {-1.0f,1.0f, 0.0f, 1.0f},
-    };
-    ortho[0][0] /= (GLfloat)width;
-    ortho[1][1] /= (GLfloat)height;
-
-    /* save previous opengl state */
-    glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
-    glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex);
-    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao);
-    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo);
-    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo);
-
-    /* setup global state */
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glDisable(GL_CULL_FACE);
-    glDisable(GL_DEPTH_TEST);
-    glEnable(GL_SCISSOR_TEST);
-    glActiveTexture(GL_TEXTURE0);
-
-    /* setup program */
-    glUseProgram(dev->prog);
-    glUniform1i(dev->uniform_tex, 0);
-    glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
-    {
-        /* convert from command queue into draw list and draw to screen */
-        const struct nk_draw_command *cmd;
-        void *vertices, *elements;
-        const nk_draw_index *offset = NULL;
-
-        /* allocate vertex and element buffer */
-        glBindVertexArray(dev->vao);
-        glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
-
-        glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
-
-        /* load draw vertices & elements directly into vertex + element buffer */
-        vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-        elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
-        {
-            /* fill converting configuration */
-            struct nk_convert_config config;
-            memset(&config, 0, sizeof(config));
-            config.global_alpha = 1.0f;
-            config.shape_AA = AA;
-            config.line_AA = AA;
-            config.circle_segment_count = 22;
-            config.curve_segment_count = 22;
-            config.arc_segment_count = 22;
-            config.null = dev->null;
-
-            /* setup buffers to load vertices and elements */
-            {struct nk_buffer vbuf, ebuf;
-            nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
-            nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
-            nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);}
-        }
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-
-        /* iterate over and execute each draw command */
-        nk_draw_foreach(cmd, ctx, &dev->cmds) {
-            if (!cmd->elem_count) continue;
-            glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
-            glScissor((GLint)cmd->clip_rect.x,
-                height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h),
-                (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h);
-            glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
-            offset += cmd->elem_count;
-        }
-        nk_clear(ctx);
-    }
-
-    /* restore old state */
-    glUseProgram((GLuint)last_prog);
-    glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
-    glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
-    glBindVertexArray((GLuint)last_vao);
-    glDisable(GL_SCISSOR_TEST);
-}
-
-
-/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/
-static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);}
-static void text_input(GLFWwindow *win, unsigned int codepoint)
-{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);}
-static void scroll_input(GLFWwindow *win, double _, double yoff)
-{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);}
-
-int main(int argc, char *argv[])
-{
-    /* Platform */
-    static GLFWwindow *win;
-    int width = 0, height = 0;
-    int display_width, display_height;
-
-    /* GUI */
-    struct device device;
-    struct nk_context ctx;
-    struct nk_font *font;
-    struct nk_font_atlas atlas;
-
-    /* GLFW */
-    glfwSetErrorCallback(error_callback);
-    if (!glfwInit()) {
-        fprintf(stdout, "[GFLW] failed to init!\n");
-        exit(1);
-    }
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#ifdef __APPLE__
-    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-#endif
-    win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL);
-    glfwMakeContextCurrent(win);
-    glfwSetWindowUserPointer(win, &ctx);
-    glfwSetCharCallback(win, text_input);
-    glfwSetScrollCallback(win, scroll_input);
-
-    /* OpenGL */
-    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
-    glewExperimental = 1;
-    if (glewInit() != GLEW_OK) {
-        fprintf(stderr, "Failed to setup GLEW\n");
-        exit(1);
-    }
-
-    {/* GUI */
-    device_init(&device);
-    {const void *image; int w, h;
-    struct nk_font_config cfg = nk_font_config(0);
-    cfg.oversample_h = 3; cfg.oversample_v = 2;
-    nk_font_atlas_init_default(&atlas);
-    nk_font_atlas_begin(&atlas);
-    font = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 14.0f, &cfg);
-    image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
-    device_upload_atlas(&device, image, w, h);
-    nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);}
-    nk_init_default(&ctx, &font->handle);}
-
-    while (!glfwWindowShouldClose(win))
-    {
-        /* Input */
-        {double x, y;
-        nk_input_begin(&ctx);
-        glfwPollEvents();
-        glfwGetWindowSize(win, &width, &height);
-        glfwGetFramebufferSize(win, &display_width, &display_height);
-
-        nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
-        if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
-            glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL)) {
-            nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_SHIFT, 1);
-        } else {
-            nk_input_key(&ctx, NK_KEY_COPY, 0);
-            nk_input_key(&ctx, NK_KEY_PASTE, 0);
-            nk_input_key(&ctx, NK_KEY_CUT, 0);
-            nk_input_key(&ctx, NK_KEY_SHIFT, 0);
-        }
-        glfwGetCursorPos(win, &x, &y);
-        x *= (double)(int)((float)display_width/(float)width);
-        y *= (double)(int)((float)display_height/(float)height);
-
-        nk_input_motion(&ctx, (int)x, (int)y);
-        nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
-        nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
-        nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
-        nk_input_end(&ctx);}
-
-        /* GUI */
-        if (!overview_window(&ctx)) break;
-
-        /* Draw */
-        glViewport(0, 0, width, height);
-        glClear(GL_COLOR_BUFFER_BIT);
-        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-        device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON);
-        glfwSwapBuffers(win);
-    }
-
-    nk_font_atlas_clear(&atlas);
-    nk_free(&ctx);
-    device_shutdown(&device);
-    glfwTerminate();
-    return 0;
+    return !nk_window_is_closed(ctx, "Overview");
 }
 }
 
 

+ 30 - 0
demo/sdl/main.c

@@ -30,6 +30,24 @@
 #define MAX_VERTEX_MEMORY 512 * 1024
 #define MAX_VERTEX_MEMORY 512 * 1024
 #define MAX_ELEMENT_MEMORY 128 * 1024
 #define MAX_ELEMENT_MEMORY 128 * 1024
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 int
 int
 main(int argc, char* argv[])
 main(int argc, char* argv[])
 {
 {
@@ -77,6 +95,12 @@ main(int argc, char* argv[])
     nk_sdl_font_stash_end();
     nk_sdl_font_stash_end();
     /*nk_style_set_font(ctx, &roboto->handle)*/;}
     /*nk_style_set_font(ctx, &roboto->handle)*/;}
 
 
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     background = nk_rgb(28,48,62);
     background = nk_rgb(28,48,62);
     while (running)
     while (running)
     {
     {
@@ -125,6 +149,12 @@ main(int argc, char* argv[])
         }
         }
         nk_end(ctx);}
         nk_end(ctx);}
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         {float bg[4];
         {float bg[4];
         nk_color_fv(bg, background);
         nk_color_fv(bg, background);

+ 31 - 0
demo/sdl1.2_gfx/main.c

@@ -21,6 +21,24 @@
 #define WINDOW_WIDTH 800
 #define WINDOW_WIDTH 800
 #define WINDOW_HEIGHT 600
 #define WINDOW_HEIGHT 600
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 int
 int
 main(void)
 main(void)
 {
 {
@@ -43,6 +61,13 @@ main(void)
 
 
     ctx = nk_sdl_init(screen_surface);
     ctx = nk_sdl_init(screen_surface);
     background = nk_rgb(28,48,62);
     background = nk_rgb(28,48,62);
+
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     while (running)
     while (running)
     {
     {
         /* Input */
         /* Input */
@@ -93,6 +118,12 @@ main(void)
         }
         }
         nk_end(ctx);}
         nk_end(ctx);}
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         nk_color_fv(bg, background);
         nk_color_fv(bg, background);
         nk_sdl_render(nk_rgb(30,30,30));
         nk_sdl_render(nk_rgb(30,30,30));

+ 0 - 0
example/style.c → demo/style.c


+ 38 - 1
demo/x11/main.c

@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdarg.h>
 #include <string.h>
 #include <string.h>
+#include <limits.h>
 #include <time.h>
 #include <time.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <unistd.h>
@@ -18,10 +19,16 @@
 #define WINDOW_HEIGHT 600
 #define WINDOW_HEIGHT 600
 
 
 #define NK_INCLUDE_FIXED_TYPES
 #define NK_INCLUDE_FIXED_TYPES
+#define NK_INCLUDE_STANDARD_IO
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #define NK_INCLUDE_DEFAULT_ALLOCATOR
 #include "nuklear_xlib.h"
 #include "nuklear_xlib.h"
 #include "nuklear_xlib.c"
 #include "nuklear_xlib.c"
 
 
+#define UNUSED(a) (void)a
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) < (b) ? (b) : (a))
+#define LEN(a) (sizeof(a)/sizeof(a)[0])
+
 typedef struct XWindow XWindow;
 typedef struct XWindow XWindow;
 struct XWindow {
 struct XWindow {
     Display *dpy;
     Display *dpy;
@@ -75,6 +82,24 @@ sleep_for(long t)
     while(-1 == nanosleep(&req, &req));
     while(-1 == nanosleep(&req, &req));
 }
 }
 
 
+/* ===============================================================
+ *
+ *                          EXAMPLE
+ *
+ * ===============================================================*/
+/* This are some code examples to provide a small overview of what can be
+ * done with this library. To try out an example uncomment the include
+ * and the corresponding function. */
+/*#include "../style.c"*/
+/*#include "../calculator.c"*/
+/*#include "../overview.c"*/
+/*#include "../node_editor.c"*/
+
+/* ===============================================================
+ *
+ *                          DEMO
+ *
+ * ===============================================================*/
 int
 int
 main(void)
 main(void)
 {
 {
@@ -108,10 +133,16 @@ main(void)
     xw.width = (unsigned int)xw.attr.width;
     xw.width = (unsigned int)xw.attr.width;
     xw.height = (unsigned int)xw.attr.height;
     xw.height = (unsigned int)xw.attr.height;
 
 
-
     /* GUI */
     /* GUI */
     xw.font = nk_xfont_create(xw.dpy, "fixed");
     xw.font = nk_xfont_create(xw.dpy, "fixed");
     ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, xw.width, xw.height);
     ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, xw.width, xw.height);
+
+    /* style.c */
+    /*set_style(ctx, THEME_WHITE);*/
+    /*set_style(ctx, THEME_RED);*/
+    /*set_style(ctx, THEME_BLUE);*/
+    /*set_style(ctx, THEME_DARK);*/
+
     while (running)
     while (running)
     {
     {
         /* Input */
         /* Input */
@@ -146,6 +177,12 @@ main(void)
         nk_end(ctx);}
         nk_end(ctx);}
         if (nk_window_is_closed(ctx, "Demo")) break;
         if (nk_window_is_closed(ctx, "Demo")) break;
 
 
+        /* -------------- EXAMPLES ---------------- */
+        /*calculator(ctx);*/
+        /*overview(ctx);*/
+        /*node_editor(ctx);*/
+        /* ----------------------------------------- */
+
         /* Draw */
         /* Draw */
         XClearWindow(xw.dpy, xw.win);
         XClearWindow(xw.dpy, xw.win);
         nk_xlib_render(xw.win, nk_rgb(30,30,30));
         nk_xlib_render(xw.win, nk_rgb(30,30,30));

+ 1 - 16
example/Makefile

@@ -13,29 +13,14 @@ else
 	endif
 	endif
 endif
 endif
 
 
-all: node_editor file_browser overview extended
-node_editor:
-	@mkdir -p bin
-	rm -f bin/node_editor $(OBJS)
-	$(CC) $(CFLAGS) -o bin/node_editor node_editor.c $(LIBS)
-
+all: file_browser extended
 file_browser:
 file_browser:
 	@mkdir -p bin
 	@mkdir -p bin
 	rm -f bin/file_browser $(OBJS)
 	rm -f bin/file_browser $(OBJS)
 	$(CC) $(CFLAGS) -o bin/file_browser file_browser.c $(LIBS)
 	$(CC) $(CFLAGS) -o bin/file_browser file_browser.c $(LIBS)
 
 
-overview:
-	@mkdir -p bin
-	rm -f bin/overview $(OBJS)
-	$(CC) $(CFLAGS) -o bin/overview overview.c $(LIBS)
-
 extended:
 extended:
 	@mkdir -p bin
 	@mkdir -p bin
 	rm -f bin/extended $(OBJS)
 	rm -f bin/extended $(OBJS)
 	$(CC) $(CFLAGS) -o bin/extended extended.c $(LIBS)
 	$(CC) $(CFLAGS) -o bin/extended extended.c $(LIBS)
 
 
-calculator:
-	@mkdir -p bin
-	rm -f bin/calculator $(OBJS)
-	$(CC) $(CFLAGS) -o bin/calculator calculator.c $(LIBS)
-

+ 0 - 438
example/calculator.c

@@ -1,438 +0,0 @@
-/* nuklear - v1.00 - public domain */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <math.h>
-#include <time.h>
-#include <limits.h>
-
-#include <GL/glew.h>
-#include <GLFW/glfw3.h>
-
-#define NK_INCLUDE_FIXED_TYPES
-#define NK_INCLUDE_STANDARD_IO
-#define NK_INCLUDE_DEFAULT_ALLOCATOR
-#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
-#define NK_INCLUDE_FONT_BAKING
-#define NK_INCLUDE_DEFAULT_FONT
-#define NK_IMPLEMENTATION
-#include "../nuklear.h"
-
-/* macros */
-#define WINDOW_WIDTH 800
-#define WINDOW_HEIGHT 600
-
-#define MAX_VERTEX_MEMORY 512 * 1024
-#define MAX_ELEMENT_MEMORY 128 * 1024
-#define UNUSED(a) (void)a
-
-#ifdef __APPLE__
-  #define NK_SHADER_VERSION "#version 150\n"
-#else
-  #define NK_SHADER_VERSION "#version 300 es\n"
-#endif
-
-/* ===============================================================
- *
- *                          DEVICE
- *
- * ===============================================================*/
-struct device {
-    struct nk_buffer cmds;
-    struct nk_draw_null_texture null;
-    GLuint vbo, vao, ebo;
-    GLuint prog;
-    GLuint vert_shdr;
-    GLuint frag_shdr;
-    GLint attrib_pos;
-    GLint attrib_uv;
-    GLint attrib_col;
-    GLint uniform_tex;
-    GLint uniform_proj;
-    GLuint font_tex;
-};
-
-
-static void
-device_init(struct device *dev)
-{
-    GLint status;
-    static const GLchar *vertex_shader =
-        NK_SHADER_VERSION
-        "uniform mat4 ProjMtx;\n"
-        "in vec2 Position;\n"
-        "in vec2 TexCoord;\n"
-        "in vec4 Color;\n"
-        "out vec2 Frag_UV;\n"
-        "out vec4 Frag_Color;\n"
-        "void main() {\n"
-        "   Frag_UV = TexCoord;\n"
-        "   Frag_Color = Color;\n"
-        "   gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
-        "}\n";
-    static const GLchar *fragment_shader =
-        NK_SHADER_VERSION
-        "precision mediump float;\n"
-        "uniform sampler2D Texture;\n"
-        "in vec2 Frag_UV;\n"
-        "in vec4 Frag_Color;\n"
-        "out vec4 Out_Color;\n"
-        "void main(){\n"
-        "   Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
-        "}\n";
-
-    nk_buffer_init_default(&dev->cmds);
-    dev->prog = glCreateProgram();
-    dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
-    dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
-    glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
-    glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
-    glCompileShader(dev->vert_shdr);
-    glCompileShader(dev->frag_shdr);
-    glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
-    assert(status == GL_TRUE);
-    glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
-    assert(status == GL_TRUE);
-    glAttachShader(dev->prog, dev->vert_shdr);
-    glAttachShader(dev->prog, dev->frag_shdr);
-    glLinkProgram(dev->prog);
-    glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
-    assert(status == GL_TRUE);
-
-    dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
-    dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
-    dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
-    dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
-    dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
-
-    {
-        /* buffer setup */
-        GLsizei vs = sizeof(struct nk_draw_vertex);
-        size_t vp = offsetof(struct nk_draw_vertex, position);
-        size_t vt = offsetof(struct nk_draw_vertex, uv);
-        size_t vc = offsetof(struct nk_draw_vertex, col);
-
-        glGenBuffers(1, &dev->vbo);
-        glGenBuffers(1, &dev->ebo);
-        glGenVertexArrays(1, &dev->vao);
-
-        glBindVertexArray(dev->vao);
-        glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
-
-        glEnableVertexAttribArray((GLuint)dev->attrib_pos);
-        glEnableVertexAttribArray((GLuint)dev->attrib_uv);
-        glEnableVertexAttribArray((GLuint)dev->attrib_col);
-
-        glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
-        glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
-        glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
-    }
-
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glBindVertexArray(0);
-}
-
-static void
-device_upload_atlas(struct device *dev, const void *image, int width, int height)
-{
-    glGenTextures(1, &dev->font_tex);
-    glBindTexture(GL_TEXTURE_2D, dev->font_tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, image);
-}
-
-static void
-device_shutdown(struct device *dev)
-{
-    glDetachShader(dev->prog, dev->vert_shdr);
-    glDetachShader(dev->prog, dev->frag_shdr);
-    glDeleteShader(dev->vert_shdr);
-    glDeleteShader(dev->frag_shdr);
-    glDeleteProgram(dev->prog);
-    glDeleteTextures(1, &dev->font_tex);
-    glDeleteBuffers(1, &dev->vbo);
-    glDeleteBuffers(1, &dev->ebo);
-    nk_buffer_free(&dev->cmds);
-}
-
-static void
-device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
-    enum nk_anti_aliasing AA)
-{
-    GLint last_prog, last_tex;
-    GLint last_ebo, last_vbo, last_vao;
-    GLfloat ortho[4][4] = {
-        {2.0f, 0.0f, 0.0f, 0.0f},
-        {0.0f,-2.0f, 0.0f, 0.0f},
-        {0.0f, 0.0f,-1.0f, 0.0f},
-        {-1.0f,1.0f, 0.0f, 1.0f},
-    };
-    ortho[0][0] /= (GLfloat)width;
-    ortho[1][1] /= (GLfloat)height;
-
-    /* save previous opengl state */
-    glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
-    glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex);
-    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao);
-    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo);
-    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo);
-
-    /* setup global state */
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glDisable(GL_CULL_FACE);
-    glDisable(GL_DEPTH_TEST);
-    glEnable(GL_SCISSOR_TEST);
-    glActiveTexture(GL_TEXTURE0);
-
-    /* setup program */
-    glUseProgram(dev->prog);
-    glUniform1i(dev->uniform_tex, 0);
-    glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
-    {
-        /* convert from command queue into draw list and draw to screen */
-        const struct nk_draw_command *cmd;
-        void *vertices, *elements;
-        const nk_draw_index *offset = NULL;
-
-        /* allocate vertex and element buffer */
-        glBindVertexArray(dev->vao);
-        glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
-
-        glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
-
-        /* load draw vertices & elements directly into vertex + element buffer */
-        vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-        elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
-        {
-            /* fill converting configuration */
-            struct nk_convert_config config;
-            memset(&config, 0, sizeof(config));
-            config.global_alpha = 1.0f;
-            config.shape_AA = AA;
-            config.line_AA = AA;
-            config.circle_segment_count = 22;
-            config.curve_segment_count = 22;
-            config.arc_segment_count = 22;
-            config.null = dev->null;
-
-            /* setup buffers to load vertices and elements */
-            {struct nk_buffer vbuf, ebuf;
-            nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
-            nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
-            nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);}
-        }
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-
-        /* iterate over and execute each draw command */
-        nk_draw_foreach(cmd, ctx, &dev->cmds) {
-            if (!cmd->elem_count) continue;
-            glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
-            glScissor((GLint)cmd->clip_rect.x,
-                height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h),
-                (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h);
-            glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
-            offset += cmd->elem_count;
-        }
-        nk_clear(ctx);
-    }
-
-    /* restore old state */
-    glUseProgram((GLuint)last_prog);
-    glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
-    glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
-    glBindVertexArray((GLuint)last_vao);
-    glDisable(GL_SCISSOR_TEST);
-}
-
-
-/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/
-static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);}
-static void text_input(GLFWwindow *win, unsigned int codepoint)
-{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);}
-static void scroll_input(GLFWwindow *win, double _, double yoff)
-{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);}
-
-int main(int argc, char *argv[])
-{
-    /* Platform */
-    static GLFWwindow *win;
-    int width = 0, height = 0;
-    int display_width, display_height;
-
-    /* GUI */
-    struct device device;
-    struct nk_context ctx;
-    struct nk_font *font;
-    struct nk_font_atlas atlas;
-
-    /* GLFW */
-    glfwSetErrorCallback(error_callback);
-    if (!glfwInit()) {
-        fprintf(stdout, "[GFLW] failed to init!\n");
-        exit(1);
-    }
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#ifdef __APPLE__
-    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-#endif
-    win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL);
-    glfwMakeContextCurrent(win);
-    glfwSetWindowUserPointer(win, &ctx);
-    glfwSetCharCallback(win, text_input);
-    glfwSetScrollCallback(win, scroll_input);
-
-    /* OpenGL */
-    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
-    glewExperimental = 1;
-    if (glewInit() != GLEW_OK) {
-        fprintf(stderr, "Failed to setup GLEW\n");
-        exit(1);
-    }
-
-    {/* GUI */
-    device_init(&device);
-    {const void *image; int w, h;
-    struct nk_font_config cfg = nk_font_config(0);
-    cfg.oversample_h = 3; cfg.oversample_v = 2;
-    nk_font_atlas_init_default(&atlas);
-    nk_font_atlas_begin(&atlas);
-    font = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 14.0f, &cfg);
-    image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
-    device_upload_atlas(&device, image, w, h);
-    nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);}
-    nk_init_default(&ctx, &font->handle);}
-
-    while (!glfwWindowShouldClose(win))
-    {
-        /* Input */
-        {double x, y;
-        nk_input_begin(&ctx);
-        glfwPollEvents();
-        glfwGetWindowSize(win, &width, &height);
-        glfwGetFramebufferSize(win, &display_width, &display_height);
-
-        nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
-        if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
-            glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL)) {
-            nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_SHIFT, 1);
-        } else {
-            nk_input_key(&ctx, NK_KEY_COPY, 0);
-            nk_input_key(&ctx, NK_KEY_PASTE, 0);
-            nk_input_key(&ctx, NK_KEY_CUT, 0);
-            nk_input_key(&ctx, NK_KEY_SHIFT, 0);
-        }
-        glfwGetCursorPos(win, &x, &y);
-        x *= (double)(int)((float)display_width/(float)width);
-        y *= (double)(int)((float)display_height/(float)height);
-
-        nk_input_motion(&ctx, (int)x, (int)y);
-        nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
-        nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
-        nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
-        nk_input_end(&ctx);}
-
-        /* GUI */
-        {struct nk_panel layout;
-        if (nk_begin(&ctx, &layout, "Calculator", nk_rect(10, 10, 180, 250),
-            NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE))
-        {
-            static int set = 0, prev = 0, op = 0;
-            static const char numbers[] = "789456123";
-            static const char ops[] = "+-*/";
-            static double a = 0, b = 0;
-            static double *current = &a;
-
-            size_t i = 0;
-            int solve = 0;
-            {int len; char buffer[256];
-            nk_layout_row_dynamic(&ctx, 35, 1);
-            len = snprintf(buffer, 256, "%.2f", *current);
-            nk_edit_string(&ctx, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_float);
-            buffer[len] = 0;
-            *current = atof(buffer);}
-
-            nk_layout_row_dynamic(&ctx, 35, 4);
-            for (i = 0; i < 16; ++i) {
-                if (i >= 12 && i < 15) {
-                    if (i > 12) continue;
-                    if (nk_button_label(&ctx, "C", NK_BUTTON_DEFAULT)) {
-                        a = b = op = 0; current = &a; set = 0;
-                    } if (nk_button_label(&ctx, "0", NK_BUTTON_DEFAULT)) {
-                        *current = *current*10.0f; set = 0;
-                    }
-                    if (nk_button_label(&ctx, "=", NK_BUTTON_DEFAULT)) {
-                        solve = 1; prev = op; op = 0;
-                    }
-                } else if (((i+1) % 4)) {
-                    if (nk_button_text(&ctx, &numbers[(i/4)*3+i%4], 1, NK_BUTTON_DEFAULT)) {
-                        *current = *current * 10.0f + numbers[(i/4)*3+i%4] - '0';
-                        set = 0;
-                    }
-                } else if (nk_button_text(&ctx, &ops[i/4], 1, NK_BUTTON_DEFAULT)) {
-                    if (!set) {
-                        if (current != &b) {
-                            current = &b;
-                        } else {
-                            prev = op;
-                            solve = 1;
-                        }
-                    }
-                    op = ops[i/4];
-                    set = 1;
-                }
-            }
-            if (solve) {
-                if (prev == '+') a = a + b;
-                if (prev == '-') a = a - b;
-                if (prev == '*') a = a * b;
-                if (prev == '/') a = a / b;
-                current = &a;
-                if (set) current = &b;
-                b = 0; set = 0;
-            }
-        }
-        nk_end(&ctx);}
-
-        /* Draw */
-        glViewport(0, 0, width, height);
-        glClear(GL_COLOR_BUFFER_BIT);
-        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-        device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON);
-        glfwSwapBuffers(win);
-    }
-
-    nk_font_atlas_clear(&atlas);
-    nk_free(&ctx);
-    device_shutdown(&device);
-    glfwTerminate();
-    return 0;
-}
-

+ 23 - 29
example/extended.c

@@ -633,10 +633,8 @@ device_shutdown(struct device *dev)
 
 
 static void
 static void
 device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
 device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
-    enum nk_anti_aliasing AA)
+    struct nk_vec2 scale, enum nk_anti_aliasing AA)
 {
 {
-    GLint last_prog, last_tex;
-    GLint last_ebo, last_vbo, last_vao;
     GLfloat ortho[4][4] = {
     GLfloat ortho[4][4] = {
         {2.0f, 0.0f, 0.0f, 0.0f},
         {2.0f, 0.0f, 0.0f, 0.0f},
         {0.0f,-2.0f, 0.0f, 0.0f},
         {0.0f,-2.0f, 0.0f, 0.0f},
@@ -646,13 +644,6 @@ device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
     ortho[0][0] /= (GLfloat)width;
     ortho[0][0] /= (GLfloat)width;
     ortho[1][1] /= (GLfloat)height;
     ortho[1][1] /= (GLfloat)height;
 
 
-    /* save previous opengl state */
-    glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
-    glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex);
-    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao);
-    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo);
-    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo);
-
     /* setup global state */
     /* setup global state */
     glEnable(GL_BLEND);
     glEnable(GL_BLEND);
     glBlendEquation(GL_FUNC_ADD);
     glBlendEquation(GL_FUNC_ADD);
@@ -705,28 +696,30 @@ device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
 
 
         /* iterate over and execute each draw command */
         /* iterate over and execute each draw command */
-        nk_draw_foreach(cmd, ctx, &dev->cmds) {
+        nk_draw_foreach(cmd, ctx, &dev->cmds)
+        {
             if (!cmd->elem_count) continue;
             if (!cmd->elem_count) continue;
             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
-            glScissor((GLint)cmd->clip_rect.x,
-                height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h),
-                (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h);
+            glScissor(
+                (GLint)(cmd->clip_rect.x * scale.x),
+                (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y),
+                (GLint)(cmd->clip_rect.w * scale.x),
+                (GLint)(cmd->clip_rect.h * scale.y));
             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
             offset += cmd->elem_count;
             offset += cmd->elem_count;
         }
         }
         nk_clear(ctx);
         nk_clear(ctx);
     }
     }
 
 
-    /* restore old state */
-    glUseProgram((GLuint)last_prog);
-    glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
-    glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
-    glBindVertexArray((GLuint)last_vao);
+    /* default OpenGL state */
+    glUseProgram(0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindVertexArray(0);
+    glDisable(GL_BLEND);
     glDisable(GL_SCISSOR_TEST);
     glDisable(GL_SCISSOR_TEST);
 }
 }
 
 
-
 /* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/
 /* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/
 static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);}
 static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);}
 static void text_input(GLFWwindow *win, unsigned int codepoint)
 static void text_input(GLFWwindow *win, unsigned int codepoint)
@@ -828,13 +821,17 @@ int main(int argc, char *argv[])
 
 
     while (!glfwWindowShouldClose(win))
     while (!glfwWindowShouldClose(win))
     {
     {
+        /* High DPI displays */
+        struct nk_vec2 scale;
+        glfwGetWindowSize(win, &width, &height);
+        glfwGetFramebufferSize(win, &display_width, &display_height);
+        scale.x = (float)display_width/(float)width;
+        scale.y = (float)display_height/(float)height;
+
         /* Input */
         /* Input */
         {double x, y;
         {double x, y;
         nk_input_begin(&ctx);
         nk_input_begin(&ctx);
         glfwPollEvents();
         glfwPollEvents();
-        glfwGetWindowSize(win, &width, &height);
-        glfwGetFramebufferSize(win, &display_width, &display_height);
-
         nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
         nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
         nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
         nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
         nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
         nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
@@ -857,9 +854,6 @@ int main(int argc, char *argv[])
             nk_input_key(&ctx, NK_KEY_SHIFT, 0);
             nk_input_key(&ctx, NK_KEY_SHIFT, 0);
         }
         }
         glfwGetCursorPos(win, &x, &y);
         glfwGetCursorPos(win, &x, &y);
-        x *= (double)(int)((float)display_width/(float)width);
-        y *= (double)(int)((float)display_height/(float)height);
-
         nk_input_motion(&ctx, (int)x, (int)y);
         nk_input_motion(&ctx, (int)x, (int)y);
         nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
         nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
         nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
         nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
@@ -872,10 +866,10 @@ int main(int argc, char *argv[])
         grid_demo(&ctx);
         grid_demo(&ctx);
 
 
         /* Draw */
         /* Draw */
-        glViewport(0, 0, width, height);
+        glViewport(0, 0, display_width, display_height);
         glClear(GL_COLOR_BUFFER_BIT);
         glClear(GL_COLOR_BUFFER_BIT);
         glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
         glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-        device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON);
+        device_draw(&device, &ctx, width, height, scale, NK_ANTI_ALIASING_ON);
         glfwSwapBuffers(win);
         glfwSwapBuffers(win);
     }
     }
 
 

+ 22 - 22
example/file_browser.c

@@ -661,10 +661,8 @@ device_shutdown(struct device *dev)
 
 
 static void
 static void
 device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
 device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
-    enum nk_anti_aliasing AA)
+    struct nk_vec2 scale, enum nk_anti_aliasing AA)
 {
 {
-    GLint last_prog, last_tex;
-    GLint last_ebo, last_vbo, last_vao;
     GLfloat ortho[4][4] = {
     GLfloat ortho[4][4] = {
         {2.0f, 0.0f, 0.0f, 0.0f},
         {2.0f, 0.0f, 0.0f, 0.0f},
         {0.0f,-2.0f, 0.0f, 0.0f},
         {0.0f,-2.0f, 0.0f, 0.0f},
@@ -674,13 +672,6 @@ device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
     ortho[0][0] /= (GLfloat)width;
     ortho[0][0] /= (GLfloat)width;
     ortho[1][1] /= (GLfloat)height;
     ortho[1][1] /= (GLfloat)height;
 
 
-    /* save previous opengl state */
-    glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
-    glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex);
-    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao);
-    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo);
-    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo);
-
     /* setup global state */
     /* setup global state */
     glEnable(GL_BLEND);
     glEnable(GL_BLEND);
     glBlendEquation(GL_FUNC_ADD);
     glBlendEquation(GL_FUNC_ADD);
@@ -736,21 +727,23 @@ device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
         nk_draw_foreach(cmd, ctx, &dev->cmds) {
         nk_draw_foreach(cmd, ctx, &dev->cmds) {
             if (!cmd->elem_count) continue;
             if (!cmd->elem_count) continue;
             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
             glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
-            glScissor((GLint)cmd->clip_rect.x,
-                height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h),
-                (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h);
+            glScissor(
+                (GLint)(cmd->clip_rect.x * scale.x),
+                (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y),
+                (GLint)(cmd->clip_rect.w * scale.x),
+                (GLint)(cmd->clip_rect.h * scale.y));
             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
             glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
             offset += cmd->elem_count;
             offset += cmd->elem_count;
         }
         }
         nk_clear(ctx);
         nk_clear(ctx);
     }
     }
 
 
-    /* restore old state */
-    glUseProgram((GLuint)last_prog);
-    glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
-    glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
-    glBindVertexArray((GLuint)last_vao);
+    /* default OpenGL state */
+    glUseProgram(0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindVertexArray(0);
+    glDisable(GL_BLEND);
     glDisable(GL_SCISSOR_TEST);
     glDisable(GL_SCISSOR_TEST);
 }
 }
 
 
@@ -767,6 +760,7 @@ int main(int argc, char *argv[])
     /* Platform */
     /* Platform */
     static GLFWwindow *win;
     static GLFWwindow *win;
     int width = 0, height = 0;
     int width = 0, height = 0;
+    int display_width = 0, display_height = 0;
 
 
     /* GUI */
     /* GUI */
     struct device device;
     struct device device;
@@ -832,6 +826,13 @@ int main(int argc, char *argv[])
     file_browser_init(&browser, &media);
     file_browser_init(&browser, &media);
     while (!glfwWindowShouldClose(win))
     while (!glfwWindowShouldClose(win))
     {
     {
+        /* High DPI displays */
+        struct nk_vec2 scale;
+        glfwGetWindowSize(win, &width, &height);
+        glfwGetFramebufferSize(win, &display_width, &display_height);
+        scale.x = (float)display_width/(float)width;
+        scale.y = (float)display_height/(float)height;
+
         /* Input */
         /* Input */
         {double x, y;
         {double x, y;
         nk_input_begin(&ctx);
         nk_input_begin(&ctx);
@@ -868,11 +869,10 @@ int main(int argc, char *argv[])
         file_browser_run(&browser, &ctx);
         file_browser_run(&browser, &ctx);
 
 
         /* Draw */
         /* Draw */
-        glfwGetWindowSize(win, &width, &height);
-        glViewport(0, 0, width, height);
+        glViewport(0, 0, display_width, display_height);
         glClear(GL_COLOR_BUFFER_BIT);
         glClear(GL_COLOR_BUFFER_BIT);
         glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
         glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-        device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON);
+        device_draw(&device, &ctx, width, height, scale, NK_ANTI_ALIASING_ON);
         glfwSwapBuffers(win);
         glfwSwapBuffers(win);
     }
     }
 
 

+ 0 - 726
example/node_editor.c

@@ -1,726 +0,0 @@
-/* nuklear - v1.00 - public domain */
-/* This is a simple node editor just to show a simple implementation and that
- * it is possible to achieve it with this library. While all nodes inside this
- * example use a simple color modifier as content you could change them
- * to have your custom content depending on the node time.
- * Biggest difference to most usual implementation is that this example does
- * not have connectors on the right position of the property that it links.
- * This is mainly done out of laziness and could be implemented as well but
- * requires calculating the position of all rows and add connectors.
- * In addition adding and removing nodes is quite limited at the
- * moment since it is based on a simple fixed array. If this is to be converted
- * into something more serious it is probably best to extend it.*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <math.h>
-#include <time.h>
-#include <limits.h>
-
-#include <GL/glew.h>
-#include <GLFW/glfw3.h>
-
-#define NK_INCLUDE_FIXED_TYPES
-#define NK_INCLUDE_STANDARD_IO
-#define NK_INCLUDE_DEFAULT_ALLOCATOR
-#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
-#define NK_INCLUDE_FONT_BAKING
-#define NK_INCLUDE_DEFAULT_FONT
-#define NK_IMPLEMENTATION
-#include "../nuklear.h"
-
-/* macros */
-#define WINDOW_WIDTH 800
-#define WINDOW_HEIGHT 600
-
-#define MAX_VERTEX_MEMORY 512 * 1024
-#define MAX_ELEMENT_MEMORY 128 * 1024
-
-#define UNUSED(a) (void)a
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) < (b) ? (b) : (a))
-#define LEN(a) (sizeof(a)/sizeof(a)[0])
-
-#ifdef __APPLE__
-  #define NK_SHADER_VERSION "#version 150\n"
-#else
-  #define NK_SHADER_VERSION "#version 300 es\n"
-#endif
-
-/* ===============================================================
- *
- *                          NODE EDITOR
- *
- * ===============================================================*/
-struct node {
-    int ID;
-    char name[32];
-    struct nk_rect bounds;
-    float value;
-    struct nk_color color;
-    int input_count;
-    int output_count;
-    struct node *next;
-    struct node *prev;
-};
-
-struct node_link {
-    int input_id;
-    int input_slot;
-    int output_id;
-    int output_slot;
-    struct nk_vec2 in;
-    struct nk_vec2 out;
-};
-
-struct node_linking {
-    int active;
-    struct node *node;
-    int input_id;
-    int input_slot;
-};
-
-struct node_editor {
-    struct node node_buf[32];
-    struct node_link links[64];
-    struct node *begin;
-    struct node *end;
-    int node_count;
-    int link_count;
-    struct nk_rect bounds;
-    struct node *selected;
-    int show_grid;
-    struct nk_vec2 scrolling;
-    struct node_linking linking;
-};
-
-static void
-node_editor_push(struct node_editor *editor, struct node *node)
-{
-    if (!editor->begin) {
-        node->next = NULL;
-        node->prev = NULL;
-        editor->begin = node;
-        editor->end = node;
-    } else {
-        node->prev = editor->end;
-        if (editor->end)
-            editor->end->next = node;
-        node->next = NULL;
-        editor->end = node;
-    }
-}
-
-static void
-node_editor_pop(struct node_editor *editor, struct node *node)
-{
-    if (node->next)
-        node->next->prev = node->prev;
-    if (node->prev)
-        node->prev->next = node->next;
-    if (editor->end == node)
-        editor->end = node->prev;
-    if (editor->begin == node)
-        editor->begin = node->next;
-    node->next = NULL;
-    node->prev = NULL;
-}
-
-static struct node*
-node_editor_find(struct node_editor *editor, int ID)
-{
-    struct node *iter = editor->begin;
-    while (iter) {
-        if (iter->ID == ID)
-            return iter;
-        iter = iter->next;
-    }
-    return NULL;
-}
-
-static void
-node_editor_add(struct node_editor *editor, const char *name, struct nk_rect bounds,
-    struct nk_color col, int in_count, int out_count)
-{
-    static int IDs = 0;
-    struct node *node;
-    assert((nk_size)editor->node_count < LEN(editor->node_buf));
-    node = &editor->node_buf[editor->node_count++];
-    node->ID = IDs++;
-    node->value = 0;
-    node->color = nk_rgb(255, 0, 0);
-    node->input_count = in_count;
-    node->output_count = out_count;
-    node->color = col;
-    node->bounds = bounds;
-    strcpy(node->name, name);
-    node_editor_push(editor, node);
-}
-
-static void
-node_editor_link(struct node_editor *editor, int in_id, int in_slot,
-    int out_id, int out_slot)
-{
-    struct node_link *link;
-    assert((nk_size)editor->link_count < LEN(editor->links));
-    link = &editor->links[editor->link_count++];
-    link->input_id = in_id;
-    link->input_slot = in_slot;
-    link->output_id = out_id;
-    link->output_slot = out_slot;
-}
-
-static void
-node_editor_init(struct node_editor *editor)
-{
-    memset(editor, 0, sizeof(*editor));
-    editor->begin = NULL;
-    editor->end = NULL;
-    node_editor_add(editor, "Source", nk_rect(40, 10, 180, 220), nk_rgb(255, 0, 0), 0, 1);
-    node_editor_add(editor, "Source", nk_rect(40, 260, 180, 220), nk_rgb(0, 255, 0), 0, 1);
-    node_editor_add(editor, "Combine", nk_rect(400, 100, 180, 220), nk_rgb(0,0,255), 2, 2);
-    node_editor_link(editor, 0, 0, 2, 0);
-    node_editor_link(editor, 1, 0, 2, 1);
-    editor->show_grid = nk_true;
-}
-
-static int
-node_editor_run(struct node_editor *nodedit, struct nk_context *ctx, int width, int height)
-{
-    int n = 0;
-    struct nk_rect total_space;
-    const struct nk_input *in = &ctx->input;
-    struct nk_command_buffer *canvas;
-    struct node *updated = 0;
-    struct nk_panel layout;
-
-    if (nk_begin(ctx, &layout, "Node Editor", nk_rect(0, 0, width, height),
-        NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE))
-    {
-        /* allocate complete window space */
-        nk_window_set_size(ctx, nk_vec2(width, height));
-        canvas = nk_window_get_canvas(ctx);
-        total_space = nk_window_get_content_region(ctx);
-        nk_layout_space_begin(ctx, NK_STATIC, total_space.h, nodedit->node_count);
-        {
-            struct nk_panel node, menu;
-            struct node *it = nodedit->begin;
-            struct nk_rect size = nk_layout_space_bounds(ctx);
-
-            if (nodedit->show_grid) {
-                /* display grid */
-                float x, y;
-                const float grid_size = 32.0f;
-                const struct nk_color grid_color = nk_rgb(50, 50, 50);
-                for (x = (float)fmod(size.x - nodedit->scrolling.x, grid_size); x < size.w; x += grid_size)
-                    nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, 1.0f, grid_color);
-                for (y = (float)fmod(size.y - nodedit->scrolling.y, grid_size); y < size.h; y += grid_size)
-                    nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, 1.0f, grid_color);
-            }
-
-            /* execute each node as a movable group */
-            while (it) {
-                /* calculate scrolled node window position and size */
-                nk_layout_space_push(ctx, nk_rect(it->bounds.x - nodedit->scrolling.x,
-                    it->bounds.y - nodedit->scrolling.y, it->bounds.w, it->bounds.h));
-
-                /* execute node window */
-                if (nk_group_begin(ctx, &node, it->name, NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE))
-                {
-                    /* always have last selected node on top */
-                    if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, node.bounds) &&
-                        (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT,
-                        nk_layout_space_rect_to_screen(ctx, node.bounds)))) &&
-                        nodedit->end != it)
-                    {
-                        updated = it;
-                    }
-
-                    /* ================= NODE CONTENT =====================*/
-                    nk_layout_row_dynamic(ctx, 25, 1);
-                    nk_button_color(ctx, it->color, NK_BUTTON_DEFAULT);
-                    it->color.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, it->color.r, 255, 1,1);
-                    it->color.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, it->color.g, 255, 1,1);
-                    it->color.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, it->color.b, 255, 1,1);
-                    it->color.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, it->color.a, 255, 1,1);
-                    /* ====================================================*/
-                    nk_group_end(ctx);
-                }
-                {
-                    /* node connector and linking */
-                    float space;
-                    struct nk_rect bounds;
-                    bounds = nk_layout_space_rect_to_local(ctx, node.bounds);
-                    bounds.x += nodedit->scrolling.x - ctx->style.window.border;
-                    bounds.y += nodedit->scrolling.y - ctx->style.window.border;
-                    bounds.w += 2*ctx->style.window.border;
-                    bounds.h += 2*ctx->style.window.border;
-
-                    it->bounds = bounds;
-
-                    /* output connector */
-                    space = node.bounds.h / (float)((it->output_count) + 1);
-                    for (n = 0; n < it->output_count; ++n) {
-                        struct nk_rect circle;
-                        circle.x = node.bounds.x + node.bounds.w-4;
-                        circle.y = node.bounds.y + space * (float)(n+1);
-                        circle.w = 8; circle.h = 8;
-                        nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100));
-
-                        /* start linking process */
-                        if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) {
-                            nodedit->linking.active = nk_true;
-                            nodedit->linking.node = it;
-                            nodedit->linking.input_id = it->ID;
-                            nodedit->linking.input_slot = n;
-                        }
-
-                        /* draw curve from linked node slot to mouse position */
-                        if (nodedit->linking.active && nodedit->linking.node == it &&
-                            nodedit->linking.input_slot == n) {
-                            struct nk_vec2 l0 = nk_vec2(circle.x + 3, circle.y + 3);
-                            struct nk_vec2 l1 = in->mouse.pos;
-                            nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y,
-                                l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100));
-                        }
-                    }
-
-                    /* input connector */
-                    space = node.bounds.h / (float)((it->input_count) + 1);
-                    for (n = 0; n < it->input_count; ++n) {
-                        struct nk_rect circle;
-                        circle.x = node.bounds.x-4;
-                        circle.y = node.bounds.y + space * (float)(n+1);
-                        circle.w = 8; circle.h = 8;
-                        nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100));
-                        if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) &&
-                            nk_input_is_mouse_hovering_rect(in, circle) &&
-                            nodedit->linking.active && nodedit->linking.node != it) {
-                            nodedit->linking.active = nk_false;
-                            node_editor_link(nodedit, nodedit->linking.input_id,
-                                nodedit->linking.input_slot, it->ID, n);
-                        }
-                    }
-                }
-                it = it->next;
-            }
-
-            /* reset linking connection */
-            if (nodedit->linking.active && nk_input_is_mouse_released(in, NK_BUTTON_LEFT)) {
-                nodedit->linking.active = nk_false;
-                nodedit->linking.node = NULL;
-                fprintf(stdout, "linking failed\n");
-            }
-
-            /* draw each link */
-            for (n = 0; n < nodedit->link_count; ++n) {
-                struct node_link *link = &nodedit->links[n];
-                struct node *ni = node_editor_find(nodedit, link->input_id);
-                struct node *no = node_editor_find(nodedit, link->output_id);
-                float spacei = node.bounds.h / (float)((ni->output_count) + 1);
-                float spaceo = node.bounds.h / (float)((no->input_count) + 1);
-                struct nk_vec2 l0 = nk_layout_space_to_screen(ctx,
-                    nk_vec2(ni->bounds.x + ni->bounds.w, 3.0f + ni->bounds.y + spacei * (float)(link->input_slot+1)));
-                struct nk_vec2 l1 = nk_layout_space_to_screen(ctx,
-                    nk_vec2(no->bounds.x, 3.0f + no->bounds.y + spaceo * (float)(link->output_slot+1)));
-
-                l0.x -= nodedit->scrolling.x;
-                l0.y -= nodedit->scrolling.y;
-                l1.x -= nodedit->scrolling.x;
-                l1.y -= nodedit->scrolling.y;
-                nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y,
-                    l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100));
-            }
-
-            if (updated) {
-                /* reshuffle nodes to have least recently selected node on top */
-                node_editor_pop(nodedit, updated);
-                node_editor_push(nodedit, updated);
-            }
-
-            /* node selection */
-            if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ctx))) {
-                it = nodedit->begin;
-                nodedit->selected = NULL;
-                nodedit->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200);
-                while (it) {
-                    struct nk_rect b = nk_layout_space_rect_to_screen(ctx, it->bounds);
-                    b.x -= nodedit->scrolling.x;
-                    b.y -= nodedit->scrolling.y;
-                    if (nk_input_is_mouse_hovering_rect(in, b))
-                        nodedit->selected = it;
-                    it = it->next;
-                }
-            }
-
-            /* contextual menu */
-            if (nk_contextual_begin(ctx, &menu, 0, nk_vec2(100, 220), nk_window_get_bounds(ctx))) {
-                const char *grid_option[] = {"Show Grid", "Hide Grid"};
-                nk_layout_row_dynamic(ctx, 25, 1);
-                if (nk_contextual_item_label(ctx, "New", NK_TEXT_CENTERED))
-                    node_editor_add(nodedit, "New", nk_rect(400, 260, 180, 220),
-                            nk_rgb(255, 255, 255), 1, 2);
-                if (nk_contextual_item_label(ctx, grid_option[nodedit->show_grid],NK_TEXT_CENTERED))
-                    nodedit->show_grid = !nodedit->show_grid;
-                nk_contextual_end(ctx);
-            }
-        }
-        nk_layout_space_end(ctx);
-
-        /* window content scrolling */
-        if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ctx)) &&
-            nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) {
-            nodedit->scrolling.x += in->mouse.delta.x;
-            nodedit->scrolling.y += in->mouse.delta.y;
-        }
-    }
-    nk_end(ctx);
-    return !nk_window_is_closed(ctx, "Node Editor");
-}
-
-/* ===============================================================
- *
- *                          DEVICE
- *
- * ===============================================================*/
-struct device {
-    struct nk_buffer cmds;
-    struct nk_draw_null_texture null;
-    GLuint vbo, vao, ebo;
-    GLuint prog;
-    GLuint vert_shdr;
-    GLuint frag_shdr;
-    GLint attrib_pos;
-    GLint attrib_uv;
-    GLint attrib_col;
-    GLint uniform_tex;
-    GLint uniform_proj;
-    GLuint font_tex;
-};
-
-static void
-device_init(struct device *dev)
-{
-    GLint status;
-    static const GLchar *vertex_shader =
-        NK_SHADER_VERSION
-        "uniform mat4 ProjMtx;\n"
-        "in vec2 Position;\n"
-        "in vec2 TexCoord;\n"
-        "in vec4 Color;\n"
-        "out vec2 Frag_UV;\n"
-        "out vec4 Frag_Color;\n"
-        "void main() {\n"
-        "   Frag_UV = TexCoord;\n"
-        "   Frag_Color = Color;\n"
-        "   gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
-        "}\n";
-    static const GLchar *fragment_shader =
-        NK_SHADER_VERSION
-        "precision mediump float;\n"
-        "uniform sampler2D Texture;\n"
-        "in vec2 Frag_UV;\n"
-        "in vec4 Frag_Color;\n"
-        "out vec4 Out_Color;\n"
-        "void main(){\n"
-        "   Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
-        "}\n";
-
-    nk_buffer_init_default(&dev->cmds);
-    dev->prog = glCreateProgram();
-    dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
-    dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
-    glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
-    glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
-    glCompileShader(dev->vert_shdr);
-    glCompileShader(dev->frag_shdr);
-    glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
-    assert(status == GL_TRUE);
-    glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
-    assert(status == GL_TRUE);
-    glAttachShader(dev->prog, dev->vert_shdr);
-    glAttachShader(dev->prog, dev->frag_shdr);
-    glLinkProgram(dev->prog);
-    glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
-    assert(status == GL_TRUE);
-
-    dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
-    dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
-    dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
-    dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
-    dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
-
-    {
-        /* buffer setup */
-        GLsizei vs = sizeof(struct nk_draw_vertex);
-        size_t vp = offsetof(struct nk_draw_vertex, position);
-        size_t vt = offsetof(struct nk_draw_vertex, uv);
-        size_t vc = offsetof(struct nk_draw_vertex, col);
-
-        glGenBuffers(1, &dev->vbo);
-        glGenBuffers(1, &dev->ebo);
-        glGenVertexArrays(1, &dev->vao);
-
-        glBindVertexArray(dev->vao);
-        glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
-
-        glEnableVertexAttribArray((GLuint)dev->attrib_pos);
-        glEnableVertexAttribArray((GLuint)dev->attrib_uv);
-        glEnableVertexAttribArray((GLuint)dev->attrib_col);
-
-        glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
-        glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
-        glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
-    }
-
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glBindVertexArray(0);
-}
-
-static void
-device_upload_atlas(struct device *dev, const void *image, int width, int height)
-{
-    glGenTextures(1, &dev->font_tex);
-    glBindTexture(GL_TEXTURE_2D, dev->font_tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, image);
-}
-
-static void
-device_shutdown(struct device *dev)
-{
-    glDetachShader(dev->prog, dev->vert_shdr);
-    glDetachShader(dev->prog, dev->frag_shdr);
-    glDeleteShader(dev->vert_shdr);
-    glDeleteShader(dev->frag_shdr);
-    glDeleteProgram(dev->prog);
-    glDeleteTextures(1, &dev->font_tex);
-    glDeleteBuffers(1, &dev->vbo);
-    glDeleteBuffers(1, &dev->ebo);
-    nk_buffer_free(&dev->cmds);
-}
-
-static void
-device_draw(struct device *dev, struct nk_context *ctx, int width, int height,
-    enum nk_anti_aliasing AA)
-{
-    GLint last_prog, last_tex;
-    GLint last_ebo, last_vbo, last_vao;
-    GLfloat ortho[4][4] = {
-        {2.0f, 0.0f, 0.0f, 0.0f},
-        {0.0f,-2.0f, 0.0f, 0.0f},
-        {0.0f, 0.0f,-1.0f, 0.0f},
-        {-1.0f,1.0f, 0.0f, 1.0f},
-    };
-    ortho[0][0] /= (GLfloat)width;
-    ortho[1][1] /= (GLfloat)height;
-
-    /* save previous opengl state */
-    glGetIntegerv(GL_CURRENT_PROGRAM, &last_prog);
-    glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_tex);
-    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_vao);
-    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_ebo);
-    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vbo);
-
-    /* setup global state */
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glDisable(GL_CULL_FACE);
-    glDisable(GL_DEPTH_TEST);
-    glEnable(GL_SCISSOR_TEST);
-    glActiveTexture(GL_TEXTURE0);
-
-    /* setup program */
-    glUseProgram(dev->prog);
-    glUniform1i(dev->uniform_tex, 0);
-    glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
-    {
-        /* convert from command queue into draw list and draw to screen */
-        const struct nk_draw_command *cmd;
-        void *vertices, *elements;
-        const nk_draw_index *offset = NULL;
-
-        /* allocate vertex and element buffer */
-        glBindVertexArray(dev->vao);
-        glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
-
-        glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW);
-
-        /* load draw vertices & elements directly into vertex + element buffer */
-        vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-        elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
-        {
-            /* fill converting configuration */
-            struct nk_convert_config config;
-            memset(&config, 0, sizeof(config));
-            config.global_alpha = 1.0f;
-            config.shape_AA = AA;
-            config.line_AA = AA;
-            config.circle_segment_count = 22;
-            config.curve_segment_count = 22;
-            config.arc_segment_count = 22;
-            config.null = dev->null;
-
-            /* setup buffers to load vertices and elements */
-            {struct nk_buffer vbuf, ebuf;
-            nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY);
-            nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY);
-            nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);}
-        }
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-
-        /* iterate over and execute each draw command */
-        nk_draw_foreach(cmd, ctx, &dev->cmds) {
-            if (!cmd->elem_count) continue;
-            glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
-            glScissor((GLint)cmd->clip_rect.x,
-                height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h),
-                (GLint)cmd->clip_rect.w, (GLint)cmd->clip_rect.h);
-            glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
-            offset += cmd->elem_count;
-        }
-        nk_clear(ctx);
-    }
-
-    /* restore old state */
-    glUseProgram((GLuint)last_prog);
-    glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex);
-    glBindBuffer(GL_ARRAY_BUFFER, (GLuint)last_vbo);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo);
-    glBindVertexArray((GLuint)last_vao);
-    glDisable(GL_SCISSOR_TEST);
-}
-
-
-/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/
-static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);}
-static void text_input(GLFWwindow *win, unsigned int codepoint)
-{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);}
-static void scroll_input(GLFWwindow *win, double _, double yoff)
-{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);}
-
-int main(int argc, char *argv[])
-{
-    /* Platform */
-    static GLFWwindow *win;
-    int width = 0, height = 0;
-    int display_width, display_height;
-
-    /* GUI */
-    struct device device;
-    struct nk_context ctx;
-    struct nk_font *font;
-    struct nk_font_atlas atlas;
-    struct node_editor node;
-
-    /* GLFW */
-    glfwSetErrorCallback(error_callback);
-    if (!glfwInit()) {
-        fprintf(stdout, "[GFLW] failed to init!\n");
-        exit(1);
-    }
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#ifdef __APPLE__
-    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-#endif
-    win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL);
-    glfwMakeContextCurrent(win);
-    glfwSetWindowUserPointer(win, &ctx);
-    glfwSetCharCallback(win, text_input);
-    glfwSetScrollCallback(win, scroll_input);
-
-    /* OpenGL */
-    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
-    glewExperimental = 1;
-    if (glewInit() != GLEW_OK) {
-        fprintf(stderr, "Failed to setup GLEW\n");
-        exit(1);
-    }
-
-    {/* GUI */
-    device_init(&device);
-    {const void *image; int w, h;
-    struct nk_font_config cfg = nk_font_config(0);
-    cfg.oversample_h = 3; cfg.oversample_v = 2;
-    nk_font_atlas_init_default(&atlas);
-    nk_font_atlas_begin(&atlas);
-    font = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 14.0f, &cfg);
-    image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
-    device_upload_atlas(&device, image, w, h);
-    nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);}
-    nk_init_default(&ctx, &font->handle);}
-
-    node_editor_init(&node);
-    while (!glfwWindowShouldClose(win))
-    {
-        /* Input */
-        {double x, y;
-        nk_input_begin(&ctx);
-        glfwPollEvents();
-        glfwGetWindowSize(win, &width, &height);
-        glfwGetFramebufferSize(win, &display_width, &display_height);
-
-        nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
-        nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
-        if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
-            glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL)) {
-            nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
-            nk_input_key(&ctx, NK_KEY_SHIFT, 1);
-        } else {
-            nk_input_key(&ctx, NK_KEY_COPY, 0);
-            nk_input_key(&ctx, NK_KEY_PASTE, 0);
-            nk_input_key(&ctx, NK_KEY_CUT, 0);
-            nk_input_key(&ctx, NK_KEY_SHIFT, 0);
-        }
-        glfwGetCursorPos(win, &x, &y);
-        x *= (double)(int)((float)display_width/(float)width);
-        y *= (double)(int)((float)display_height/(float)height);
-
-        nk_input_motion(&ctx, (int)x, (int)y);
-        nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
-        nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
-        nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
-        nk_input_end(&ctx);}
-
-        /* GUI */
-        if (!node_editor_run(&node, &ctx, width, height)) break;
-
-        /* Draw */
-        glViewport(0, 0, width, height);
-        glClear(GL_COLOR_BUFFER_BIT);
-        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-        device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON);
-        glfwSwapBuffers(win);
-    }
-
-    nk_font_atlas_clear(&atlas);
-    nk_free(&ctx);
-    device_shutdown(&device);
-    glfwTerminate();
-    return 0;
-}
-