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