1 /*
2 Copyright (c) 2019 Mateusz Muszyński
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 Permission is hereby granted, free of charge, to any person or organization
6 obtaining a copy of the software and accompanying documentation covered by
7 this license (the "Software") to use, reproduce, display, distribute,
8 execute, and transmit the Software, and to prepare derivative works of the
9 Software, and to permit third-parties to whom the Software is furnished to
10 do so, all subject to the following:
11 
12 The copyright notices in the Software and this entire statement, including
13 the above license grant, this restriction and the following disclaimer,
14 must be included in all copies of the Software, in whole or in part, and
15 all derivative works of the Software, unless such copies or derivative
16 works are solely in the form of machine-executable object code generated by
17 a source language processor.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 */
27 
28 module dagon.ui.nuklear;
29 
30 import core.stdc.stdarg;
31 
32 import dlib.image.color;
33 import dlib.container.array;
34 import dlib.text.utf8;
35 import dlib.text.unmanagedstring;
36 
37 import dagon.core.interfaces;
38 import dagon.core.ownership;
39 import dagon.core.event;
40 import dagon.core.keycodes;
41 import dagon.core.locale;
42 import dagon.graphics.shaderloader;
43 import dagon.graphics.texture;
44 import dagon.resource.fontasset;
45 
46 version(NoNuklear)
47 {
48     pragma(msg, "Warning: Dagon is compiled without Nuklear support, dagon.ui.nuklear is not available");
49 }
50 else
51 {
52     version = EnableNuklear;
53 }
54 
55 version(EnableNuklear):
56 
57 import dagon.core.libs;
58 
59 alias nk_color NKColor;
60 alias nk_colorf NKColorf;
61 alias nk_rect NKRect;
62 alias nk_rect NKRecti;
63 alias nk_vec2 NKVec2;
64 alias nk_vec2i NKVec2i;
65 alias nk_cursor NKCursor;
66 alias nk_font NKFont;
67 alias nk_flags NKFlags;
68 alias nk_size NKSize;
69 alias nk_image NKImage;
70 alias nk_rune NKRune;
71 alias nk_handle NKHandle;
72 alias nk_window NKWindow;
73 alias nk_panel NKPanel;
74 
75 NKImage toNKImage(Texture texture)
76 {
77     NKImage img;
78     img.handle.id = cast(int)texture.tex;
79     img.w = cast(short)texture.width;
80     img.h = cast(short)texture.height;
81     img.region[2] = cast(short)texture.width;
82     img.region[3] = cast(short)texture.height;
83     return img;
84 }
85 
86 private extern(C) void clipboardPaste(nk_handle usr, nk_text_edit* edit)
87 {
88     char* text = SDL_GetClipboardText();
89     if (text) 
90     {
91         // Determine how many codepoints do we have
92         uint numCharacters = 0;
93         size_t offset = 0;
94         while(true)
95         {
96             UTF8Decoder dec = UTF8Decoder(cast(string)text[offset..offset+4]);
97             auto code = dec.decodeNext();
98             if (code == 0)
99                 break;
100             offset += dec.index;
101             numCharacters++;
102         }
103     
104         nk_textedit_paste(edit, text, numCharacters); //nk_strlen(text)
105         SDL_free(text);
106     }
107 }
108 
109 private extern(C) void clipboardCopy(nk_handle usr, const(char)* text, int len)
110 {
111     import core.stdc.stdio;
112     import core.stdc.string;
113     import core.stdc.stdlib;
114     char *str = null;
115     if (!len) return;
116     
117     // Decode len codepoints and determine byte length
118     size_t byteLen = 0;
119     for(int pos = 0; pos < len; pos++)
120     {
121         UTF8Decoder dec = UTF8Decoder(cast(string)text[byteLen..byteLen+4]);
122         dec.decodeNext();
123         byteLen += dec.index;
124     }
125     
126     str = cast(char*)malloc(byteLen+1);
127     if (!str) return;
128     memcpy(str, text, byteLen);
129     str[byteLen] = '\0';
130     SDL_SetClipboardText(str);
131     free(str);
132 }
133 
134 enum NuklearEventType
135 {
136     MouseMotion,
137     MouseButton,
138     MouseScroll,
139     TextInput,
140     Key
141 }
142 
143 struct NuklearEvent
144 {
145     NuklearEventType type;
146     int x;
147     int y;
148     union
149     {
150         int button;
151         dchar unicode;
152         int key;
153     }
154     int down;
155 }
156 
157 class NuklearGUI : Owner, Drawable
158 {
159     NuklearEvent[10] events;
160     int eventsCount = 0;
161 
162     nk_context ctx;
163     nk_buffer cmds;
164     nk_draw_null_texture nullTexture;
165 
166     DynamicArray!nk_font_atlas atlases;
167     DynamicArray!GLuint fontsTextures;
168 
169     GLuint vbo;
170     GLuint vao;
171     GLuint ebo;
172 
173     GLuint shaderProgram;
174     GLuint vertexShader;
175     GLuint fragmentShader;
176 
177     GLint positionLoc;
178     GLint texcoordLoc;
179     GLint colorLoc;
180 
181     GLint textureLoc;
182     GLint projectionMatrixLoc;
183 
184     string vs = import("Nuklear.vs");
185     string fs = import("Nuklear.fs");
186 
187     EventManager eventManager; // Needed for mouse position
188 
189     this(EventManager em, Owner o)
190     {
191         super(o);
192 
193         eventManager = em;
194 
195         atlases = DynamicArray!nk_font_atlas();
196         fontsTextures = DynamicArray!GLuint();
197 
198         nk_init_default(&ctx, null);
199 
200         ctx.clip.copy = cast(nk_plugin_copy)&clipboardCopy;
201         ctx.clip.paste = cast(nk_plugin_paste)&clipboardPaste;
202         ctx.clip.userdata = nk_handle_ptr(null);
203 
204         nk_buffer_init_default(&cmds);
205 
206         prepareVAO();
207 
208         addFont(null, 0, 13.0f); // load default font
209     }
210 
211     ~this()
212     {
213         if (atlases.length)
214         {
215             foreach(atlas; atlases)
216                 nk_font_atlas_clear(&atlas);
217             atlases.free();
218         }
219         nk_free(&ctx);
220         nk_buffer_free(&cmds);
221 
222         glDeleteProgram(shaderProgram);
223         if (fontsTextures.length)
224         {
225             foreach(tex; fontsTextures)
226                 glDeleteTextures(1, &tex);
227             fontsTextures.free();
228         }
229         glDeleteBuffers(1, &vbo);
230         glDeleteBuffers(1, &ebo);
231     }
232 
233     void prepareVAO()
234     {
235         vertexShader = compileShader(vs, ShaderStage.vertex);
236         fragmentShader = compileShader(fs, ShaderStage.fragment);
237         if (vertexShader != 0 && fragmentShader != 0)
238             shaderProgram = linkShaders(vertexShader, fragmentShader);
239 
240         if (shaderProgram != 0)
241         {
242             textureLoc = glGetUniformLocation(shaderProgram, "Texture");
243             projectionMatrixLoc = glGetUniformLocation(shaderProgram, "ProjMtx");      
244             positionLoc = glGetAttribLocation(shaderProgram, "va_Vertex");
245             texcoordLoc = glGetAttribLocation(shaderProgram, "va_Texcoord");
246             colorLoc = glGetAttribLocation(shaderProgram, "va_Color");
247         }
248 
249         // buffer setup
250         glGenBuffers(1, &vbo);
251         glGenBuffers(1, &ebo);
252         glGenVertexArrays(1, &vao);
253 
254         glBindVertexArray(vao);
255         glBindBuffer(GL_ARRAY_BUFFER, vbo);
256         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
257 
258         glEnableVertexAttribArray(positionLoc);
259         glEnableVertexAttribArray(texcoordLoc);
260         glEnableVertexAttribArray(colorLoc);
261 
262         glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 20, cast(void*)0);
263         glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, GL_FALSE, 20, cast(void*)8);
264         glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 20, cast(void*)16);
265 
266         glBindTexture(GL_TEXTURE_2D, 0);
267         glBindBuffer(GL_ARRAY_BUFFER, 0);
268         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
269         glBindVertexArray(0);
270     }
271 
272     override void update(double dt)
273     {
274         nk_clear(&ctx);
275 
276         nk_input_begin(&ctx);
277         nk_input_motion(&ctx, eventManager.mouseX, eventManager.mouseY);
278 
279         // perform all inputs
280         while (eventsCount != 0)
281         {
282             auto e = events[--eventsCount];
283             switch (e.type)
284             {
285                 case NuklearEventType.Key:
286                     nk_input_key(&ctx, cast(nk_keys)e.key, e.down);
287                     break;
288                 case NuklearEventType.MouseButton:
289                     nk_input_button(&ctx, cast(nk_buttons)e.button, e.x, e.y, e.down);
290                     break;
291                 case NuklearEventType.MouseScroll:
292                     nk_input_scroll(&ctx, nk_vec2(e.x, e.y));
293                     break;
294                 case NuklearEventType.TextInput:
295                     nk_input_unicode(&ctx, e.unicode);
296                     break;
297                 default:
298                     break;
299             }
300         }
301 
302         nk_input_end(&ctx);
303     }
304 
305     override void render(RenderingContext* rc)
306     {
307         const(int) maxVertexBuffer = 512 * 1024;
308         const(int) maxElementBuffer = 128 * 1024;
309 
310         glEnable(GL_SCISSOR_TEST);
311         glEnable(GL_BLEND);
312         glBlendEquation(GL_FUNC_ADD);
313         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
314         glActiveTexture(GL_TEXTURE0);
315 
316         glUseProgram(shaderProgram);
317         glUniform1i(textureLoc, 0);
318         glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, rc.projectionMatrix.arrayof.ptr);
319 
320         const(nk_draw_command) *cmd;
321         void *vertices;
322         void *elements;
323         const(nk_draw_index) *offset = null;
324         nk_buffer vbuf;
325         nk_buffer ebuf;
326 
327         // allocate vertex and element buffer
328         glBindVertexArray(vao);
329         glBindBuffer(GL_ARRAY_BUFFER, vbo);
330         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
331 
332         glBufferData(GL_ARRAY_BUFFER, maxVertexBuffer, null, GL_STREAM_DRAW);
333         glBufferData(GL_ELEMENT_ARRAY_BUFFER, maxElementBuffer, null, GL_STREAM_DRAW);
334 
335         // load vertices/elements directly into vertex/element buffer
336         vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
337         elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
338         {
339             // fill convert configuration 
340             nk_convert_config config;
341             nk_draw_vertex_layout_element[] vertex_layout = 
342             [
343                 { NK_VERTEX_POSITION, NK_FORMAT_FLOAT, 0 },
344                     { NK_VERTEX_TEXCOORD,  NK_FORMAT_FLOAT, 8 },
345                         { NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, 16 },
346                             NK_VERTEX_LAYOUT_END
347             ];
348             config.vertex_layout = vertex_layout.ptr;
349             config.vertex_size = 20;
350             config.vertex_alignment = 0;
351             config.null_ = nullTexture;
352             config.circle_segment_count = 16;
353             config.curve_segment_count = 16;
354             config.arc_segment_count = 16;
355             config.global_alpha = 1.0f;
356             config.shape_AA = NK_ANTI_ALIASING_ON;
357             config.line_AA = NK_ANTI_ALIASING_ON;
358 
359             // setup buffers to load vertices and elements
360             nk_buffer_init_fixed(&vbuf, vertices, cast(nk_size)maxVertexBuffer);
361             nk_buffer_init_fixed(&ebuf, elements, cast(nk_size)maxElementBuffer);
362             nk_convert(&ctx, &cmds, &vbuf, &ebuf, &config);
363         }
364         glUnmapBuffer(GL_ARRAY_BUFFER);
365         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
366 
367         // iterate over and execute each draw command
368         nk_draw_foreach(&ctx, &cmds, (cmd)
369                         {
370                             if (!cmd.elem_count) return;
371                             glBindTexture(GL_TEXTURE_2D, cmd.texture.id);
372                             glScissor(cast(GLint)(cmd.clip_rect.x),
373                                       cast(GLint)((eventManager.windowHeight - cast(GLint)(cmd.clip_rect.y + cmd.clip_rect.h))),
374                                       cast(GLint)(cmd.clip_rect.w),
375                                       cast(GLint)(cmd.clip_rect.h));
376                             glDrawElements(GL_TRIANGLES, cmd.elem_count, GL_UNSIGNED_INT, offset);
377                             offset += cmd.elem_count;
378                         });
379 
380         glDisable(GL_BLEND);
381         glDisable(GL_SCISSOR_TEST);
382     }
383 
384     // TODO: move this to a separate module for easier extending?
385     static const(NKRune[]) fontDefaultGlyphRanges = [ 0x0020, 0x00FF, 0 ];
386     static const(NKRune[]) fontLatinExtendedAGlyphRanges = [ 0x0020, 0x017F, 0 ];
387     static const(NKRune[]) fontLatinExtendedBGlyphRanges = [ 0x0020, 0x024F, 0 ];
388     static const(NKRune[]) fontCyrillicGlyphRanges = [ 0x0020, 0x00FF,  0x0400, 0x052F, 0x2DE0, 0x2DFF, 0xA640, 0xA69F, 0 ];
389     static const(NKRune[]) fontGreekGlyphRanges = [ 0x0020, 0x00FF, 0x0370, 0x03FF, 0 ];
390     static const(NKRune[]) fontChineseGlyphRanges = [ 0x0020, 0x00FF, 0x3000, 0x30FF, 0x31F0, 0x31FF, 0xFF00, 0xFFEF, 0x4E00, 0x9FAF, 0 ];
391     static const(NKRune[]) fontJapaneseGlyphRanges = [ 0x0020, 0x00FF, 0x3000, 0x303F, 0x3040, 0x309F, 0x30A0, 0x30FF, 0 ];
392     static const(NKRune[]) fontKoreanGlyphRanges = [ 0x0020, 0x00FF, 0x3131, 0x3163,  0xAC00, 0xD79D, 0 ];
393     static const(NKRune[]) fontHebrewGlyphRanges = [ 0x0020, 0x00FF, 0x0590, 0x05FF, 0 ];
394     static const(NKRune[]) fontArabicGlyphRanges = [ 0x0020, 0x00FF, 0x0600, 0x06FF, 0 ];
395     static const(NKRune[]) fontArmenianGlyphRanges = [ 0x0020, 0x00FF, 0x0530, 0x058F, 0 ];
396     static const(NKRune[]) fontGeorgianGlyphRanges = [ 0x0020, 0x00FF, 0x10A0, 0x10FF, 0 ];
397     
398     static const(NKRune[]) localeGlyphRanges(string locale = systemLocale())
399     {
400         if (locale == "ru_RU" || // Russian
401             locale == "tt_RU")   // Tatar
402             return fontCyrillicGlyphRanges;
403             
404         else if (locale == "fr_FR" || // French
405                  locale == "de_DE" || // German
406                  locale == "is_IS" || // Icelandic
407                  locale == "es_ES" || // Spanish
408                  locale == "ca_ES" || // Catalan
409                  locale == "pl_PL" || // Polish
410                  locale == "cs_CZ" || // Czech
411                  locale == "lv_LV" || // Latvian
412                  locale == "lt_LT" || // Lithuanian
413                  locale == "sk_SK" || // Slovak
414                  locale == "tr_TR" || // Turkish
415                  locale == "cy_GB")   // Welsh
416             return fontLatinExtendedAGlyphRanges;
417             
418         else if (locale == "el_GR") // Greek
419             return fontGreekGlyphRanges;
420             
421         else if (locale == "zh_CN") // Chinese
422             return fontChineseGlyphRanges;
423             
424         else if (locale == "ja_JP") // Japanese
425             return fontJapaneseGlyphRanges;
426             
427         else if (locale == "ko_KR") // Korean
428             return fontKoreanGlyphRanges;
429             
430         else if (locale == "he_IL") // Hebrew
431             return fontHebrewGlyphRanges;
432             
433         else if (locale == "ar_AE" || // Arabic (United Arab Emirates)
434                  locale == "ar_DZ" || // Arabic (Algeria)
435                  locale == "ar_BH" || // Arabic (Bahrain)
436                  locale == "ar_EG" || // Arabic (Egypt)
437                  locale == "ar_IQ" || // Arabic (Iraq)
438                  locale == "ar_JO" || // Arabic (Jordan)
439                  locale == "ar_KW" || // Arabic (Kuwait)
440                  locale == "ar_LB" || // Arabic (Lebanon)
441                  locale == "ar_LY" || // Arabic (Libya)
442                  locale == "ar_MA" || // Arabic (Morocco)
443                  locale == "ar_OM" || // Arabic (Oman)
444                  locale == "ar_QA" || // Arabic (Qatar)
445                  locale == "ar_SA" || // Arabic (Saudi Arabia)
446                  locale == "ar_SD" || // Arabic (Sudan)
447                  locale == "ar_SY" || // Arabic (Syria)
448                  locale == "ar_TN" || // Arabic (Tunisia)
449                  locale == "ar_YE")   // Arabic (Yemen)
450             return fontArabicGlyphRanges;
451             
452         else if (locale == "hy_AM") // Armenian 
453             return fontArmenianGlyphRanges;
454             
455         else if (locale == "ka_GE") // Georgian 
456             return fontArmenianGlyphRanges;
457             
458         else // Assume English
459             return fontDefaultGlyphRanges;
460     }
461 
462     NKFont* addFont(FontAsset font, float height = 13, const(NKRune[]) range = fontDefaultGlyphRanges)
463     {
464         return addFont(font.buffer.ptr, font.buffer.length, height, range);
465     }
466 
467     NKFont* addFont(ubyte* buffer, ulong len, float height = 13, const(NKRune[]) range = fontDefaultGlyphRanges)
468     {
469         nk_font_config cfg = nk_font_config_(0);
470         cfg.range = range.ptr;
471 
472         nk_font_atlas atlas;
473         nk_font_atlas_init_default(&atlas);
474         nk_font_atlas_begin(&atlas);
475 
476         nk_font* nkfont;
477         if(buffer)
478             nkfont = nk_font_atlas_add_from_memory(&atlas, buffer, cast(int)len, height, &cfg);
479         else
480             nkfont = nk_font_atlas_add_default(&atlas, height, &cfg);
481 
482         atlas.default_font = nkfont;
483 
484         int w = 0;
485         int h = 0;
486         const(void)* image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
487 
488         GLuint texture;
489         glGenTextures(1, &texture);
490         glBindTexture(GL_TEXTURE_2D, texture);
491         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
492         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
493         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cast(GLsizei)w, cast(GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
494 
495         nk_font_atlas_end(&atlas, nk_handle_id(cast(int)texture), &nullTexture);
496         nk_style_set_font(&ctx, &atlas.default_font.handle);
497 
498         atlases.insertBack(atlas);
499         fontsTextures.insertBack(texture);
500 
501         return nkfont;
502     }
503 
504     deprecated("No need to call generateFontAtlas()") void generateFontAtlas() {}
505 
506     NKFont* getFont(uint index)
507     {
508         if(index >= atlases.length)
509             return atlases[0].default_font;
510 
511         return atlases[index].default_font;
512     }
513 
514     float textWidth(const(char)* txt, int len)
515     {
516         const(nk_user_font) *f = ctx.style.font;
517         return f.width(cast(nk_handle)f.userdata, f.height, txt, len);
518     }
519 
520     float textWidth(NKFont* font, const(char)* txt, int len)
521     {
522         const(nk_user_font) *f = &font.handle;
523         return f.width(cast(nk_handle)f.userdata, f.height, txt, len);
524     }
525 
526     void inputKey(nk_keys key, int down)
527     {
528         auto e = NuklearEvent(NuklearEventType.Key);
529         e.key = key;
530         e.down = down;
531         if (eventsCount < 10)
532             events[eventsCount++] = e;
533     }
534 
535     void inputKeyDown(nk_keys key)
536     {
537         inputKey(key, 1);
538     }
539 
540     void inputKeyUp(nk_keys key)
541     {
542         inputKey(key, 0);
543     }
544 
545     void inputButton(int button, int down)
546     {
547         auto e = NuklearEvent(NuklearEventType.MouseButton);
548         switch (button)
549         {
550             case MB_LEFT: e.button = nk_buttons.NK_BUTTON_LEFT; break;
551             case MB_MIDDLE: e.button = nk_buttons.NK_BUTTON_MIDDLE; break;
552             case MB_RIGHT: e.button = nk_buttons.NK_BUTTON_RIGHT; break;
553             default:
554                 break;
555         }
556         e.x = eventManager.mouseX;
557         e.y = eventManager.mouseY;
558         e.down = down;
559         if (eventsCount < 10)
560             events[eventsCount++] = e;
561     }
562 
563     void inputButtonDown(int button)
564     {
565         inputButton(button, 1);
566     }
567 
568     void inputButtonUp(int button)
569     {
570         inputButton(button, 0);
571     }
572 
573     void inputScroll(int x, int y)
574     {
575         auto e = NuklearEvent(NuklearEventType.MouseScroll);
576         e.x = x;
577         e.y = y;
578         if (eventsCount < 10)
579             events[eventsCount++] = e;
580     }
581 
582     void inputUnicode(dchar key)
583     {
584         auto e = NuklearEvent(NuklearEventType.TextInput);
585         e.unicode = key;
586         if (eventsCount < 10)
587             events[eventsCount++] = e;
588     }
589 
590     int begin(const(char)* title, NKRect bounds, NKFlags flags)
591     {
592         return nk_begin(&ctx, title, bounds, flags);
593     }
594 
595     int beginTitled(const(char)* name, const(char)* title, NKRect bounds, NKFlags flags)
596     {
597         return nk_begin_titled(&ctx, name, title, bounds, flags);
598     }
599 
600     void end()
601     {
602         nk_end(&ctx);
603     }
604 
605     nk_style_window oldWindowStyle;
606 
607     int canvasBegin(const(char)* title, NKRect bounds, NKColor background = NKColor(255,255,255,255))
608     {
609         oldWindowStyle = ctx.style.window;
610 
611         ctx.style.window.spacing = nk_vec2(0, 0);
612         ctx.style.window.padding = nk_vec2(0, 0);
613         ctx.style.window.fixed_background = nk_style_item_color(background);
614 
615         nk_begin(&ctx, title, bounds, NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_BACKGROUND | NK_WINDOW_NO_INPUT);
616 
617         nk_rect totalSpace = nk_window_get_content_region(&ctx);
618         nk_layout_row_dynamic(&ctx, totalSpace.h, 1);
619         nk_widget(&totalSpace, &ctx);
620 
621         return 1;
622     }
623 
624     void canvasEnd()
625     {
626         nk_end(&ctx);
627         ctx.style.window = oldWindowStyle;
628     }
629 
630     NKWindow* windowFind(const(char)* name)
631     {
632         return nk_window_find(&ctx, name);
633     }
634 
635     NKPanel* windowGetPanel()
636     {
637         return nk_window_get_panel(&ctx);
638     }
639 
640     NKRect windowGetContentRegion()
641     {
642         return nk_window_get_content_region(&ctx);
643     }
644 
645     NKVec2 windowGetContentRegionMin()
646     {
647         return nk_window_get_content_region_min(&ctx);
648     }
649 
650     NKVec2 windowGetContentRegionMax()
651     {
652         return nk_window_get_content_region_max(&ctx);
653     }
654 
655     NKVec2 windowGetContentRegionSize()
656     {
657         return nk_window_get_content_region_size(&ctx);
658     }
659 
660     nk_command_buffer* windowGetCanvas()
661     {
662         return nk_window_get_canvas(&ctx);
663     }
664 
665     int windowIsHovered()
666     {
667         return nk_window_is_hovered(&ctx);
668     }
669 
670     int windowIsCollapsed(const(char)* name)
671     {
672         return nk_window_is_collapsed(&ctx, name);
673     }
674 
675     int windowIsClosed(const(char)* name)
676     {
677         return nk_window_is_closed(&ctx,  name);
678     }
679 
680     int windowIsHidden(const(char)* name)
681     {
682         return nk_window_is_hidden(&ctx,  name);
683     }
684 
685     int windowIsActive(const(char)* name)
686     {
687         return nk_window_is_active(&ctx, name);
688     }
689 
690     int windowIsAnyHovered()
691     {
692         return nk_window_is_any_hovered(&ctx);
693     }
694 
695     int itemIsAnyActive()
696     {
697         return nk_item_is_any_active(&ctx);
698     }
699 
700     void windowSetBounds(const(char)* name, NKRect bounds)
701     {
702         nk_window_set_bounds(&ctx, name, bounds);
703     }
704 
705     void windowSetPosition(const(char)* name, NKVec2 pos)
706     {
707         nk_window_set_position(&ctx, name, pos);
708     }
709 
710     void windowSetSize(const(char)* name, NKVec2 size)
711     {
712         nk_window_set_size(&ctx, name, size);
713     }
714 
715     void windowSetFocus(const(char)* name)
716     {
717         nk_window_set_focus(&ctx, name);
718     }
719 
720     void windowClose(const(char)* name)
721     {
722         nk_window_close(&ctx, name);
723     }
724 
725     void windowCollapse(const(char)* name, nk_collapse_states state)
726     {
727         nk_window_collapse(&ctx, name, state);
728     }
729 
730     void windowCollapseIf(const(char)* name, nk_collapse_states state, int cond)
731     {
732         nk_window_collapse_if (&ctx, name, state, cond);
733     }
734 
735     void windowShow(const(char)* name, nk_show_states state)
736     {
737         nk_window_show(&ctx, name, state);
738     }
739 
740     void windowShowIf(const(char)* name, nk_show_states state, int cond)
741     {
742         nk_window_show_if (&ctx, name, state, cond);
743     }
744 
745     void layoutSetMinRowHeight(float height)
746     {
747         nk_layout_set_min_row_height(&ctx, height);
748     }
749 
750     void layoutResetMinRowHeight()
751     {
752         nk_layout_reset_min_row_height(&ctx);
753     }
754 
755     NKRect layoutWidgetBounds()
756     {
757         return nk_layout_widget_bounds(&ctx);
758     }
759 
760     float layoutRatioFromPixel(float pixel_width)
761     {
762         return nk_layout_ratio_from_pixel(&ctx, pixel_width);
763     }
764 
765     void layoutRowDynamic(float height, int cols)
766     {
767         nk_layout_row_dynamic(&ctx, height, cols);
768     }
769 
770     void layoutRowStatic(float height, int item_width, int cols)
771     {
772         nk_layout_row_static(&ctx, height, item_width, cols);
773     }
774 
775     void layoutRowBegin(nk_layout_format fmt, float row_height, int cols)
776     {
777         nk_layout_row_begin(&ctx, fmt, row_height, cols);
778     }
779 
780     void layoutRowPush(float value)
781     {
782         nk_layout_row_push(&ctx, value);
783     }
784 
785     void layoutRowEnd()
786     {
787         nk_layout_row_end(&ctx);
788     }
789 
790     void layoutRow(nk_layout_format format, float height, int cols, const(float)* ratio)
791     {
792         nk_layout_row(&ctx, format, height, cols, ratio);
793     }
794 
795     void layoutRowTemplateBegin(float row_height)
796     {
797         nk_layout_row_template_begin(&ctx, row_height);
798     }
799 
800     void layoutRowTemplatePushDynamic()
801     {
802         nk_layout_row_template_push_dynamic(&ctx);
803     }
804 
805     void layoutRowTemplatePushVariable(float min_width)
806     {
807         nk_layout_row_template_push_variable(&ctx, min_width);
808     }
809 
810     void layoutRowTemplatePushStatic(float width)
811     {
812         nk_layout_row_template_push_static(&ctx, width);
813     }
814 
815     void layoutRowTemplateEnd()
816     {
817         nk_layout_row_template_end(&ctx);
818     }
819 
820     void layoutSpaceBegin(nk_layout_format foramt, float height, int widget_count)
821     {
822         nk_layout_space_begin(&ctx, foramt, height, widget_count);
823     }
824 
825     void layoutSpacePush(NKRect bounds)
826     {
827         nk_layout_space_push(&ctx, bounds);
828     }
829 
830     void layoutSpaceEnd()
831     {
832         nk_layout_space_end(&ctx);
833     }
834 
835     NKRect layoutSpaceBounds()
836     {
837         return nk_layout_space_bounds(&ctx);
838     }
839 
840     NKVec2 layoutSpaceToScreen(NKVec2 a)
841     {
842         return nk_layout_space_to_screen(&ctx, a);
843     }
844 
845     NKVec2 layoutSpaceToLocal(NKVec2 a)
846     {
847         return nk_layout_space_to_local(&ctx, a);
848     }
849 
850     NKRect layoutSpaceRectToScreen(NKRect a)
851     {
852         return nk_layout_space_rect_to_screen(&ctx, a);
853     }
854 
855     NKRect layoutSpaceRectToLocal(NKRect a)
856     {
857         return nk_layout_space_rect_to_local(&ctx, a);
858     }
859 
860     int groupBegin(const(char)* title, NKFlags flags)
861     {
862         return nk_group_begin(&ctx, title, flags);
863     }
864 
865     int groupBeginTitled(const(char)* name, const(char)* title, NKFlags flags)
866     {
867         return nk_group_begin_titled(&ctx, name, title, flags);
868     }
869 
870     void groupEnd()
871     {
872         nk_group_end(&ctx);
873     }
874 
875     int groupScrolledOffsetBegin(nk_uint* x_offset, nk_uint* y_offset, const(char)* title, NKFlags flags)
876     {
877         return nk_group_scrolled_offset_begin(&ctx, x_offset, y_offset, title, flags);
878     }
879 
880     int groupScrolledBegin(nk_scroll* off, const(char)* title, NKFlags flags)
881     {
882         return nk_group_scrolled_begin(&ctx, off, title, flags);
883     }
884 
885     void groupScrolledEnd()
886     {
887         nk_group_scrolled_end(&ctx);
888     }
889 
890     int treePush(size_t line = __LINE__)(nk_tree_type type, const(char) *title, nk_collapse_states state)
891     {
892         return nk_tree_push_hashed(&ctx, type, title, state, null, 0, line);
893     }
894 
895     int treePushId(nk_tree_type type, const(char) *title, nk_collapse_states state, int id)
896     {
897         return nk_tree_push_hashed(&ctx, type, title, state, null, 0, id);
898     }
899 
900     void treePop()
901     {
902         nk_tree_pop(&ctx);
903     }
904 
905     int treeStatePush(nk_tree_type type, const(char)* title, nk_collapse_states* state)
906     {
907         return nk_tree_state_push(&ctx, type, title, state);
908     }
909 
910     int treeStateImagePush(nk_tree_type type, NKImage image, const(char)* title, nk_collapse_states* state)
911     {
912         return nk_tree_state_image_push(&ctx, type, image, title, state);
913     }
914 
915     void treeStatePop()
916     {
917         nk_tree_state_pop(&ctx);
918     }
919 
920     auto treeElementPush(size_t line = __LINE__)(nk_tree_type type, const(char) *title, nk_collapse_states state, int* selected)
921     {
922         return nk_tree_element_push_hashed(&ctx, type, title, state, selected, null, 0, line);
923     }
924 
925     auto treeElementPushId(nk_tree_type type, const(char) *title, nk_collapse_states state, int* selected, int id)
926     {
927         return nk_tree_element_push_hashed(&ctx, type, title, state, selected, null, 0, id);
928     }
929 
930     auto treeElementImagePush(size_t line = __LINE__)(nk_tree_type type, NKImage img, const(char) *title, nk_collapse_states state)
931     {
932         return nk_tree_image_push_hashed(&ctx, type, img, title, state, null, 0, line);
933     }
934 
935     auto treeElementImagePushId(nk_tree_type type, NKImage img, const(char) *title, nk_collapse_states state, int id)
936     {
937         return nk_tree_image_push_hashed(&ctx, type, img, title, state, null, 0, id);
938     }
939 
940     void treeElementPop()
941     {
942         nk_tree_element_pop(&ctx);
943     }
944 
945     int listViewBegin(nk_list_view* out_, const(char)* id, NKFlags flags, int row_height, int row_count)
946     {
947         return nk_list_view_begin(&ctx, out_, id, flags, row_height, row_count);
948     }
949 
950     NKRect widgetBounds()
951     {
952         return nk_widget_bounds(&ctx);
953     }
954 
955     NKVec2 widgetPosition()
956     {
957         return nk_widget_position(&ctx);
958     }
959 
960     NKVec2 widgetSize()
961     {
962         return nk_widget_size(&ctx);
963     }
964 
965     float widgetWidth()
966     {
967         return nk_widget_width(&ctx);
968     }
969 
970     float widgetHeight()
971     {
972         return nk_widget_height(&ctx);
973     }
974 
975     int widgetIsHovered()
976     {
977         return nk_widget_is_hovered(&ctx);
978     }
979 
980     int widgetIsMouseClicked(nk_buttons buttons)
981     {
982         return nk_widget_is_mouse_clicked(&ctx, buttons);
983     }
984 
985     int widgetHasMouseClickDown(nk_buttons buttons, int down)
986     {
987         return nk_widget_has_mouse_click_down(&ctx, buttons, down);
988     }
989 
990     void spacing(int cols)
991     {
992         nk_spacing(&ctx, cols);
993     }
994 
995     void text(const(char)* txt, int len, NKFlags flags)
996     {
997         nk_text(&ctx, txt, len, flags);
998     }
999 
1000     void textColored(const(char)* txt, int len, NKFlags flags, NKColor color)
1001     {
1002         nk_text_colored(&ctx, txt, len, flags, color);
1003     }
1004 
1005     void textWrap(const(char)* txt, int len)
1006     {
1007         nk_text_wrap(&ctx, txt, len);
1008     }
1009 
1010     void textWrapColored(const(char)* txt, int len, NKColor color)
1011     {
1012         nk_text_wrap_colored(&ctx, txt, len, color);
1013     }
1014 
1015     void label(const(char)* txt, NKFlags align__)
1016     {
1017         nk_label(&ctx, txt, align__);
1018     }
1019 
1020     void labelColored(const(char)* txt, NKFlags align__, NKColor color)
1021     {
1022         nk_label_colored(&ctx, txt, align__, color);
1023     }
1024 
1025     void labelWrap(const(char)* txt)
1026     {
1027         nk_label_wrap(&ctx, txt);
1028     }
1029 
1030     void labelColoredWrap(const(char)* txt, NKColor color)
1031     {
1032         nk_label_colored_wrap(&ctx, txt, color);
1033     }
1034 
1035     void image(NKImage img)
1036     {
1037         nk_image_(&ctx, img);
1038     }
1039 
1040     void imageColor(NKImage img, NKColor color)
1041     {
1042         nk_image_color(&ctx, img, color);
1043     }
1044 
1045     void labelf(NKFlags align_, const(char)* format, ...)
1046     {
1047         va_list args;
1048         va_start(args, format);
1049         nk_labelfv(&ctx, align_, format, args);
1050     }
1051 
1052     void labelfColored(NKFlags align_, NKColor color, const(char)* format, ...)
1053     {
1054         va_list args;
1055         va_start(args, format);
1056         nk_labelf_colored(&ctx, align_, color, format, args);
1057     }
1058 
1059     void labelfWrap(const(char)* format, ...)
1060     {
1061         va_list args;
1062         va_start(args, format);
1063         nk_labelf_wrap(&ctx, format, args);
1064     }
1065 
1066     void labelfColoredWrap(NKColor color, const(char)* format, ...)
1067     {
1068         va_list args;
1069         va_start(args, format);
1070         nk_labelf_colored_wrap(&ctx, color, format, args);
1071     }
1072 
1073     void valueBool(const(char)* prefix, int value)
1074     {
1075         nk_value_bool(&ctx, prefix, value);
1076     }
1077 
1078     void valueInt(const(char)* prefix, int value)
1079     {
1080         nk_value_int(&ctx, prefix, value);
1081     }
1082 
1083     void valueUint(const(char)* prefix, uint value)
1084     {
1085         nk_value_uint(&ctx, prefix, value);
1086     }
1087 
1088     void valueFloat(const(char)* prefix, float value)
1089     {
1090         nk_value_float(&ctx, prefix, value);
1091     }
1092 
1093     void valueColorByte(const(char)* prefix, NKColor value)
1094     {
1095         nk_value_color_byte(&ctx, prefix, value);
1096     }
1097 
1098     void valueColorFloat(const(char)* prefix, NKColor value)
1099     {
1100         nk_value_color_float(&ctx, prefix, value);
1101     }
1102 
1103     void valueColorHex(const(char)* prefix, NKColor value)
1104     {
1105         nk_value_color_hex(&ctx, prefix, value);
1106     }
1107 
1108     int buttonText(const(char)* title, int len)
1109     {
1110         return nk_button_text(&ctx, title, len);
1111     }
1112 
1113     int buttonLabel(const(char)* title)
1114     {
1115         return nk_button_label(&ctx, title);
1116     }
1117 
1118     int buttonColor(NKColor color)
1119     {
1120         return nk_button_color(&ctx,  color);
1121     }
1122 
1123     int buttonSymbol(nk_symbol_type type)
1124     {
1125         return nk_button_symbol(&ctx, type);
1126     }
1127 
1128     int buttonImage(NKImage img)
1129     {
1130         return nk_button_image(&ctx, img);
1131     }
1132 
1133     int buttonSymbolLabel(nk_symbol_type type, const(char)* label, NKFlags text_alignment)
1134     {
1135         return nk_button_symbol_label(&ctx, type, label, text_alignment);
1136     }
1137 
1138     int buttonSymbolText(nk_symbol_type type, const(char)* txt, int len, NKFlags align_ment)
1139     {
1140         return nk_button_symbol_text(&ctx, type, txt, len, align_ment);
1141     }
1142 
1143     int buttonImageLabel(NKImage img, const(char)* txt, NKFlags text_alignment)
1144     {
1145         return nk_button_image_label(&ctx, img, txt, text_alignment);
1146     }
1147 
1148     int buttonImageText(NKImage img, const(char)* txt, int len, NKFlags align_ment)
1149     {
1150         return nk_button_image_text(&ctx, img, txt, len, align_ment);
1151     }
1152 
1153     int buttonTextStyled(const(nk_style_button)* style, const(char)* title, int len)
1154     {
1155         return nk_button_text_styled(&ctx, style, title, len);
1156     }
1157 
1158     int buttonLabelStyled(const(nk_style_button)* style, const(char)* title)
1159     {
1160         return nk_button_label_styled(&ctx, style, title);
1161     }
1162 
1163     int buttonSymbolStyled(const(nk_style_button)* style, nk_symbol_type type)
1164     {
1165         return nk_button_symbol_styled(&ctx, style, type);
1166     }
1167 
1168     int buttonImageStyled(const(nk_style_button)* style, NKImage img)
1169     {
1170         return nk_button_image_styled(&ctx, style, img);
1171     }
1172 
1173     int buttonSymbolTextStyled(const(nk_style_button)* style, nk_symbol_type type, const(char)* txt, int len, NKFlags align_ment)
1174     {
1175         return nk_button_symbol_text_styled(&ctx, style, type, txt, len, align_ment);
1176     }
1177 
1178     int buttonSymbolLabelStyled(const(nk_style_button)* style, nk_symbol_type symbol, const(char)* title, NKFlags align_)
1179     {
1180         return nk_button_symbol_label_styled(&ctx, style, symbol, title, align_);
1181     }
1182 
1183     int buttonImageLabelStyled(const(nk_style_button)* style, NKImage img, const(char)* label, NKFlags text_alignment)
1184     {
1185         return nk_button_image_label_styled(&ctx, style, img, label, text_alignment);
1186     }
1187 
1188     int buttonImageTextStyled(const(nk_style_button)* style, NKImage img, const(char)* txt, int len, NKFlags align_ment)
1189     {
1190         return nk_button_image_text_styled(&ctx, style, img, txt, len, align_ment);
1191     }
1192 
1193     void buttonSetBehavior(nk_button_behavior beh)
1194     {
1195         nk_button_set_behavior(&ctx, beh);
1196     }
1197 
1198     int buttonPushBehavior(nk_button_behavior beh)
1199     {
1200         return nk_button_push_behavior(&ctx, beh);
1201     }
1202 
1203     int buttonPopBehavior()
1204     {
1205         return nk_button_pop_behavior(&ctx);
1206     }
1207 
1208     int checkLabel(const(char)* label, int active)
1209     {
1210         return nk_check_label(&ctx, label, active);
1211     }
1212 
1213     int checkText(const(char)* txt, int len, int active)
1214     {
1215         return nk_check_text(&ctx, txt, len, active);
1216     }
1217 
1218     uint checkFlagsLabel(const(char)* label, uint flags, uint value)
1219     {
1220         return nk_check_flags_label(&ctx, label, flags, value);
1221     }
1222 
1223     uint checkFlagsText(const(char)* txt, int len, uint flags, uint value)
1224     {
1225         return nk_check_flags_text(&ctx, txt, len, flags, value);
1226     }
1227 
1228     int checkboxLabel(const(char)* label, int* active)
1229     {
1230         return nk_checkbox_label(&ctx, label, active);
1231     }
1232 
1233     int checkboxText(const(char)* txt, int len, int* active)
1234     {
1235         return nk_checkbox_text(&ctx, txt, len, active);
1236     }
1237 
1238     int checkboxFlagsLabel(const(char)* label, uint* flags, uint value)
1239     {
1240         return nk_checkbox_flags_label(&ctx, label, flags, value);
1241     }
1242 
1243     int checkboxFlagsText(const(char)* txt, int len, uint* flags, uint value)
1244     {
1245         return nk_checkbox_flags_text(&ctx, txt, len, flags, value);
1246     }
1247 
1248     int radioLabel(const(char)* label, int* active)
1249     {
1250         return nk_radio_label(&ctx, label, active);
1251     }
1252 
1253     int radioText(const(char)* txt, int len, int* active)
1254     {
1255         return nk_radio_text(&ctx, txt, len, active);
1256     }
1257 
1258     int optionLabel(const(char)* label, int active)
1259     {
1260         return nk_option_label(&ctx, label, active);
1261     }
1262 
1263     int optionText(const(char)* txt, int len, int active)
1264     {
1265         return nk_option_text(&ctx, txt, len, active);
1266     }
1267 
1268     int selectableLabel(const(char)* label, NKFlags align_, int* value)
1269     {
1270         return nk_selectable_label(&ctx, label, align_, value);
1271     }
1272 
1273     int selectableText(const(char)* txt, int len, NKFlags align_, int* value)
1274     {
1275         return nk_selectable_text(&ctx, txt, len, align_, value);
1276     }
1277 
1278     int selectableImageLabel(NKImage img, const(char)* label, NKFlags align_, int* value)
1279     {
1280         return nk_selectable_image_label(&ctx, img, label, align_, value);
1281     }
1282 
1283     int selectableImageText(NKImage img, const(char)* text, int len, NKFlags align_, int* value)
1284     {
1285         return nk_selectable_image_text(&ctx, img, text, len, align_, value);
1286     }
1287 
1288     int selectableSymbolLabel(nk_symbol_type type, const(char)* label, NKFlags align_, int* value)
1289     {
1290         return nk_selectable_symbol_label(&ctx, type, label, align_, value);
1291     }
1292 
1293     int selectableSymbolText(nk_symbol_type type, const(char)* txt, int len, NKFlags align_, int* value)
1294     {
1295         return nk_selectable_symbol_text(&ctx, type, txt, len, align_, value);
1296     }
1297 
1298     int selectLabel(const(char)* label, NKFlags align_, int value)
1299     {
1300         return nk_select_label(&ctx, label, align_, value);
1301     }
1302 
1303     int selectText(const(char)* txt, int len, NKFlags align_, int value)
1304     {
1305         return nk_select_text(&ctx, txt, len, align_, value);
1306     }
1307 
1308     int selectImageLabel(NKImage img, const(char)* label, NKFlags align_, int value)
1309     {
1310         return nk_select_image_label(&ctx, img, label, align_, value);
1311     }
1312 
1313     int selectImageText(NKImage img, const(char)* txt, int len, NKFlags align_, int value)
1314     {
1315         return nk_select_image_text(&ctx, img, txt, len, align_, value);
1316     }
1317 
1318     int selectSymbolLabel(nk_symbol_type type, const(char)* label, NKFlags align_, int value)
1319     {
1320         return nk_select_symbol_label(&ctx, type, label, align_, value);
1321     }
1322 
1323     int selectSymbolText(nk_symbol_type type, const(char)* txt, int len, NKFlags align_, int value)
1324     {
1325         return nk_select_symbol_text(&ctx, type, txt, len, align_, value);
1326     }
1327 
1328     float slide(float min, float val, float max, float step)
1329     {
1330         return nk_slide_float(&ctx,min, val, max, step);
1331     }
1332 
1333     int slide(int min, int val, int max, int step)
1334     {
1335         return nk_slide_int(&ctx,min, val, max, step);
1336     }
1337 
1338     int slider(float min, float* val, float max, float step)
1339     {
1340         return nk_slider_float(&ctx, min, val, max, step);
1341     }
1342 
1343     int slider(int min, int* val, int max, int step)
1344     {
1345         return nk_slider_int(&ctx, min, val, max, step);
1346     }
1347 
1348     int progress(NKSize* cur, NKSize max, int modifyable)
1349     {
1350         return nk_progress(&ctx, cur, max, modifyable);
1351     }
1352 
1353     NKSize prog(NKSize cur, NKSize max, int modifyable)
1354     {
1355         return nk_prog(&ctx, cur, max, modifyable);
1356     }
1357 
1358     NKColorf colorPicker(NKColorf color, nk_color_format format)
1359     {
1360         return nk_color_picker(&ctx, color, format);
1361     }
1362 
1363     Color4f colorPicker(Color4f color, nk_color_format format)
1364     {   
1365         nk_colorf tmp = nk_colorf(color.r, color.g, color.b, color.a);
1366         tmp = nk_color_picker(&ctx, tmp, format);
1367         return Color4f(tmp.r, tmp.g, tmp.b, tmp.a);
1368     }
1369 
1370     int colorPick(NKColorf* color, nk_color_format format)
1371     {
1372         return nk_color_pick(&ctx, color, format);
1373     }
1374 
1375     int colorPick(Color4f* color, nk_color_format format)
1376     {
1377         nk_colorf tmp = nk_colorf(color.r, color.g, color.b, color.a);
1378         int res = nk_color_pick(&ctx, &tmp, format);
1379         *color = Color4f(tmp.r, tmp.g, tmp.b, tmp.a);
1380         return res;
1381     }
1382 
1383     void property(const(char)* name, int min, int* val, int max, int step, float inc_per_pixel)
1384     {
1385         nk_property_int(&ctx, name, min, val, max, step, inc_per_pixel);
1386     }
1387 
1388     void property(const(char)* name, float min, float* val, float max, float step, float inc_per_pixel)
1389     {
1390         nk_property_float(&ctx, name, min, val, max, step, inc_per_pixel);
1391     }
1392 
1393     void property(const(char)* name, double min, double* val, double max, double step, float inc_per_pixel)
1394     {
1395         nk_property_double(&ctx, name, min, val, max, step, inc_per_pixel);
1396     }
1397 
1398     int property(const(char)* name, int min, int val, int max, int step, float inc_per_pixel)
1399     {
1400         return nk_propertyi(&ctx, name, min, val, max, step, inc_per_pixel);
1401     }
1402 
1403     float property(const(char)* name, float min, float val, float max, float step, float inc_per_pixel)
1404     {
1405         return nk_propertyf(&ctx, name, min, val, max, step, inc_per_pixel);
1406     }
1407 
1408     double property(const(char)* name, double min, double val, double max, double step, float inc_per_pixel)
1409     {
1410         return nk_propertyd(&ctx, name, min, val, max, step, inc_per_pixel);
1411     }
1412 
1413     alias nk_filter_default filterDefault;
1414     alias nk_filter_ascii filterAscii;
1415     alias nk_filter_float filterFloat;
1416     alias nk_filter_decimal filterDecimal;
1417     alias nk_filter_hex filterHex;
1418     alias nk_filter_oct filterOct;
1419     alias nk_filter_binary filterBinary;
1420 
1421     NKFlags editString(NKFlags flags, char* buffer, int* len, int max, nk_plugin_filter filter = filterDefault)
1422     {
1423         return nk_edit_string(&ctx, flags, buffer, len, max, filter);
1424     }
1425 
1426     NKFlags editStringZeroTerminated(NKFlags flags, char* buffer, int max, nk_plugin_filter filter = filterDefault)
1427     {
1428         return nk_edit_string_zero_terminated(&ctx, flags, buffer, max, filter);
1429     }
1430 
1431     NKFlags editBuffer(NKFlags flags, nk_text_edit* edit, nk_plugin_filter filter = filterDefault)
1432     {
1433         return nk_edit_buffer(&ctx, flags, edit, filter);
1434     }
1435 
1436     void editFocus(NKFlags flags)
1437     {
1438         nk_edit_focus(&ctx, flags);
1439     }
1440 
1441     void editUnfocus()
1442     {
1443         nk_edit_unfocus(&ctx);
1444     }
1445 
1446     int chartBegin(nk_chart_type type, int num, float min, float max)
1447     {
1448         return nk_chart_begin(&ctx, type, num, min, max);
1449     }
1450 
1451     int chartBeginColored(nk_chart_type type, NKColor color, NKColor active, int num, float min, float max)
1452     {
1453         return nk_chart_begin_colored(&ctx, type, color, active, num, min, max);
1454     }
1455 
1456     void chartAddSlot(const(nk_chart_type) type, int count, float min_value, float max_value)
1457     {
1458         nk_chart_add_slot(&ctx, type, count, min_value, max_value);
1459     }
1460 
1461     void chartAddSlotColored(const(nk_chart_type) type, NKColor color, NKColor active, int count, float min_value, float max_value)
1462     {
1463         nk_chart_add_slot_colored(&ctx, type, color, active, count, min_value, max_value);
1464     }
1465 
1466     NKFlags chartPush(float value)
1467     {
1468         return nk_chart_push(&ctx, value);
1469     }
1470 
1471     NKFlags chartPushSlot(float value, int slot)
1472     {
1473         return nk_chart_push_slot(&ctx, value, slot);
1474     }
1475 
1476     void chartEnd()
1477     {
1478         nk_chart_end(&ctx);
1479     }
1480 
1481     void plot(nk_chart_type type, const(float)* values, int count, int offset)
1482     {
1483         nk_plot(&ctx, type, values, count, offset);
1484     }
1485 
1486     void plotFunction(nk_chart_type type, float function(int index) fn, int count, int offset)
1487     {
1488         import std.algorithm : min, max;
1489         int i = 0;
1490         float min_value;
1491         float max_value;
1492 
1493         if (count == 0) return;
1494 
1495         max_value = min_value = fn(offset);
1496         for (i = 0; i < count; ++i)
1497         {
1498             float value = fn(i + offset);
1499             min_value = min(value, min_value);
1500             max_value = max(value, max_value);
1501         }
1502 
1503         if (nk_chart_begin(&ctx, type, count, min_value, max_value))
1504         {
1505             for (i = 0; i < count; ++i)
1506                 nk_chart_push(&ctx, fn(i + offset));
1507             nk_chart_end(&ctx);
1508         }
1509     }
1510 
1511     int popupBegin(nk_popup_type type, const(char)* title, NKFlags flags, NKRect bounds)
1512     {
1513         return nk_popup_begin(&ctx, type, title, flags, bounds);
1514     }
1515 
1516     void popupClose()
1517     {
1518         nk_popup_close(&ctx);
1519     }
1520 
1521     void popupEnd()
1522     {
1523         nk_popup_end(&ctx);
1524     }
1525 
1526     int combo(const(char)** items, int count, int selected, int item_height, NKVec2 size)
1527     {
1528         return nk_combo(&ctx, items, count, selected, item_height, size);
1529     }
1530 
1531     int comboSeparator(const(char)* items_separated_by_separator, int separator, int selected, int count, int item_height, NKVec2 size)
1532     {
1533         return nk_combo_separator(&ctx, items_separated_by_separator, separator, selected, count, item_height, size);
1534     }
1535 
1536     int comboString(const(char)* items_separated_by_zeros, int selected, int count, int item_height, NKVec2 size)
1537     {
1538         return nk_combo_string(&ctx, items_separated_by_zeros, selected, count, item_height, size);
1539     }
1540 
1541     /*int comboCallback(void func(void*, int, const(char) **) fn, void *userdata, int selected, int count, int item_height, NKVec2 size)
1542     {
1543     return nk_combo_callback(&ctx, fn, userdata, selected, count, item_height, size);
1544     }*/
1545 
1546     void combobox(const(char)** items, int count, int* selected, int item_height, NKVec2 size)
1547     {
1548         nk_combobox(&ctx, items, count, selected, item_height, size);
1549     }
1550 
1551     void comboboxString(const(char)* items_separated_by_zeros, int* selected, int count, int item_height, NKVec2 size)
1552     {
1553         nk_combobox_string(&ctx, items_separated_by_zeros, selected, count, item_height, size);
1554     }
1555 
1556     void comboboxSeparator(const(char)* items_separated_by_separator, int separator, int* selected, int count, int item_height, NKVec2 size)
1557     {
1558         nk_combobox_separator(&ctx, items_separated_by_separator, separator, selected, count, item_height, size);
1559     }
1560 
1561     /*void comboboxCallback(void function(void*, int, const(char) **), void*, int *selected, int count, int item_height, NKVec2 size)
1562     {
1563     nk_combobox_callback(&ctx);
1564     }*/
1565     
1566     int comboBeginText(const(char)* selected, int len, NKVec2 size)
1567     {
1568         return nk_combo_begin_text(&ctx, selected, len, size);
1569     }
1570 
1571     int comboBeginLabel(const(char)* selected, NKVec2 size)
1572     {
1573         return nk_combo_begin_label(&ctx, selected, size);
1574     }
1575 
1576     int comboBeginColor(NKColor color, NKVec2 size)
1577     {
1578         return nk_combo_begin_color(&ctx, color, size);
1579     }
1580 
1581     int comboBeginSymbol(nk_symbol_type type, NKVec2 size)
1582     {
1583         return nk_combo_begin_symbol(&ctx, type, size);
1584     }
1585 
1586     int comboBeginSymbolLabel(const(char)* selected, nk_symbol_type type, NKVec2 size)
1587     {
1588         return nk_combo_begin_symbol_label(&ctx, selected, type, size);
1589     }
1590 
1591     int comboBeginSymbolText(const(char)* selected, int len, nk_symbol_type type, NKVec2 size)
1592     {
1593         return nk_combo_begin_symbol_text(&ctx, selected, len, type, size);
1594     }
1595 
1596     int comboBeginImage(NKImage img, NKVec2 size)
1597     {
1598         return nk_combo_begin_image(&ctx, img, size);
1599     }
1600 
1601     int comboBeginImageLabel(const(char)* selected, NKImage img, NKVec2 size)
1602     {
1603         return nk_combo_begin_image_label(&ctx, selected, img, size);
1604     }
1605 
1606     int comboBeginImageText(const(char)* selected, int len, NKImage img, NKVec2 size)
1607     {
1608         return nk_combo_begin_image_text(&ctx, selected, len, img, size);
1609     }
1610 
1611     int comboItemLabel(const(char)* label, NKFlags align_ment)
1612     {
1613         return nk_combo_item_label(&ctx, label, align_ment);
1614     }
1615 
1616     int comboItemText(const(char)* txt, int len, NKFlags align_ment)
1617     {
1618         return nk_combo_item_text(&ctx, txt, len, align_ment);
1619     }
1620 
1621     int comboItemImageLabel(NKImage img, const(char)* label, NKFlags align_ment)
1622     {
1623         return nk_combo_item_image_label(&ctx, img, label, align_ment);
1624     }
1625 
1626     int comboItemImageText(NKImage img, const(char)* txt, int len, NKFlags align_ment)
1627     {
1628         return nk_combo_item_image_text(&ctx, img, txt, len, align_ment);
1629     }
1630 
1631     int comboItemSymbolLabel(nk_symbol_type type, const(char)* label, NKFlags align_ment)
1632     {
1633         return nk_combo_item_symbol_label(&ctx, type, label, align_ment);
1634     }
1635 
1636     int comboItemSymbolText(nk_symbol_type type, const(char)* txt, int len, NKFlags align_ment)
1637     {
1638         return nk_combo_item_symbol_text(&ctx, type, txt, len, align_ment);
1639     }
1640 
1641     void comboClose()
1642     {
1643         nk_combo_close(&ctx);
1644     }
1645 
1646     void comboEnd()
1647     {
1648         nk_combo_end(&ctx);
1649     }
1650 
1651     int contextualBegin(NKFlags flags, NKVec2 size, NKRect trigger_bounds)
1652     {
1653         return nk_contextual_begin(&ctx, flags, size, trigger_bounds);
1654     }
1655 
1656     int contextualItemText(const(char)* txt, int len, NKFlags align_)
1657     {
1658         return nk_contextual_item_text(&ctx, txt, len, align_);
1659     }
1660 
1661     int contextualItemLabel(const(char)* label, NKFlags align_)
1662     {
1663         return nk_contextual_item_label(&ctx, label, align_);
1664     }
1665 
1666     int contextualItemImageLabel(NKImage img, const(char)* label, NKFlags align_ment)
1667     {
1668         return nk_contextual_item_image_label(&ctx, img, label, align_ment);
1669     }
1670 
1671     int contextualItemImageText(NKImage img, const(char)* txt, int len, NKFlags align_ment)
1672     {
1673         return nk_contextual_item_image_text(&ctx, img, txt, len, align_ment);
1674     }
1675 
1676     int contextualItemSymbolLabel(nk_symbol_type type, const(char)* label, NKFlags align_ment)
1677     {
1678         return nk_contextual_item_symbol_label(&ctx, type, label, align_ment);
1679     }
1680 
1681     int contextualItemSymbolText(nk_symbol_type type, const(char)* txt, int len, NKFlags align_ment)
1682     {
1683         return nk_contextual_item_symbol_text(&ctx, type, txt, len, align_ment);
1684     }
1685 
1686     void contextualClose()
1687     {
1688         nk_contextual_close(&ctx);
1689     }
1690 
1691     void contextualEnd()
1692     {
1693         nk_contextual_end(&ctx);
1694     }
1695 
1696     void tooltip(const(char)* txt)
1697     {
1698         nk_tooltip(&ctx, txt);
1699     }
1700 
1701     void tooltipf(const(char)* format, ...)
1702     {
1703         va_list args;
1704         va_start(args, format);
1705         nk_tooltipfv(&ctx, format, args);
1706     }
1707     
1708     int tooltipBegin(float width)
1709     {
1710         return nk_tooltip_begin(&ctx, width);
1711     }
1712 
1713     void tooltipEnd()
1714     {
1715         nk_tooltip_end(&ctx);
1716     }
1717 
1718     void menubarBegin()
1719     {
1720         nk_menubar_begin(&ctx);
1721     }
1722 
1723     void menubarEnd()
1724     {
1725         nk_menubar_end(&ctx);
1726     }
1727 
1728     int menuBeginText(const(char)* title, int title_len, NKFlags align_, NKVec2 size)
1729     {
1730         return nk_menu_begin_text(&ctx, title, title_len, align_, size);
1731     }
1732 
1733     int menuBeginLabel(const(char)* label, NKFlags align_, NKVec2 size)
1734     {
1735         return nk_menu_begin_label(&ctx, label, align_, size);
1736     }
1737 
1738     int menuBeginImage(const(char)* label, NKImage img, NKVec2 size)
1739     {
1740         return nk_menu_begin_image(&ctx, label, img, size);
1741     }
1742 
1743     int menuBeginImageText(const(char)* txt, int len, NKFlags align_, NKImage img, NKVec2 size)
1744     {
1745         return nk_menu_begin_image_text(&ctx, txt, len, align_, img, size);
1746     }
1747 
1748     int menuBeginImageLabel(const(char)* label, NKFlags align_, NKImage img, NKVec2 size)
1749     {
1750         return nk_menu_begin_image_label(&ctx, label, align_, img, size);
1751     }
1752 
1753     int menuBeginSymbol(const(char)* label, nk_symbol_type type, NKVec2 size)
1754     {
1755         return nk_menu_begin_symbol(&ctx, label, type, size);
1756     }
1757 
1758     int menuBeginSymbolText(const(char)* txt, int len, NKFlags align_, nk_symbol_type type, NKVec2 size)
1759     {
1760         return nk_menu_begin_symbol_text(&ctx, txt, len, align_, type, size);
1761     }
1762 
1763     int menuBeginSymbolLabel(const(char)* label, NKFlags align_, nk_symbol_type type, NKVec2 size)
1764     {
1765         return nk_menu_begin_symbol_label(&ctx, label, align_, type, size);
1766     }
1767 
1768     int menuItemText(const(char)* txt, int len, NKFlags align_)
1769     {
1770         return nk_menu_item_text(&ctx, txt, len, align_);
1771     }
1772 
1773     int menuItemLabel(const(char)* label, NKFlags align_ment)
1774     {
1775         return nk_menu_item_label(&ctx, label, align_ment);
1776     }
1777 
1778     int menuItemImageLabel(NKImage img, const(char)* label, NKFlags align_ment)
1779     {
1780         return nk_menu_item_image_label(&ctx, img, label, align_ment);
1781     }
1782 
1783     int menuItemImageText(NKImage img, const(char)* txt, int len, NKFlags align_ment)
1784     {
1785         return nk_menu_item_image_text(&ctx, img, txt, len, align_ment);
1786     }
1787 
1788     int menuItemSymbolText(nk_symbol_type type, const(char)* txt, int len, NKFlags align_ment)
1789     {
1790         return nk_menu_item_symbol_text(&ctx, type, txt, len, align_ment);
1791     }
1792 
1793     int menuItemSymbolLabel(nk_symbol_type type, const(char)* label, NKFlags align_ment)
1794     {
1795         return nk_menu_item_symbol_label(&ctx, type, label, align_ment);
1796     }
1797 
1798     void menuClose()
1799     {
1800         nk_menu_close(&ctx);
1801     }
1802 
1803     void menuEnd()
1804     {
1805         nk_menu_end(&ctx);
1806     }
1807 
1808     void styleDefault()
1809     {
1810         nk_style_default(&ctx);
1811     }
1812 
1813     void styleFromTable(const(NKColor)* colors)
1814     {
1815         nk_style_from_table(&ctx, colors);
1816     }
1817 
1818     void styleLoadCursor(nk_style_cursor cursor, const(NKCursor)* c)
1819     {
1820         nk_style_load_cursor(&ctx, cursor, c);
1821     }
1822     
1823     void styleLoadAllCursors(NKCursor* cursor)
1824     {
1825         nk_style_load_all_cursors(&ctx, cursor);
1826     }
1827 
1828     void styleSetFont(uint index)
1829     {
1830         nk_style_set_font(&ctx, &(getFont(index)).handle);
1831     }
1832 
1833     void styleSetFont(const(NKFont)* font)
1834     {
1835         nk_style_set_font(&ctx, &font.handle);
1836     }
1837 
1838     void styleSetFont(const(nk_user_font)* font)
1839     {
1840         nk_style_set_font(&ctx, font);
1841     }
1842 
1843     int styleSetCursor(nk_style_cursor cursor)
1844     {
1845         return nk_style_set_cursor(&ctx, cursor);
1846     }
1847 
1848     void styleShowCursor()
1849     {
1850         nk_style_show_cursor(&ctx);
1851     }
1852 
1853     void styleHideCursor()
1854     {
1855         nk_style_hide_cursor(&ctx);
1856     }
1857 
1858     int stylePushFont(const(nk_user_font)* font)
1859     {
1860         return nk_style_push_font(&ctx, font);
1861     }
1862 
1863     int stylePushFloat(float* address, float value)
1864     {
1865         return nk_style_push_float(&ctx, address, value);
1866     }
1867 
1868     int stylePushVec2(NKVec2* address, NKVec2 value)
1869     {
1870         return nk_style_push_vec2(&ctx, address, value);
1871     }
1872 
1873     int stylePushStyleItem(nk_style_item* address, nk_style_item value)
1874     {
1875         return nk_style_push_style_item(&ctx, address, value);
1876     }
1877 
1878     int stylePushFlags(NKFlags* address, NKFlags value)
1879     {
1880         return nk_style_push_flags(&ctx, address, value);
1881     }
1882 
1883     int stylePushColor(NKColor* address, NKColor value)
1884     {
1885         return nk_style_push_color(&ctx, address, value);
1886     }
1887     
1888     int stylePopFont()
1889     {
1890         return nk_style_pop_font(&ctx);
1891     }
1892 
1893     int stylePopFloat()
1894     {
1895         return nk_style_pop_float(&ctx);
1896     }
1897 
1898     int stylePopVec2()
1899     {
1900         return nk_style_pop_vec2(&ctx);
1901     }
1902 
1903     int stylePopStyleItem()
1904     {
1905         return nk_style_pop_style_item(&ctx);
1906     }
1907 
1908     int stylePopFlags()
1909     {
1910         return nk_style_pop_flags(&ctx);
1911     }
1912 
1913     int stylePopColor()
1914     {
1915         return nk_style_pop_color(&ctx);
1916     }
1917 
1918     // Primitives
1919 
1920     void strokeLine(float x0, float y0, float x1, float y1, float line_thickness, NKColor color)
1921     {
1922         if(ctx.current)
1923             nk_stroke_line(&ctx.current.buffer, x0, y0, x1, y1, line_thickness, color);
1924     }
1925 
1926     void strokeCurve(float ax, float ay, float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, float bx, float by, float line_thickness, NKColor color)
1927     {
1928         if(ctx.current)
1929             nk_stroke_curve(&ctx.current.buffer, ax, ay, ctrl0x, ctrl0y, ctrl1x, ctrl1y, bx, by, line_thickness, color);
1930     }
1931 
1932     void strokeRect(NKRect rect, float rounding, float line_thickness, NKColor color)
1933     {
1934         if(ctx.current)
1935             nk_stroke_rect(&ctx.current.buffer, rect, rounding, line_thickness, color);
1936     }
1937 
1938     void strokeCircle(NKRect rect, float line_thickness, NKColor color)
1939     {
1940         if(ctx.current)
1941             nk_stroke_circle(&ctx.current.buffer, rect, line_thickness, color);
1942     }
1943 
1944     void strokeArc(float cx, float cy, float radius, float a_min, float a_max, float line_thickness, NKColor color)
1945     {
1946         if(ctx.current)
1947             nk_stroke_arc(&ctx.current.buffer, cx, cy, radius, a_min, a_max, line_thickness, color);
1948     }
1949 
1950     void strokeTriangle(float x0, float y0, float x1, float y1, float x2, float y2, float line_thichness, NKColor color)
1951     {
1952         if(ctx.current)
1953             nk_stroke_triangle(&ctx.current.buffer, x0, y0, x1, y1, x2, y2, line_thichness, color);
1954     }
1955 
1956     void strokePolyline(float* points, int point_count, float line_thickness, NKColor color)
1957     {
1958         if(ctx.current)
1959             nk_stroke_polyline(&ctx.current.buffer, points, point_count, line_thickness, color);
1960     }
1961 
1962     void strokePolygon(float* points, int point_count, float line_thickness, NKColor color)
1963     {
1964         if(ctx.current)
1965             nk_stroke_polygon(&ctx.current.buffer, points, point_count, line_thickness, color);
1966     }
1967 
1968     void fillRect(NKRect rect, float rounding, NKColor color)
1969     {
1970         if(ctx.current)
1971             nk_fill_rect(&ctx.current.buffer, rect, rounding, color);
1972     }
1973 
1974     void fillRectMultiColor(NKRect rect, NKColor left, NKColor top, NKColor right, NKColor bottom)
1975     {
1976         if(ctx.current)
1977             nk_fill_rect_multi_color(&ctx.current.buffer, rect, left, top, right, bottom);
1978     }
1979 
1980     void fillCircle(NKRect rect, NKColor color)
1981     {
1982         if(ctx.current)
1983             nk_fill_circle(&ctx.current.buffer, rect, color);
1984     }
1985 
1986     void fillArc(float cx, float cy, float radius, float a_min, float a_max, NKColor color)
1987     {
1988         if(ctx.current)
1989             nk_fill_arc(&ctx.current.buffer, cx, cy, radius, a_min, a_max, color);
1990     }
1991 
1992     void fillTriangle(float x0, float y0, float x1, float y1, float x2, float y2, NKColor color)
1993     {
1994         if(ctx.current)
1995             nk_fill_triangle(&ctx.current.buffer, x0, y0, x1, y1, x2, y2, color);
1996     }
1997 
1998     void fillPolygon(float* points, int point_count, NKColor color)
1999     {
2000         if(ctx.current)
2001             nk_fill_polygon(&ctx.current.buffer, points, point_count, color);
2002     }
2003 
2004     void drawImage(NKRect rect, const(NKImage)* image, NKColor color)
2005     {
2006         if(ctx.current)
2007             nk_draw_image(&ctx.current.buffer, rect, image, color);
2008     }
2009 
2010     void drawText(NKRect rect, const(char)* txt, int len, const(NKFont)* font, NKColor bg, NKColor fg)
2011     {
2012         drawText(rect, txt, len, &font.handle, bg, fg);
2013     }
2014 
2015     void drawText(NKRect rect, const(char)* txt, int len, const(nk_user_font)* font, NKColor bg, NKColor fg)
2016     {
2017         if(!font)
2018             font = &atlases[0].default_font.handle;
2019         if(ctx.current)
2020             nk_draw_text(&ctx.current.buffer, rect, txt, len, font, bg, fg);
2021     }
2022 
2023     void pushScissor(NKRect rect)
2024     {
2025         if(ctx.current)
2026             nk_push_scissor(&ctx.current.buffer, rect);
2027     }
2028 
2029     // Colors
2030 
2031     NKColor rgb(int r, int g, int b)
2032     {
2033         return nk_rgb(r, g, b);
2034     }
2035 
2036     NKColor rgb(float r, float g, float b)
2037     {
2038         return nk_rgb_f(r, g, b);
2039     }
2040 
2041     NKColor rgb(char* hex)
2042     {
2043         return nk_rgb_hex(hex);
2044     }
2045 
2046     NKColor rgba(int r, int g, int b, int a)
2047     {
2048         return nk_rgba(r, g, b, a);
2049     }
2050 
2051     NKColor rgba(float r, float g, float b, float a)
2052     {
2053         return nk_rgba_f(r, g, b, a);
2054     }
2055 
2056     NKColor rgba(char* hex)
2057     {
2058         return nk_rgba_hex(hex);
2059     }
2060 
2061     NKColor hsv(int h, int s, int v)
2062     {
2063         return nk_hsv(h, s, v);
2064     }
2065 
2066     NKColor hsv(float h, float s, float v)
2067     {
2068         return nk_hsv_f(h, s, v);
2069     }
2070 
2071     NKColor hsva(int h, int s, int v, int a)
2072     {
2073         return nk_hsva(h, s, v, a);
2074     }
2075 
2076     NKColor hsva(float h, float s, float v, float a)
2077     {
2078         return nk_hsva_f(h, s, v, a);
2079     }
2080 }