nuklear.h (980614B)
1 /* 2 /// # Nuklear 3 /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif) 4 /// 5 /// ## Contents 6 /// 1. About section 7 /// 2. Highlights section 8 /// 3. Features section 9 /// 4. Usage section 10 /// 1. Flags section 11 /// 2. Constants section 12 /// 3. Dependencies section 13 /// 5. Example section 14 /// 6. API section 15 /// 1. Context section 16 /// 2. Input section 17 /// 3. Drawing section 18 /// 4. Window section 19 /// 5. Layouting section 20 /// 6. Groups section 21 /// 7. Tree section 22 /// 8. Properties section 23 /// 7. License section 24 /// 8. Changelog section 25 /// 9. Gallery section 26 /// 10. Credits section 27 /// 28 /// ## About 29 /// This is a minimal state immediate mode graphical user interface toolkit 30 /// written in ANSI C and licensed under public domain. It was designed as a simple 31 /// embeddable user interface for application and does not have any dependencies, 32 /// a default renderbackend or OS window and input handling but instead provides a very modular 33 /// library approach by using simple input state for input and draw 34 /// commands describing primitive shapes as output. So instead of providing a 35 /// layered library that tries to abstract over a number of platform and 36 /// render backends it only focuses on the actual UI. 37 /// 38 /// ## Highlights 39 /// - Graphical user interface toolkit 40 /// - Single header library 41 /// - Written in C89 (a.k.a. ANSI C or ISO C90) 42 /// - Small codebase (~18kLOC) 43 /// - Focus on portability, efficiency and simplicity 44 /// - No dependencies (not even the standard library if not wanted) 45 /// - Fully skinnable and customizable 46 /// - Low memory footprint with total memory control if needed or wanted 47 /// - UTF-8 support 48 /// - No global or hidden state 49 /// - Customizable library modules (you can compile and use only what you need) 50 /// - Optional font baker and vertex buffer output 51 /// 52 /// ## Features 53 /// - Absolutely no platform dependent code 54 /// - Memory management control ranging from/to 55 /// - Ease of use by allocating everything from standard library 56 /// - Control every byte of memory inside the library 57 /// - Font handling control ranging from/to 58 /// - Use your own font implementation for everything 59 /// - Use this libraries internal font baking and handling API 60 /// - Drawing output control ranging from/to 61 /// - Simple shapes for more high level APIs which already have drawing capabilities 62 /// - Hardware accessible anti-aliased vertex buffer output 63 /// - Customizable colors and properties ranging from/to 64 /// - Simple changes to color by filling a simple color table 65 /// - Complete control with ability to use skinning to decorate widgets 66 /// - Bendable UI library with widget ranging from/to 67 /// - Basic widgets like buttons, checkboxes, slider, ... 68 /// - Advanced widget like abstract comboboxes, contextual menus,... 69 /// - Compile time configuration to only compile what you need 70 /// - Subset which can be used if you do not want to link or use the standard library 71 /// - Can be easily modified to only update on user input instead of frame updates 72 /// 73 /// ## Usage 74 /// This library is self contained in one single header file and can be used either 75 /// in header only mode or in implementation mode. The header only mode is used 76 /// by default when included and allows including this header in other headers 77 /// and does not contain the actual implementation. <br /><br /> 78 /// 79 /// The implementation mode requires to define the preprocessor macro 80 /// NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.: 81 /// 82 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C 83 /// #define NK_IMPLEMENTATION 84 /// #include "nuklear.h" 85 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 86 /// 87 /// Also optionally define the symbols listed in the section "OPTIONAL DEFINES" 88 /// below in header and implementation mode if you want to use additional functionality 89 /// or need more control over the library. 90 /// 91 /// !!! WARNING 92 /// Every time nuklear is included define the same compiler flags. This very important not doing so could lead to compiler errors or even worse stack corruptions. 93 /// 94 /// ### Flags 95 /// Flag | Description 96 /// --------------------------------|------------------------------------------ 97 /// NK_PRIVATE | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation 98 /// NK_INCLUDE_FIXED_TYPES | If defined it will include header `<stdint.h>` for fixed sized types otherwise nuklear tries to select the correct type. If that fails it will throw a compiler error and you have to select the correct types yourself. 99 /// NK_INCLUDE_DEFAULT_ALLOCATOR | If defined it will include header `<stdlib.h>` and provide additional functions to use this library without caring for memory allocation control and therefore ease memory management. 100 /// NK_INCLUDE_STANDARD_IO | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading. 101 /// NK_INCLUDE_STANDARD_VARARGS | If defined it will include header <stdio.h> and provide additional functions depending on file loading. 102 /// NK_INCLUDE_VERTEX_BUFFER_OUTPUT | Defining this adds a vertex draw command list backend to this library, which allows you to convert queue commands into vertex draw commands. This is mainly if you need a hardware accessible format for OpenGL, DirectX, Vulkan, Metal,... 103 /// NK_INCLUDE_FONT_BAKING | Defining this adds `stb_truetype` and `stb_rect_pack` implementation to this library and provides font baking and rendering. If you already have font handling or do not want to use this font handler you don't have to define it. 104 /// NK_INCLUDE_DEFAULT_FONT | Defining this adds the default font: ProggyClean.ttf into this library which can be loaded into a font atlas and allows using this library without having a truetype font 105 /// NK_INCLUDE_COMMAND_USERDATA | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures. 106 /// NK_BUTTON_TRIGGER_ON_RELEASE | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released. 107 /// NK_ZERO_COMMAND_MEMORY | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame. 108 /// 109 /// !!! WARNING 110 /// The following flags will pull in the standard C library: 111 /// - NK_INCLUDE_DEFAULT_ALLOCATOR 112 /// - NK_INCLUDE_STANDARD_IO 113 /// - NK_INCLUDE_STANDARD_VARARGS 114 /// 115 /// !!! WARNING 116 /// The following flags if defined need to be defined for both header and implementation: 117 /// - NK_INCLUDE_FIXED_TYPES 118 /// - NK_INCLUDE_DEFAULT_ALLOCATOR 119 /// - NK_INCLUDE_STANDARD_VARARGS 120 /// - NK_INCLUDE_VERTEX_BUFFER_OUTPUT 121 /// - NK_INCLUDE_FONT_BAKING 122 /// - NK_INCLUDE_DEFAULT_FONT 123 /// - NK_INCLUDE_STANDARD_VARARGS 124 /// - NK_INCLUDE_COMMAND_USERDATA 125 /// 126 /// ### Constants 127 /// Define | Description 128 /// --------------------------------|--------------------------------------- 129 /// NK_BUFFER_DEFAULT_INITIAL_SIZE | Initial buffer size allocated by all buffers while using the default allocator functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't want to allocate the default 4k memory then redefine it. 130 /// NK_MAX_NUMBER_BUFFER | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient. 131 /// NK_INPUT_MAX | Defines the max number of bytes which can be added as text input in one frame. Under normal circumstances this should be more than sufficient. 132 /// 133 /// !!! WARNING 134 /// The following constants if defined need to be defined for both header and implementation: 135 /// - NK_MAX_NUMBER_BUFFER 136 /// - NK_BUFFER_DEFAULT_INITIAL_SIZE 137 /// - NK_INPUT_MAX 138 /// 139 /// ### Dependencies 140 /// Function | Description 141 /// ------------|--------------------------------------------------------------- 142 /// NK_ASSERT | If you don't define this, nuklear will use <assert.h> with assert(). 143 /// NK_MEMSET | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version. 144 /// NK_MEMCPY | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version. 145 /// NK_SQRT | You can define this to 'sqrt' or your own sqrt implementation replacement. If not nuklear will use its own slow and not highly accurate version. 146 /// NK_SIN | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation. 147 /// NK_COS | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation. 148 /// NK_STRTOD | You can define this to `strtod` or your own string to double conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!). 149 /// NK_DTOA | You can define this to `dtoa` or your own double to string conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!). 150 /// NK_VSNPRINTF| If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO` and want to be safe define this to `vsnprintf` on compilers supporting later versions of C or C++. By default nuklear will check for your stdlib version in C as well as compiler version in C++. if `vsnprintf` is available it will define it to `vsnprintf` directly. If not defined and if you have older versions of C or C++ it will be defined to `vsprintf` which is unsafe. 151 /// 152 /// !!! WARNING 153 /// The following dependencies will pull in the standard C library if not redefined: 154 /// - NK_ASSERT 155 /// 156 /// !!! WARNING 157 /// The following dependencies if defined need to be defined for both header and implementation: 158 /// - NK_ASSERT 159 /// 160 /// !!! WARNING 161 /// The following dependencies if defined need to be defined only for the implementation part: 162 /// - NK_MEMSET 163 /// - NK_MEMCPY 164 /// - NK_SQRT 165 /// - NK_SIN 166 /// - NK_COS 167 /// - NK_STRTOD 168 /// - NK_DTOA 169 /// - NK_VSNPRINTF 170 /// 171 /// ## Example 172 /// 173 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 174 /// // init gui state 175 /// enum {EASY, HARD}; 176 /// static int op = EASY; 177 /// static float value = 0.6f; 178 /// static int i = 20; 179 /// struct nk_context ctx; 180 /// 181 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font); 182 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220), 183 /// NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { 184 /// // fixed widget pixel width 185 /// nk_layout_row_static(&ctx, 30, 80, 1); 186 /// if (nk_button_label(&ctx, "button")) { 187 /// // event handling 188 /// } 189 /// 190 /// // fixed widget window ratio width 191 /// nk_layout_row_dynamic(&ctx, 30, 2); 192 /// if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY; 193 /// if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD; 194 /// 195 /// // custom widget pixel width 196 /// nk_layout_row_begin(&ctx, NK_STATIC, 30, 2); 197 /// { 198 /// nk_layout_row_push(&ctx, 50); 199 /// nk_label(&ctx, "Volume:", NK_TEXT_LEFT); 200 /// nk_layout_row_push(&ctx, 110); 201 /// nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f); 202 /// } 203 /// nk_layout_row_end(&ctx); 204 /// } 205 /// nk_end(&ctx); 206 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 207 /// 208 /// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png) 209 /// 210 /// ## API 211 /// 212 */ 213 #ifndef NK_SINGLE_FILE 214 #define NK_SINGLE_FILE 215 #endif 216 217 #ifndef NK_NUKLEAR_H_ 218 #define NK_NUKLEAR_H_ 219 220 #ifdef __cplusplus 221 extern "C" { 222 #endif 223 /* 224 * ============================================================== 225 * 226 * CONSTANTS 227 * 228 * =============================================================== 229 */ 230 #define NK_UNDEFINED (-1.0f) 231 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */ 232 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/ 233 #ifndef NK_INPUT_MAX 234 #define NK_INPUT_MAX 16 235 #endif 236 #ifndef NK_MAX_NUMBER_BUFFER 237 #define NK_MAX_NUMBER_BUFFER 64 238 #endif 239 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT 240 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f 241 #endif 242 /* 243 * ============================================================== 244 * 245 * HELPER 246 * 247 * =============================================================== 248 */ 249 #ifndef NK_API 250 #ifdef NK_PRIVATE 251 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L)) 252 #define NK_API static inline 253 #elif defined(__cplusplus) 254 #define NK_API static inline 255 #else 256 #define NK_API static 257 #endif 258 #else 259 #define NK_API extern 260 #endif 261 #endif 262 #ifndef NK_LIB 263 #ifdef NK_SINGLE_FILE 264 #define NK_LIB static 265 #else 266 #define NK_LIB extern 267 #endif 268 #endif 269 270 #define NK_INTERN static 271 #define NK_STORAGE static 272 #define NK_GLOBAL static 273 274 #define NK_FLAG(x) (1 << (x)) 275 #define NK_STRINGIFY(x) #x 276 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x) 277 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 278 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2) 279 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2) 280 281 #ifdef _MSC_VER 282 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__) 283 #else 284 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__) 285 #endif 286 287 #ifndef NK_STATIC_ASSERT 288 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1] 289 #endif 290 291 #ifndef NK_FILE_LINE 292 #ifdef _MSC_VER 293 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__) 294 #else 295 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__) 296 #endif 297 #endif 298 299 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b)) 300 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a)) 301 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i)) 302 303 #ifdef NK_INCLUDE_STANDARD_VARARGS 304 #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ 305 #include <sal.h> 306 #define NK_PRINTF_FORMAT_STRING _Printf_format_string_ 307 #else 308 #define NK_PRINTF_FORMAT_STRING 309 #endif 310 #if defined(__GNUC__) 311 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1))) 312 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0))) 313 #else 314 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) 315 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) 316 #endif 317 #include <stdarg.h> /* valist, va_start, va_end, ... */ 318 #endif 319 320 /* 321 * =============================================================== 322 * 323 * BASIC 324 * 325 * =============================================================== 326 */ 327 #ifdef NK_INCLUDE_FIXED_TYPES 328 #include <stdint.h> 329 #define NK_INT8 int8_t 330 #define NK_UINT8 uint8_t 331 #define NK_INT16 int16_t 332 #define NK_UINT16 uint16_t 333 #define NK_INT32 int32_t 334 #define NK_UINT32 uint32_t 335 #define NK_SIZE_TYPE uintptr_t 336 #define NK_POINTER_TYPE uintptr_t 337 #else 338 #ifndef NK_INT8 339 #define NK_INT8 char 340 #endif 341 #ifndef NK_UINT8 342 #define NK_UINT8 unsigned char 343 #endif 344 #ifndef NK_INT16 345 #define NK_INT16 signed short 346 #endif 347 #ifndef NK_UINT16 348 #define NK_UINT16 unsigned short 349 #endif 350 #ifndef NK_INT32 351 #if defined(_MSC_VER) 352 #define NK_INT32 __int32 353 #else 354 #define NK_INT32 signed int 355 #endif 356 #endif 357 #ifndef NK_UINT32 358 #if defined(_MSC_VER) 359 #define NK_UINT32 unsigned __int32 360 #else 361 #define NK_UINT32 unsigned int 362 #endif 363 #endif 364 #ifndef NK_SIZE_TYPE 365 #if defined(_WIN64) && defined(_MSC_VER) 366 #define NK_SIZE_TYPE unsigned __int64 367 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 368 #define NK_SIZE_TYPE unsigned __int32 369 #elif defined(__GNUC__) || defined(__clang__) 370 #if defined(__x86_64__) || defined(__ppc64__) 371 #define NK_SIZE_TYPE unsigned long 372 #else 373 #define NK_SIZE_TYPE unsigned int 374 #endif 375 #else 376 #define NK_SIZE_TYPE unsigned long 377 #endif 378 #endif 379 #ifndef NK_POINTER_TYPE 380 #if defined(_WIN64) && defined(_MSC_VER) 381 #define NK_POINTER_TYPE unsigned __int64 382 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 383 #define NK_POINTER_TYPE unsigned __int32 384 #elif defined(__GNUC__) || defined(__clang__) 385 #if defined(__x86_64__) || defined(__ppc64__) 386 #define NK_POINTER_TYPE unsigned long 387 #else 388 #define NK_POINTER_TYPE unsigned int 389 #endif 390 #else 391 #define NK_POINTER_TYPE unsigned long 392 #endif 393 #endif 394 #endif 395 396 typedef NK_INT8 nk_char; 397 typedef NK_UINT8 nk_uchar; 398 typedef NK_UINT8 nk_byte; 399 typedef NK_INT16 nk_short; 400 typedef NK_UINT16 nk_ushort; 401 typedef NK_INT32 nk_int; 402 typedef NK_UINT32 nk_uint; 403 typedef NK_SIZE_TYPE nk_size; 404 typedef NK_POINTER_TYPE nk_ptr; 405 406 typedef nk_uint nk_hash; 407 typedef nk_uint nk_flags; 408 typedef nk_uint nk_rune; 409 410 /* Make sure correct type size: 411 * This will fire with a negative subscript error if the type sizes 412 * are set incorrectly by the compiler, and compile out if not */ 413 NK_STATIC_ASSERT(sizeof(nk_short) == 2); 414 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 415 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 416 NK_STATIC_ASSERT(sizeof(nk_int) == 4); 417 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 418 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 419 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 420 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 421 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); 422 423 /* ============================================================================ 424 * 425 * API 426 * 427 * =========================================================================== */ 428 struct nk_buffer; 429 struct nk_allocator; 430 struct nk_command_buffer; 431 struct nk_draw_command; 432 struct nk_convert_config; 433 struct nk_style_item; 434 struct nk_text_edit; 435 struct nk_draw_list; 436 struct nk_user_font; 437 struct nk_panel; 438 struct nk_context; 439 struct nk_draw_vertex_layout_element; 440 struct nk_style_button; 441 struct nk_style_toggle; 442 struct nk_style_selectable; 443 struct nk_style_slide; 444 struct nk_style_progress; 445 struct nk_style_scrollbar; 446 struct nk_style_edit; 447 struct nk_style_property; 448 struct nk_style_chart; 449 struct nk_style_combo; 450 struct nk_style_tab; 451 struct nk_style_window_header; 452 struct nk_style_window; 453 454 enum {nk_false, nk_true}; 455 struct nk_color {nk_byte r,g,b,a;}; 456 struct nk_colorf {float r,g,b,a;}; 457 struct nk_vec2 {float x,y;}; 458 struct nk_vec2i {short x, y;}; 459 struct nk_rect {float x,y,w,h;}; 460 struct nk_recti {short x,y,w,h;}; 461 typedef char nk_glyph[NK_UTF_SIZE]; 462 typedef union {void *ptr; int id;} nk_handle; 463 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];}; 464 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;}; 465 struct nk_scroll {nk_uint x, y;}; 466 467 enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT}; 468 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER}; 469 enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true}; 470 enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL}; 471 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true}; 472 enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true}; 473 enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX}; 474 enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02}; 475 enum nk_color_format {NK_RGB, NK_RGBA}; 476 enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC}; 477 enum nk_layout_format {NK_DYNAMIC, NK_STATIC}; 478 enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB}; 479 480 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size); 481 typedef void (*nk_plugin_free)(nk_handle, void *old); 482 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode); 483 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*); 484 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len); 485 486 struct nk_allocator { 487 nk_handle userdata; 488 nk_plugin_alloc alloc; 489 nk_plugin_free free; 490 }; 491 enum nk_symbol_type { 492 NK_SYMBOL_NONE, 493 NK_SYMBOL_X, 494 NK_SYMBOL_UNDERSCORE, 495 NK_SYMBOL_CIRCLE_SOLID, 496 NK_SYMBOL_CIRCLE_OUTLINE, 497 NK_SYMBOL_RECT_SOLID, 498 NK_SYMBOL_RECT_OUTLINE, 499 NK_SYMBOL_TRIANGLE_UP, 500 NK_SYMBOL_TRIANGLE_DOWN, 501 NK_SYMBOL_TRIANGLE_LEFT, 502 NK_SYMBOL_TRIANGLE_RIGHT, 503 NK_SYMBOL_PLUS, 504 NK_SYMBOL_MINUS, 505 NK_SYMBOL_MAX 506 }; 507 /* ============================================================================= 508 * 509 * CONTEXT 510 * 511 * =============================================================================*/ 512 /*/// ### Context 513 /// Contexts are the main entry point and the majestro of nuklear and contain all required state. 514 /// They are used for window, memory, input, style, stack, commands and time management and need 515 /// to be passed into all nuklear GUI specific functions. 516 /// 517 /// #### Usage 518 /// To use a context it first has to be initialized which can be achieved by calling 519 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`. 520 /// Each takes in a font handle and a specific way of handling memory. Memory control 521 /// hereby ranges from standard library to just specifying a fixed sized block of memory 522 /// which nuklear has to manage itself from. 523 /// 524 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 525 /// struct nk_context ctx; 526 /// nk_init_xxx(&ctx, ...); 527 /// while (1) { 528 /// // [...] 529 /// nk_clear(&ctx); 530 /// } 531 /// nk_free(&ctx); 532 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 533 /// 534 /// #### Reference 535 /// Function | Description 536 /// --------------------|------------------------------------------------------- 537 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free) 538 /// __nk_init_fixed__ | Initializes context from single fixed size memory block 539 /// __nk_init__ | Initializes context with memory allocator callbacks for alloc and free 540 /// __nk_init_custom__ | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations 541 /// __nk_clear__ | Called at the end of the frame to reset and prepare the context for the next frame 542 /// __nk_free__ | Shutdown and free all memory allocated inside the context 543 /// __nk_set_user_data__| Utility function to pass user data to draw command 544 */ 545 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 546 /*/// #### nk_init_default 547 /// Initializes a `nk_context` struct with a default standard library allocator. 548 /// Should be used if you don't want to be bothered with memory management in nuklear. 549 /// 550 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 551 /// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font); 552 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 553 /// 554 /// Parameter | Description 555 /// ------------|--------------------------------------------------------------- 556 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 557 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 558 /// 559 /// Returns either `false(0)` on failure or `true(1)` on success. 560 /// 561 */ 562 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*); 563 #endif 564 /*/// #### nk_init_fixed 565 /// Initializes a `nk_context` struct from single fixed size memory block 566 /// Should be used if you want complete control over nuklear's memory management. 567 /// Especially recommended for system with little memory or systems with virtual memory. 568 /// For the later case you can just allocate for example 16MB of virtual memory 569 /// and only the required amount of memory will actually be committed. 570 /// 571 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 572 /// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font); 573 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 574 /// 575 /// !!! Warning 576 /// make sure the passed memory block is aligned correctly for `nk_draw_commands`. 577 /// 578 /// Parameter | Description 579 /// ------------|-------------------------------------------------------------- 580 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 581 /// __memory__ | Must point to a previously allocated memory block 582 /// __size__ | Must contain the total size of __memory__ 583 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 584 /// 585 /// Returns either `false(0)` on failure or `true(1)` on success. 586 */ 587 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*); 588 /*/// #### nk_init 589 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate 590 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation 591 /// interface to nuklear. Can be useful for cases like monitoring memory consumption. 592 /// 593 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 594 /// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font); 595 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 596 /// 597 /// Parameter | Description 598 /// ------------|--------------------------------------------------------------- 599 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 600 /// __alloc__ | Must point to a previously allocated memory allocator 601 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 602 /// 603 /// Returns either `false(0)` on failure or `true(1)` on success. 604 */ 605 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*); 606 /*/// #### nk_init_custom 607 /// Initializes a `nk_context` struct from two different either fixed or growing 608 /// buffers. The first buffer is for allocating draw commands while the second buffer is 609 /// used for allocating windows, panels and state tables. 610 /// 611 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 612 /// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font); 613 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 614 /// 615 /// Parameter | Description 616 /// ------------|--------------------------------------------------------------- 617 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 618 /// __cmds__ | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into 619 /// __pool__ | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables 620 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 621 /// 622 /// Returns either `false(0)` on failure or `true(1)` on success. 623 */ 624 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*); 625 /*/// #### nk_clear 626 /// Resets the context state at the end of the frame. This includes mostly 627 /// garbage collector tasks like removing windows or table not called and therefore 628 /// used anymore. 629 /// 630 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 631 /// void nk_clear(struct nk_context *ctx); 632 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 633 /// 634 /// Parameter | Description 635 /// ------------|----------------------------------------------------------- 636 /// __ctx__ | Must point to a previously initialized `nk_context` struct 637 */ 638 NK_API void nk_clear(struct nk_context*); 639 /*/// #### nk_free 640 /// Frees all memory allocated by nuklear. Not needed if context was 641 /// initialized with `nk_init_fixed`. 642 /// 643 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 644 /// void nk_free(struct nk_context *ctx); 645 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 646 /// 647 /// Parameter | Description 648 /// ------------|----------------------------------------------------------- 649 /// __ctx__ | Must point to a previously initialized `nk_context` struct 650 */ 651 NK_API void nk_free(struct nk_context*); 652 #ifdef NK_INCLUDE_COMMAND_USERDATA 653 /*/// #### nk_set_user_data 654 /// Sets the currently passed userdata passed down into each draw command. 655 /// 656 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 657 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data); 658 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 659 /// 660 /// Parameter | Description 661 /// ------------|-------------------------------------------------------------- 662 /// __ctx__ | Must point to a previously initialized `nk_context` struct 663 /// __data__ | Handle with either pointer or index to be passed into every draw commands 664 */ 665 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle); 666 #endif 667 /* ============================================================================= 668 * 669 * INPUT 670 * 671 * =============================================================================*/ 672 /*/// ### Input 673 /// The input API is responsible for holding the current input state composed of 674 /// mouse, key and text input states. 675 /// It is worth noting that no direct OS or window handling is done in nuklear. 676 /// Instead all input state has to be provided by platform specific code. This on one hand 677 /// expects more work from the user and complicates usage but on the other hand 678 /// provides simple abstraction over a big number of platforms, libraries and other 679 /// already provided functionality. 680 /// 681 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 682 /// nk_input_begin(&ctx); 683 /// while (GetEvent(&evt)) { 684 /// if (evt.type == MOUSE_MOVE) 685 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 686 /// else if (evt.type == [...]) { 687 /// // [...] 688 /// } 689 /// } nk_input_end(&ctx); 690 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 691 /// 692 /// #### Usage 693 /// Input state needs to be provided to nuklear by first calling `nk_input_begin` 694 /// which resets internal state like delta mouse position and button transistions. 695 /// After `nk_input_begin` all current input state needs to be provided. This includes 696 /// mouse motion, button and key pressed and released, text input and scrolling. 697 /// Both event- or state-based input handling are supported by this API 698 /// and should work without problems. Finally after all input state has been 699 /// mirrored `nk_input_end` needs to be called to finish input process. 700 /// 701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 702 /// struct nk_context ctx; 703 /// nk_init_xxx(&ctx, ...); 704 /// while (1) { 705 /// Event evt; 706 /// nk_input_begin(&ctx); 707 /// while (GetEvent(&evt)) { 708 /// if (evt.type == MOUSE_MOVE) 709 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 710 /// else if (evt.type == [...]) { 711 /// // [...] 712 /// } 713 /// } 714 /// nk_input_end(&ctx); 715 /// // [...] 716 /// nk_clear(&ctx); 717 /// } nk_free(&ctx); 718 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 719 /// 720 /// #### Reference 721 /// Function | Description 722 /// --------------------|------------------------------------------------------- 723 /// __nk_input_begin__ | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls 724 /// __nk_input_motion__ | Mirrors mouse cursor position 725 /// __nk_input_key__ | Mirrors key state with either pressed or released 726 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released 727 /// __nk_input_scroll__ | Mirrors mouse scroll values 728 /// __nk_input_char__ | Adds a single ASCII text character into an internal text buffer 729 /// __nk_input_glyph__ | Adds a single multi-byte UTF-8 character into an internal text buffer 730 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer 731 /// __nk_input_end__ | Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call 732 */ 733 enum nk_keys { 734 NK_KEY_NONE, 735 NK_KEY_SHIFT, 736 NK_KEY_CTRL, 737 NK_KEY_DEL, 738 NK_KEY_ENTER, 739 NK_KEY_TAB, 740 NK_KEY_BACKSPACE, 741 NK_KEY_COPY, 742 NK_KEY_CUT, 743 NK_KEY_PASTE, 744 NK_KEY_UP, 745 NK_KEY_DOWN, 746 NK_KEY_LEFT, 747 NK_KEY_RIGHT, 748 /* Shortcuts: text field */ 749 NK_KEY_TEXT_INSERT_MODE, 750 NK_KEY_TEXT_REPLACE_MODE, 751 NK_KEY_TEXT_RESET_MODE, 752 NK_KEY_TEXT_LINE_START, 753 NK_KEY_TEXT_LINE_END, 754 NK_KEY_TEXT_START, 755 NK_KEY_TEXT_END, 756 NK_KEY_TEXT_UNDO, 757 NK_KEY_TEXT_REDO, 758 NK_KEY_TEXT_SELECT_ALL, 759 NK_KEY_TEXT_WORD_LEFT, 760 NK_KEY_TEXT_WORD_RIGHT, 761 /* Shortcuts: scrollbar */ 762 NK_KEY_SCROLL_START, 763 NK_KEY_SCROLL_END, 764 NK_KEY_SCROLL_DOWN, 765 NK_KEY_SCROLL_UP, 766 NK_KEY_MAX 767 }; 768 enum nk_buttons { 769 NK_BUTTON_LEFT, 770 NK_BUTTON_MIDDLE, 771 NK_BUTTON_RIGHT, 772 NK_BUTTON_DOUBLE, 773 NK_BUTTON_MAX 774 }; 775 /*/// #### nk_input_begin 776 /// Begins the input mirroring process by resetting text, scroll 777 /// mouse, previous mouse position and movement as well as key state transitions, 778 /// 779 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 780 /// void nk_input_begin(struct nk_context*); 781 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 782 /// 783 /// Parameter | Description 784 /// ------------|----------------------------------------------------------- 785 /// __ctx__ | Must point to a previously initialized `nk_context` struct 786 */ 787 NK_API void nk_input_begin(struct nk_context*); 788 /*/// #### nk_input_motion 789 /// Mirrors current mouse position to nuklear 790 /// 791 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 792 /// void nk_input_motion(struct nk_context *ctx, int x, int y); 793 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 794 /// 795 /// Parameter | Description 796 /// ------------|----------------------------------------------------------- 797 /// __ctx__ | Must point to a previously initialized `nk_context` struct 798 /// __x__ | Must hold an integer describing the current mouse cursor x-position 799 /// __y__ | Must hold an integer describing the current mouse cursor y-position 800 */ 801 NK_API void nk_input_motion(struct nk_context*, int x, int y); 802 /*/// #### nk_input_key 803 /// Mirrors the state of a specific key to nuklear 804 /// 805 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 806 /// void nk_input_key(struct nk_context*, enum nk_keys key, int down); 807 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 808 /// 809 /// Parameter | Description 810 /// ------------|----------------------------------------------------------- 811 /// __ctx__ | Must point to a previously initialized `nk_context` struct 812 /// __key__ | Must be any value specified in enum `nk_keys` that needs to be mirrored 813 /// __down__ | Must be 0 for key is up and 1 for key is down 814 */ 815 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down); 816 /*/// #### nk_input_button 817 /// Mirrors the state of a specific mouse button to nuklear 818 /// 819 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 820 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, int down); 821 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 822 /// 823 /// Parameter | Description 824 /// ------------|----------------------------------------------------------- 825 /// __ctx__ | Must point to a previously initialized `nk_context` struct 826 /// __btn__ | Must be any value specified in enum `nk_buttons` that needs to be mirrored 827 /// __x__ | Must contain an integer describing mouse cursor x-position on click up/down 828 /// __y__ | Must contain an integer describing mouse cursor y-position on click up/down 829 /// __down__ | Must be 0 for key is up and 1 for key is down 830 */ 831 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down); 832 /*/// #### nk_input_scroll 833 /// Copies the last mouse scroll value to nuklear. Is generally 834 /// a scroll value. So does not have to come from mouse and could also originate 835 /// TODO finish this sentence 836 /// 837 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 838 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val); 839 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 840 /// 841 /// Parameter | Description 842 /// ------------|----------------------------------------------------------- 843 /// __ctx__ | Must point to a previously initialized `nk_context` struct 844 /// __val__ | vector with both X- as well as Y-scroll value 845 */ 846 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val); 847 /*/// #### nk_input_char 848 /// Copies a single ASCII character into an internal text buffer 849 /// This is basically a helper function to quickly push ASCII characters into 850 /// nuklear. 851 /// 852 /// !!! Note 853 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 854 /// 855 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 856 /// void nk_input_char(struct nk_context *ctx, char c); 857 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 858 /// 859 /// Parameter | Description 860 /// ------------|----------------------------------------------------------- 861 /// __ctx__ | Must point to a previously initialized `nk_context` struct 862 /// __c__ | Must be a single ASCII character preferable one that can be printed 863 */ 864 NK_API void nk_input_char(struct nk_context*, char); 865 /*/// #### nk_input_glyph 866 /// Converts an encoded unicode rune into UTF-8 and copies the result into an 867 /// internal text buffer. 868 /// 869 /// !!! Note 870 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 871 /// 872 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 873 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g); 874 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 875 /// 876 /// Parameter | Description 877 /// ------------|----------------------------------------------------------- 878 /// __ctx__ | Must point to a previously initialized `nk_context` struct 879 /// __g__ | UTF-32 unicode codepoint 880 */ 881 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph); 882 /*/// #### nk_input_unicode 883 /// Converts a unicode rune into UTF-8 and copies the result 884 /// into an internal text buffer. 885 /// !!! Note 886 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 887 /// 888 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 889 /// void nk_input_unicode(struct nk_context*, nk_rune rune); 890 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 891 /// 892 /// Parameter | Description 893 /// ------------|----------------------------------------------------------- 894 /// __ctx__ | Must point to a previously initialized `nk_context` struct 895 /// __rune__ | UTF-32 unicode codepoint 896 */ 897 NK_API void nk_input_unicode(struct nk_context*, nk_rune); 898 /*/// #### nk_input_end 899 /// End the input mirroring process by resetting mouse grabbing 900 /// state to ensure the mouse cursor is not grabbed indefinitely. 901 /// 902 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 903 /// void nk_input_end(struct nk_context *ctx); 904 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 905 /// 906 /// Parameter | Description 907 /// ------------|----------------------------------------------------------- 908 /// __ctx__ | Must point to a previously initialized `nk_context` struct 909 */ 910 NK_API void nk_input_end(struct nk_context*); 911 /* ============================================================================= 912 * 913 * DRAWING 914 * 915 * =============================================================================*/ 916 /*/// ### Drawing 917 /// This library was designed to be render backend agnostic so it does 918 /// not draw anything to screen directly. Instead all drawn shapes, widgets 919 /// are made of, are buffered into memory and make up a command queue. 920 /// Each frame therefore fills the command buffer with draw commands 921 /// that then need to be executed by the user and his own render backend. 922 /// After that the command buffer needs to be cleared and a new frame can be 923 /// started. It is probably important to note that the command buffer is the main 924 /// drawing API and the optional vertex buffer API only takes this format and 925 /// converts it into a hardware accessible format. 926 /// 927 /// #### Usage 928 /// To draw all draw commands accumulated over a frame you need your own render 929 /// backend able to draw a number of 2D primitives. This includes at least 930 /// filled and stroked rectangles, circles, text, lines, triangles and scissors. 931 /// As soon as this criterion is met you can iterate over each draw command 932 /// and execute each draw command in a interpreter like fashion: 933 /// 934 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 935 /// const struct nk_command *cmd = 0; 936 /// nk_foreach(cmd, &ctx) { 937 /// switch (cmd->type) { 938 /// case NK_COMMAND_LINE: 939 /// your_draw_line_function(...) 940 /// break; 941 /// case NK_COMMAND_RECT 942 /// your_draw_rect_function(...) 943 /// break; 944 /// case //...: 945 /// //[...] 946 /// } 947 /// } 948 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 949 /// 950 /// In program flow context draw commands need to be executed after input has been 951 /// gathered and the complete UI with windows and their contained widgets have 952 /// been executed and before calling `nk_clear` which frees all previously 953 /// allocated draw commands. 954 /// 955 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 956 /// struct nk_context ctx; 957 /// nk_init_xxx(&ctx, ...); 958 /// while (1) { 959 /// Event evt; 960 /// nk_input_begin(&ctx); 961 /// while (GetEvent(&evt)) { 962 /// if (evt.type == MOUSE_MOVE) 963 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 964 /// else if (evt.type == [...]) { 965 /// [...] 966 /// } 967 /// } 968 /// nk_input_end(&ctx); 969 /// // 970 /// // [...] 971 /// // 972 /// const struct nk_command *cmd = 0; 973 /// nk_foreach(cmd, &ctx) { 974 /// switch (cmd->type) { 975 /// case NK_COMMAND_LINE: 976 /// your_draw_line_function(...) 977 /// break; 978 /// case NK_COMMAND_RECT 979 /// your_draw_rect_function(...) 980 /// break; 981 /// case ...: 982 /// // [...] 983 /// } 984 /// nk_clear(&ctx); 985 /// } 986 /// nk_free(&ctx); 987 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 988 /// 989 /// You probably noticed that you have to draw all of the UI each frame which is 990 /// quite wasteful. While the actual UI updating loop is quite fast rendering 991 /// without actually needing it is not. So there are multiple things you could do. 992 /// 993 /// First is only update on input. This of course is only an option if your 994 /// application only depends on the UI and does not require any outside calculations. 995 /// If you actually only update on input make sure to update the UI two times each 996 /// frame and call `nk_clear` directly after the first pass and only draw in 997 /// the second pass. In addition it is recommended to also add additional timers 998 /// to make sure the UI is not drawn more than a fixed number of frames per second. 999 /// 1000 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1001 /// struct nk_context ctx; 1002 /// nk_init_xxx(&ctx, ...); 1003 /// while (1) { 1004 /// // [...wait for input ] 1005 /// // [...do two UI passes ...] 1006 /// do_ui(...) 1007 /// nk_clear(&ctx); 1008 /// do_ui(...) 1009 /// // 1010 /// // draw 1011 /// const struct nk_command *cmd = 0; 1012 /// nk_foreach(cmd, &ctx) { 1013 /// switch (cmd->type) { 1014 /// case NK_COMMAND_LINE: 1015 /// your_draw_line_function(...) 1016 /// break; 1017 /// case NK_COMMAND_RECT 1018 /// your_draw_rect_function(...) 1019 /// break; 1020 /// case ...: 1021 /// //[...] 1022 /// } 1023 /// nk_clear(&ctx); 1024 /// } 1025 /// nk_free(&ctx); 1026 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1027 /// 1028 /// The second probably more applicable trick is to only draw if anything changed. 1029 /// It is not really useful for applications with continuous draw loop but 1030 /// quite useful for desktop applications. To actually get nuklear to only 1031 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and 1032 /// allocate a memory buffer that will store each unique drawing output. 1033 /// After each frame you compare the draw command memory inside the library 1034 /// with your allocated buffer by memcmp. If memcmp detects differences 1035 /// you have to copy the command buffer into the allocated buffer 1036 /// and then draw like usual (this example uses fixed memory but you could 1037 /// use dynamically allocated memory). 1038 /// 1039 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1040 /// //[... other defines ...] 1041 /// #define NK_ZERO_COMMAND_MEMORY 1042 /// #include "nuklear.h" 1043 /// // 1044 /// // setup context 1045 /// struct nk_context ctx; 1046 /// void *last = calloc(1,64*1024); 1047 /// void *buf = calloc(1,64*1024); 1048 /// nk_init_fixed(&ctx, buf, 64*1024); 1049 /// // 1050 /// // loop 1051 /// while (1) { 1052 /// // [...input...] 1053 /// // [...ui...] 1054 /// void *cmds = nk_buffer_memory(&ctx.memory); 1055 /// if (memcmp(cmds, last, ctx.memory.allocated)) { 1056 /// memcpy(last,cmds,ctx.memory.allocated); 1057 /// const struct nk_command *cmd = 0; 1058 /// nk_foreach(cmd, &ctx) { 1059 /// switch (cmd->type) { 1060 /// case NK_COMMAND_LINE: 1061 /// your_draw_line_function(...) 1062 /// break; 1063 /// case NK_COMMAND_RECT 1064 /// your_draw_rect_function(...) 1065 /// break; 1066 /// case ...: 1067 /// // [...] 1068 /// } 1069 /// } 1070 /// } 1071 /// nk_clear(&ctx); 1072 /// } 1073 /// nk_free(&ctx); 1074 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1075 /// 1076 /// Finally while using draw commands makes sense for higher abstracted platforms like 1077 /// X11 and Win32 or drawing libraries it is often desirable to use graphics 1078 /// hardware directly. Therefore it is possible to just define 1079 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output. 1080 /// To access the vertex output you first have to convert all draw commands into 1081 /// vertexes by calling `nk_convert` which takes in your preferred vertex format. 1082 /// After successfully converting all draw commands just iterate over and execute all 1083 /// vertex draw commands: 1084 /// 1085 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1086 /// // fill configuration 1087 /// struct nk_convert_config cfg = {}; 1088 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = { 1089 /// {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)}, 1090 /// {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)}, 1091 /// {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)}, 1092 /// {NK_VERTEX_LAYOUT_END} 1093 /// }; 1094 /// cfg.shape_AA = NK_ANTI_ALIASING_ON; 1095 /// cfg.line_AA = NK_ANTI_ALIASING_ON; 1096 /// cfg.vertex_layout = vertex_layout; 1097 /// cfg.vertex_size = sizeof(struct your_vertex); 1098 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex); 1099 /// cfg.circle_segment_count = 22; 1100 /// cfg.curve_segment_count = 22; 1101 /// cfg.arc_segment_count = 22; 1102 /// cfg.global_alpha = 1.0f; 1103 /// cfg.null = dev->null; 1104 /// // 1105 /// // setup buffers and convert 1106 /// struct nk_buffer cmds, verts, idx; 1107 /// nk_buffer_init_default(&cmds); 1108 /// nk_buffer_init_default(&verts); 1109 /// nk_buffer_init_default(&idx); 1110 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg); 1111 /// // 1112 /// // draw 1113 /// nk_draw_foreach(cmd, &ctx, &cmds) { 1114 /// if (!cmd->elem_count) continue; 1115 /// //[...] 1116 /// } 1117 /// nk_buffer_free(&cms); 1118 /// nk_buffer_free(&verts); 1119 /// nk_buffer_free(&idx); 1120 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1121 /// 1122 /// #### Reference 1123 /// Function | Description 1124 /// --------------------|------------------------------------------------------- 1125 /// __nk__begin__ | Returns the first draw command in the context draw command list to be drawn 1126 /// __nk__next__ | Increments the draw command iterator to the next command inside the context draw command list 1127 /// __nk_foreach__ | Iterates over each draw command inside the context draw command list 1128 /// __nk_convert__ | Converts from the abstract draw commands list into a hardware accessible vertex format 1129 /// __nk_draw_begin__ | Returns the first vertex command in the context vertex draw list to be executed 1130 /// __nk__draw_next__ | Increments the vertex command iterator to the next command inside the context vertex command list 1131 /// __nk__draw_end__ | Returns the end of the vertex draw list 1132 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list 1133 */ 1134 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON}; 1135 enum nk_convert_result { 1136 NK_CONVERT_SUCCESS = 0, 1137 NK_CONVERT_INVALID_PARAM = 1, 1138 NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1), 1139 NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2), 1140 NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3) 1141 }; 1142 struct nk_draw_null_texture { 1143 nk_handle texture; /* texture handle to a texture with a white pixel */ 1144 struct nk_vec2 uv; /* coordinates to a white pixel in the texture */ 1145 }; 1146 struct nk_convert_config { 1147 float global_alpha; /* global alpha value */ 1148 enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */ 1149 enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */ 1150 unsigned circle_segment_count; /* number of segments used for circles: default to 22 */ 1151 unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */ 1152 unsigned curve_segment_count; /* number of segments used for curves: default to 22 */ 1153 struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */ 1154 const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ 1155 nk_size vertex_size; /* sizeof one vertex for vertex packing */ 1156 nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */ 1157 }; 1158 /*/// #### nk__begin 1159 /// Returns a draw command list iterator to iterate all draw 1160 /// commands accumulated over one frame. 1161 /// 1162 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1163 /// const struct nk_command* nk__begin(struct nk_context*); 1164 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1165 /// 1166 /// Parameter | Description 1167 /// ------------|----------------------------------------------------------- 1168 /// __ctx__ | must point to an previously initialized `nk_context` struct at the end of a frame 1169 /// 1170 /// Returns draw command pointer pointing to the first command inside the draw command list 1171 */ 1172 NK_API const struct nk_command* nk__begin(struct nk_context*); 1173 /*/// #### nk__next 1174 /// Returns draw command pointer pointing to the next command inside the draw command list 1175 /// 1176 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1177 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1178 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1179 /// 1180 /// Parameter | Description 1181 /// ------------|----------------------------------------------------------- 1182 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1183 /// __cmd__ | Must point to an previously a draw command either returned by `nk__begin` or `nk__next` 1184 /// 1185 /// Returns draw command pointer pointing to the next command inside the draw command list 1186 */ 1187 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1188 /*/// #### nk_foreach 1189 /// Iterates over each draw command inside the context draw command list 1190 /// 1191 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1192 /// #define nk_foreach(c, ctx) 1193 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1194 /// 1195 /// Parameter | Description 1196 /// ------------|----------------------------------------------------------- 1197 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1198 /// __cmd__ | Command pointer initialized to NULL 1199 /// 1200 /// Iterates over each draw command inside the context draw command list 1201 */ 1202 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c)) 1203 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 1204 /*/// #### nk_convert 1205 /// Converts all internal draw commands into vertex draw commands and fills 1206 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format 1207 /// as well as some other configuration values have to be configured by filling out a 1208 /// `nk_convert_config` struct. 1209 /// 1210 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1211 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 1212 // struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); 1213 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1214 /// 1215 /// Parameter | Description 1216 /// ------------|----------------------------------------------------------- 1217 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1218 /// __cmds__ | Must point to a previously initialized buffer to hold converted vertex draw commands 1219 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices 1220 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices 1221 /// __config__ | Must point to a filled out `nk_config` struct to configure the conversion process 1222 /// 1223 /// Returns one of enum nk_convert_result error codes 1224 /// 1225 /// Parameter | Description 1226 /// --------------------------------|----------------------------------------------------------- 1227 /// NK_CONVERT_SUCCESS | Signals a successful draw command to vertex buffer conversion 1228 /// NK_CONVERT_INVALID_PARAM | An invalid argument was passed in the function call 1229 /// NK_CONVERT_COMMAND_BUFFER_FULL | The provided buffer for storing draw commands is full or failed to allocate more memory 1230 /// NK_CONVERT_VERTEX_BUFFER_FULL | The provided buffer for storing vertices is full or failed to allocate more memory 1231 /// NK_CONVERT_ELEMENT_BUFFER_FULL | The provided buffer for storing indicies is full or failed to allocate more memory 1232 */ 1233 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); 1234 /*/// #### nk__draw_begin 1235 /// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer 1236 /// 1237 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1238 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1239 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1240 /// 1241 /// Parameter | Description 1242 /// ------------|----------------------------------------------------------- 1243 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1244 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1245 /// 1246 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer 1247 */ 1248 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1249 /*/// #### nk__draw_end 1250 /// Returns the vertex draw command at the end of the vertex draw command buffer 1251 /// 1252 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1253 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf); 1254 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1255 /// 1256 /// Parameter | Description 1257 /// ------------|----------------------------------------------------------- 1258 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1259 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1260 /// 1261 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1262 */ 1263 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*); 1264 /*/// #### nk__draw_next 1265 /// Increments the vertex draw command buffer iterator 1266 /// 1267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1268 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1269 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1270 /// 1271 /// Parameter | Description 1272 /// ------------|----------------------------------------------------------- 1273 /// __cmd__ | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command 1274 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1275 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1276 /// 1277 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1278 */ 1279 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1280 /*/// #### nk_draw_foreach 1281 /// Iterates over each vertex draw command inside a vertex draw command buffer 1282 /// 1283 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1284 /// #define nk_draw_foreach(cmd,ctx, b) 1285 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1286 /// 1287 /// Parameter | Description 1288 /// ------------|----------------------------------------------------------- 1289 /// __cmd__ | `nk_draw_command`iterator set to NULL 1290 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1291 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1292 */ 1293 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) 1294 #endif 1295 /* ============================================================================= 1296 * 1297 * WINDOW 1298 * 1299 * ============================================================================= 1300 /// ### Window 1301 /// Windows are the main persistent state used inside nuklear and are life time 1302 /// controlled by simply "retouching" (i.e. calling) each window each frame. 1303 /// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx` 1304 /// and `nk_end`. Calling any widgets outside these two functions will result in an 1305 /// assert in debug or no state change in release mode.<br /><br /> 1306 /// 1307 /// Each window holds frame persistent state like position, size, flags, state tables, 1308 /// and some garbage collected internal persistent widget state. Each window 1309 /// is linked into a window stack list which determines the drawing and overlapping 1310 /// order. The topmost window thereby is the currently active window.<br /><br /> 1311 /// 1312 /// To change window position inside the stack occurs either automatically by 1313 /// user input by being clicked on or programmatically by calling `nk_window_focus`. 1314 /// Windows by default are visible unless explicitly being defined with flag 1315 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag 1316 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling 1317 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br /> 1318 /// 1319 /// #### Usage 1320 /// To create and keep a window you have to call one of the two `nk_begin_xxx` 1321 /// functions to start window declarations and `nk_end` at the end. Furthermore it 1322 /// is recommended to check the return value of `nk_begin_xxx` and only process 1323 /// widgets inside the window if the value is not 0. Either way you have to call 1324 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to 1325 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not 1326 /// in a segmentation fault. 1327 /// 1328 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1329 /// if (nk_begin_xxx(...) { 1330 /// // [... widgets ...] 1331 /// } 1332 /// nk_end(ctx); 1333 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1334 /// 1335 /// In the grand concept window and widget declarations need to occur after input 1336 /// handling and before drawing to screen. Not doing so can result in higher 1337 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear` 1338 /// is called at the end of the frame. While nuklear's default platform backends 1339 /// already call `nk_clear` for you if you write your own backend not calling 1340 /// `nk_clear` can cause asserts or even worse undefined behavior. 1341 /// 1342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1343 /// struct nk_context ctx; 1344 /// nk_init_xxx(&ctx, ...); 1345 /// while (1) { 1346 /// Event evt; 1347 /// nk_input_begin(&ctx); 1348 /// while (GetEvent(&evt)) { 1349 /// if (evt.type == MOUSE_MOVE) 1350 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 1351 /// else if (evt.type == [...]) { 1352 /// nk_input_xxx(...); 1353 /// } 1354 /// } 1355 /// nk_input_end(&ctx); 1356 /// 1357 /// if (nk_begin_xxx(...) { 1358 /// //[...] 1359 /// } 1360 /// nk_end(ctx); 1361 /// 1362 /// const struct nk_command *cmd = 0; 1363 /// nk_foreach(cmd, &ctx) { 1364 /// case NK_COMMAND_LINE: 1365 /// your_draw_line_function(...) 1366 /// break; 1367 /// case NK_COMMAND_RECT 1368 /// your_draw_rect_function(...) 1369 /// break; 1370 /// case //...: 1371 /// //[...] 1372 /// } 1373 /// nk_clear(&ctx); 1374 /// } 1375 /// nk_free(&ctx); 1376 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1377 /// 1378 /// #### Reference 1379 /// Function | Description 1380 /// ------------------------------------|---------------------------------------- 1381 /// nk_begin | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed 1382 /// nk_begin_titled | Extended window start with separated title and identifier to allow multiple windows with same name but not title 1383 /// nk_end | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup 1384 // 1385 /// nk_window_find | Finds and returns the window with give name 1386 /// nk_window_get_bounds | Returns a rectangle with screen position and size of the currently processed window. 1387 /// nk_window_get_position | Returns the position of the currently processed window 1388 /// nk_window_get_size | Returns the size with width and height of the currently processed window 1389 /// nk_window_get_width | Returns the width of the currently processed window 1390 /// nk_window_get_height | Returns the height of the currently processed window 1391 /// nk_window_get_panel | Returns the underlying panel which contains all processing state of the current window 1392 /// nk_window_get_content_region | Returns the position and size of the currently visible and non-clipped space inside the currently processed window 1393 /// nk_window_get_content_region_min | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1394 /// nk_window_get_content_region_max | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1395 /// nk_window_get_content_region_size | Returns the size of the currently visible and non-clipped space inside the currently processed window 1396 /// nk_window_get_canvas | Returns the draw command buffer. Can be used to draw custom widgets 1397 /// nk_window_has_focus | Returns if the currently processed window is currently active 1398 /// nk_window_is_collapsed | Returns if the window with given name is currently minimized/collapsed 1399 /// nk_window_is_closed | Returns if the currently processed window was closed 1400 /// nk_window_is_hidden | Returns if the currently processed window was hidden 1401 /// nk_window_is_active | Same as nk_window_has_focus for some reason 1402 /// nk_window_is_hovered | Returns if the currently processed window is currently being hovered by mouse 1403 /// nk_window_is_any_hovered | Return if any window currently hovered 1404 /// nk_item_is_any_active | Returns if any window or widgets is currently hovered or active 1405 // 1406 /// nk_window_set_bounds | Updates position and size of the currently processed window 1407 /// nk_window_set_position | Updates position of the currently process window 1408 /// nk_window_set_size | Updates the size of the currently processed window 1409 /// nk_window_set_focus | Set the currently processed window as active window 1410 // 1411 /// nk_window_close | Closes the window with given window name which deletes the window at the end of the frame 1412 /// nk_window_collapse | Collapses the window with given window name 1413 /// nk_window_collapse_if | Collapses the window with given window name if the given condition was met 1414 /// nk_window_show | Hides a visible or reshows a hidden window 1415 /// nk_window_show_if | Hides/shows a window depending on condition 1416 */ 1417 /* 1418 /// #### nk_panel_flags 1419 /// Flag | Description 1420 /// ----------------------------|---------------------------------------- 1421 /// NK_WINDOW_BORDER | Draws a border around the window to visually separate window from the background 1422 /// NK_WINDOW_MOVABLE | The movable flag indicates that a window can be moved by user input or by dragging the window header 1423 /// NK_WINDOW_SCALABLE | The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window 1424 /// NK_WINDOW_CLOSABLE | Adds a closable icon into the header 1425 /// NK_WINDOW_MINIMIZABLE | Adds a minimize icon into the header 1426 /// NK_WINDOW_NO_SCROLLBAR | Removes the scrollbar from the window 1427 /// NK_WINDOW_TITLE | Forces a header at the top at the window showing the title 1428 /// NK_WINDOW_SCROLL_AUTO_HIDE | Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame 1429 /// NK_WINDOW_BACKGROUND | Always keep window in the background 1430 /// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-ottom corner instead right-bottom 1431 /// NK_WINDOW_NO_INPUT | Prevents window of scaling, moving or getting focus 1432 /// 1433 /// #### nk_collapse_states 1434 /// State | Description 1435 /// ----------------|----------------------------------------------------------- 1436 /// __NK_MINIMIZED__| UI section is collased and not visibile until maximized 1437 /// __NK_MAXIMIZED__| UI section is extended and visibile until minimized 1438 /// <br /><br /> 1439 */ 1440 enum nk_panel_flags { 1441 NK_WINDOW_BORDER = NK_FLAG(0), 1442 NK_WINDOW_MOVABLE = NK_FLAG(1), 1443 NK_WINDOW_SCALABLE = NK_FLAG(2), 1444 NK_WINDOW_CLOSABLE = NK_FLAG(3), 1445 NK_WINDOW_MINIMIZABLE = NK_FLAG(4), 1446 NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), 1447 NK_WINDOW_TITLE = NK_FLAG(6), 1448 NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), 1449 NK_WINDOW_BACKGROUND = NK_FLAG(8), 1450 NK_WINDOW_SCALE_LEFT = NK_FLAG(9), 1451 NK_WINDOW_NO_INPUT = NK_FLAG(10) 1452 }; 1453 /*/// #### nk_begin 1454 /// Starts a new window; needs to be called every frame for every 1455 /// window (unless hidden) or otherwise the window gets removed 1456 /// 1457 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1458 /// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1459 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1460 /// 1461 /// Parameter | Description 1462 /// ------------|----------------------------------------------------------- 1463 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1464 /// __title__ | Window title and identifier. Needs to be persistent over frames to identify the window 1465 /// __bounds__ | Initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame 1466 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1467 /// 1468 /// Returns `true(1)` if the window can be filled up with widgets from this point 1469 /// until `nk_end` or `false(0)` otherwise for example if minimized 1470 */ 1471 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1472 /*/// #### nk_begin_titled 1473 /// Extended window start with separated title and identifier to allow multiple 1474 /// windows with same title but not name 1475 /// 1476 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1477 /// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1478 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1479 /// 1480 /// Parameter | Description 1481 /// ------------|----------------------------------------------------------- 1482 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1483 /// __name__ | Window identifier. Needs to be persistent over frames to identify the window 1484 /// __title__ | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set 1485 /// __bounds__ | Initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame 1486 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1487 /// 1488 /// Returns `true(1)` if the window can be filled up with widgets from this point 1489 /// until `nk_end` or `false(0)` otherwise for example if minimized 1490 */ 1491 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1492 /*/// #### nk_end 1493 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup. 1494 /// All widget calls after this functions will result in asserts or no state changes 1495 /// 1496 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1497 /// void nk_end(struct nk_context *ctx); 1498 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1499 /// 1500 /// Parameter | Description 1501 /// ------------|----------------------------------------------------------- 1502 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1503 */ 1504 NK_API void nk_end(struct nk_context *ctx); 1505 /*/// #### nk_window_find 1506 /// Finds and returns a window from passed name 1507 /// 1508 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1509 /// void nk_end(struct nk_context *ctx); 1510 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1511 /// 1512 /// Parameter | Description 1513 /// ------------|----------------------------------------------------------- 1514 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1515 /// __name__ | Window identifier 1516 /// 1517 /// Returns a `nk_window` struct pointing to the identified window or NULL if 1518 /// no window with the given name was found 1519 */ 1520 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1521 /*/// #### nk_window_get_bounds 1522 /// Returns a rectangle with screen position and size of the currently processed window 1523 /// 1524 /// !!! WARNING 1525 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1526 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1527 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1528 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1529 /// 1530 /// Parameter | Description 1531 /// ------------|----------------------------------------------------------- 1532 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1533 /// 1534 /// Returns a `nk_rect` struct with window upper left window position and size 1535 */ 1536 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1537 /*/// #### nk_window_get_position 1538 /// Returns the position of the currently processed window. 1539 /// 1540 /// !!! WARNING 1541 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1542 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1543 /// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1544 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1545 /// 1546 /// Parameter | Description 1547 /// ------------|----------------------------------------------------------- 1548 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1549 /// 1550 /// Returns a `nk_vec2` struct with window upper left position 1551 */ 1552 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1553 /*/// #### nk_window_get_size 1554 /// Returns the size with width and height of the currently processed window. 1555 /// 1556 /// !!! WARNING 1557 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1558 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1559 /// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx); 1560 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1561 /// 1562 /// Parameter | Description 1563 /// ------------|----------------------------------------------------------- 1564 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1565 /// 1566 /// Returns a `nk_vec2` struct with window width and height 1567 */ 1568 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*); 1569 /*/// #### nk_window_get_width 1570 /// Returns the width of the currently processed window. 1571 /// 1572 /// !!! WARNING 1573 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1575 /// float nk_window_get_width(const struct nk_context *ctx); 1576 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1577 /// 1578 /// Parameter | Description 1579 /// ------------|----------------------------------------------------------- 1580 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1581 /// 1582 /// Returns the current window width 1583 */ 1584 NK_API float nk_window_get_width(const struct nk_context*); 1585 /*/// #### nk_window_get_height 1586 /// Returns the height of the currently processed window. 1587 /// 1588 /// !!! WARNING 1589 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1590 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1591 /// float nk_window_get_height(const struct nk_context *ctx); 1592 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1593 /// 1594 /// Parameter | Description 1595 /// ------------|----------------------------------------------------------- 1596 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1597 /// 1598 /// Returns the current window height 1599 */ 1600 NK_API float nk_window_get_height(const struct nk_context*); 1601 /*/// #### nk_window_get_panel 1602 /// Returns the underlying panel which contains all processing state of the current window. 1603 /// 1604 /// !!! WARNING 1605 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1606 /// !!! WARNING 1607 /// Do not keep the returned panel pointer around, it is only valid until `nk_end` 1608 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1609 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx); 1610 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1611 /// 1612 /// Parameter | Description 1613 /// ------------|----------------------------------------------------------- 1614 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1615 /// 1616 /// Returns a pointer to window internal `nk_panel` state. 1617 */ 1618 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*); 1619 /*/// #### nk_window_get_content_region 1620 /// Returns the position and size of the currently visible and non-clipped space 1621 /// inside the currently processed window. 1622 /// 1623 /// !!! WARNING 1624 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1625 /// 1626 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1627 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx); 1628 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1629 /// 1630 /// Parameter | Description 1631 /// ------------|----------------------------------------------------------- 1632 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1633 /// 1634 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset) 1635 /// of the visible space inside the current window 1636 */ 1637 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*); 1638 /*/// #### nk_window_get_content_region_min 1639 /// Returns the upper left position of the currently visible and non-clipped 1640 /// space inside the currently processed window. 1641 /// 1642 /// !!! WARNING 1643 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1644 /// 1645 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1646 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx); 1647 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1648 /// 1649 /// Parameter | Description 1650 /// ------------|----------------------------------------------------------- 1651 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1652 /// 1653 /// returns `nk_vec2` struct with upper left screen position (no scrollbar offset) 1654 /// of the visible space inside the current window 1655 */ 1656 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*); 1657 /*/// #### nk_window_get_content_region_max 1658 /// Returns the lower right screen position of the currently visible and 1659 /// non-clipped space inside the currently processed window. 1660 /// 1661 /// !!! WARNING 1662 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1663 /// 1664 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1665 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx); 1666 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1667 /// 1668 /// Parameter | Description 1669 /// ------------|----------------------------------------------------------- 1670 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1671 /// 1672 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset) 1673 /// of the visible space inside the current window 1674 */ 1675 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*); 1676 /*/// #### nk_window_get_content_region_size 1677 /// Returns the size of the currently visible and non-clipped space inside the 1678 /// currently processed window 1679 /// 1680 /// !!! WARNING 1681 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1682 /// 1683 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1684 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx); 1685 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1686 /// 1687 /// Parameter | Description 1688 /// ------------|----------------------------------------------------------- 1689 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1690 /// 1691 /// Returns `nk_vec2` struct with size the visible space inside the current window 1692 */ 1693 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); 1694 /*/// #### nk_window_get_canvas 1695 /// Returns the draw command buffer. Can be used to draw custom widgets 1696 /// !!! WARNING 1697 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1698 /// !!! WARNING 1699 /// Do not keep the returned command buffer pointer around it is only valid until `nk_end` 1700 /// 1701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1702 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx); 1703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1704 /// 1705 /// Parameter | Description 1706 /// ------------|----------------------------------------------------------- 1707 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1708 /// 1709 /// Returns a pointer to window internal `nk_command_buffer` struct used as 1710 /// drawing canvas. Can be used to do custom drawing. 1711 */ 1712 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); 1713 /*/// #### nk_window_has_focus 1714 /// Returns if the currently processed window is currently active 1715 /// !!! WARNING 1716 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1717 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1718 /// int nk_window_has_focus(const struct nk_context *ctx); 1719 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1720 /// 1721 /// Parameter | Description 1722 /// ------------|----------------------------------------------------------- 1723 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1724 /// 1725 /// Returns `false(0)` if current window is not active or `true(1)` if it is 1726 */ 1727 NK_API int nk_window_has_focus(const struct nk_context*); 1728 /*/// #### nk_window_is_hovered 1729 /// Return if the current window is being hovered 1730 /// !!! WARNING 1731 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1732 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1733 /// int nk_window_is_hovered(struct nk_context *ctx); 1734 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1735 /// 1736 /// Parameter | Description 1737 /// ------------|----------------------------------------------------------- 1738 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1739 /// 1740 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise 1741 */ 1742 NK_API int nk_window_is_hovered(struct nk_context*); 1743 /*/// #### nk_window_is_collapsed 1744 /// Returns if the window with given name is currently minimized/collapsed 1745 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1746 /// int nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1747 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1748 /// 1749 /// Parameter | Description 1750 /// ------------|----------------------------------------------------------- 1751 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1752 /// __name__ | Identifier of window you want to check if it is collapsed 1753 /// 1754 /// Returns `true(1)` if current window is minimized and `false(0)` if window not 1755 /// found or is not minimized 1756 */ 1757 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1758 /*/// #### nk_window_is_closed 1759 /// Returns if the window with given name was closed by calling `nk_close` 1760 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1761 /// int nk_window_is_closed(struct nk_context *ctx, const char *name); 1762 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1763 /// 1764 /// Parameter | Description 1765 /// ------------|----------------------------------------------------------- 1766 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1767 /// __name__ | Identifier of window you want to check if it is closed 1768 /// 1769 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed 1770 */ 1771 NK_API int nk_window_is_closed(struct nk_context*, const char*); 1772 /*/// #### nk_window_is_hidden 1773 /// Returns if the window with given name is hidden 1774 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1775 /// int nk_window_is_hidden(struct nk_context *ctx, const char *name); 1776 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1777 /// 1778 /// Parameter | Description 1779 /// ------------|----------------------------------------------------------- 1780 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1781 /// __name__ | Identifier of window you want to check if it is hidden 1782 /// 1783 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible 1784 */ 1785 NK_API int nk_window_is_hidden(struct nk_context*, const char*); 1786 /*/// #### nk_window_is_active 1787 /// Same as nk_window_has_focus for some reason 1788 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1789 /// int nk_window_is_active(struct nk_context *ctx, const char *name); 1790 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1791 /// 1792 /// Parameter | Description 1793 /// ------------|----------------------------------------------------------- 1794 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1795 /// __name__ | Identifier of window you want to check if it is active 1796 /// 1797 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active 1798 */ 1799 NK_API int nk_window_is_active(struct nk_context*, const char*); 1800 /*/// #### nk_window_is_any_hovered 1801 /// Returns if the any window is being hovered 1802 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1803 /// int nk_window_is_any_hovered(struct nk_context*); 1804 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1805 /// 1806 /// Parameter | Description 1807 /// ------------|----------------------------------------------------------- 1808 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1809 /// 1810 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise 1811 */ 1812 NK_API int nk_window_is_any_hovered(struct nk_context*); 1813 /*/// #### nk_item_is_any_active 1814 /// Returns if the any window is being hovered or any widget is currently active. 1815 /// Can be used to decide if input should be processed by UI or your specific input handling. 1816 /// Example could be UI and 3D camera to move inside a 3D space. 1817 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1818 /// int nk_item_is_any_active(struct nk_context*); 1819 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1820 /// 1821 /// Parameter | Description 1822 /// ------------|----------------------------------------------------------- 1823 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1824 /// 1825 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise 1826 */ 1827 NK_API int nk_item_is_any_active(struct nk_context*); 1828 /*/// #### nk_window_set_bounds 1829 /// Updates position and size of window with passed in name 1830 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1831 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1832 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1833 /// 1834 /// Parameter | Description 1835 /// ------------|----------------------------------------------------------- 1836 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1837 /// __name__ | Identifier of the window to modify both position and size 1838 /// __bounds__ | Must point to a `nk_rect` struct with the new position and size 1839 */ 1840 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1841 /*/// #### nk_window_set_position 1842 /// Updates position of window with passed name 1843 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1844 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1845 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1846 /// 1847 /// Parameter | Description 1848 /// ------------|----------------------------------------------------------- 1849 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1850 /// __name__ | Identifier of the window to modify both position 1851 /// __pos__ | Must point to a `nk_vec2` struct with the new position 1852 */ 1853 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1854 /*/// #### nk_window_set_size 1855 /// Updates size of window with passed in name 1856 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1857 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1858 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1859 /// 1860 /// Parameter | Description 1861 /// ------------|----------------------------------------------------------- 1862 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1863 /// __name__ | Identifier of the window to modify both window size 1864 /// __size__ | Must point to a `nk_vec2` struct with new window size 1865 */ 1866 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1867 /*/// #### nk_window_set_focus 1868 /// Sets the window with given name as active 1869 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1870 /// void nk_window_set_focus(struct nk_context*, const char *name); 1871 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1872 /// 1873 /// Parameter | Description 1874 /// ------------|----------------------------------------------------------- 1875 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1876 /// __name__ | Identifier of the window to set focus on 1877 */ 1878 NK_API void nk_window_set_focus(struct nk_context*, const char *name); 1879 /*/// #### nk_window_close 1880 /// Closes a window and marks it for being freed at the end of the frame 1881 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1882 /// void nk_window_close(struct nk_context *ctx, const char *name); 1883 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1884 /// 1885 /// Parameter | Description 1886 /// ------------|----------------------------------------------------------- 1887 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1888 /// __name__ | Identifier of the window to close 1889 */ 1890 NK_API void nk_window_close(struct nk_context *ctx, const char *name); 1891 /*/// #### nk_window_collapse 1892 /// Updates collapse state of a window with given name 1893 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1894 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1895 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1896 /// 1897 /// Parameter | Description 1898 /// ------------|----------------------------------------------------------- 1899 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1900 /// __name__ | Identifier of the window to close 1901 /// __state__ | value out of nk_collapse_states section 1902 */ 1903 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1904 /*/// #### nk_window_collapse_if 1905 /// Updates collapse state of a window with given name if given condition is met 1906 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1907 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1908 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1909 /// 1910 /// Parameter | Description 1911 /// ------------|----------------------------------------------------------- 1912 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1913 /// __name__ | Identifier of the window to either collapse or maximize 1914 /// __state__ | value out of nk_collapse_states section the window should be put into 1915 /// __cond__ | condition that has to be met to actually commit the collapse state change 1916 */ 1917 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1918 /*/// #### nk_window_show 1919 /// updates visibility state of a window with given name 1920 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1921 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1922 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1923 /// 1924 /// Parameter | Description 1925 /// ------------|----------------------------------------------------------- 1926 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1927 /// __name__ | Identifier of the window to either collapse or maximize 1928 /// __state__ | state with either visible or hidden to modify the window with 1929 */ 1930 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1931 /*/// #### nk_window_show_if 1932 /// Updates visibility state of a window with given name if a given condition is met 1933 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1934 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1935 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1936 /// 1937 /// Parameter | Description 1938 /// ------------|----------------------------------------------------------- 1939 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1940 /// __name__ | Identifier of the window to either hide or show 1941 /// __state__ | state with either visible or hidden to modify the window with 1942 /// __cond__ | condition that has to be met to actually commit the visbility state change 1943 */ 1944 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1945 /* ============================================================================= 1946 * 1947 * LAYOUT 1948 * 1949 * ============================================================================= 1950 /// ### Layouting 1951 /// Layouting in general describes placing widget inside a window with position and size. 1952 /// While in this particular implementation there are five different APIs for layouting 1953 /// each with different trade offs between control and ease of use. <br /><br /> 1954 /// 1955 /// All layouting methods in this library are based around the concept of a row. 1956 /// A row has a height the window content grows by and a number of columns and each 1957 /// layouting method specifies how each widget is placed inside the row. 1958 /// After a row has been allocated by calling a layouting functions and then 1959 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br /> 1960 /// 1961 /// To actually define a layout you just call the appropriate layouting function 1962 /// and each subsequent widget call will place the widget as specified. Important 1963 /// here is that if you define more widgets then columns defined inside the layout 1964 /// functions it will allocate the next row without you having to make another layouting <br /><br /> 1965 /// call. 1966 /// 1967 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API 1968 /// is that you have to define the row height for each. However the row height 1969 /// often depends on the height of the font. <br /><br /> 1970 /// 1971 /// To fix that internally nuklear uses a minimum row height that is set to the 1972 /// height plus padding of currently active font and overwrites the row height 1973 /// value if zero. <br /><br /> 1974 /// 1975 /// If you manually want to change the minimum row height then 1976 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to 1977 /// reset it back to be derived from font height. <br /><br /> 1978 /// 1979 /// Also if you change the font in nuklear it will automatically change the minimum 1980 /// row height for you and. This means if you change the font but still want 1981 /// a minimum row height smaller than the font you have to repush your value. <br /><br /> 1982 /// 1983 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx` 1984 /// layouting method in combination with a cassowary constraint solver (there are 1985 /// some versions on github with permissive license model) to take over all control over widget 1986 /// layouting yourself. However for quick and dirty layouting using all the other layouting 1987 /// functions should be fine. 1988 /// 1989 /// #### Usage 1990 /// 1. __nk_layout_row_dynamic__<br /><br /> 1991 /// The easiest layouting function is `nk_layout_row_dynamic`. It provides each 1992 /// widgets with same horizontal space inside the row and dynamically grows 1993 /// if the owning window grows in width. So the number of columns dictates 1994 /// the size of each widget dynamically by formula: 1995 /// 1996 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1997 /// widget_width = (window_width - padding - spacing) * (1/colum_count) 1998 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1999 /// 2000 /// Just like all other layouting APIs if you define more widget than columns this 2001 /// library will allocate a new row and keep all layouting parameters previously 2002 /// defined. 2003 /// 2004 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2005 /// if (nk_begin_xxx(...) { 2006 /// // first row with height: 30 composed of two widgets 2007 /// nk_layout_row_dynamic(&ctx, 30, 2); 2008 /// nk_widget(...); 2009 /// nk_widget(...); 2010 /// // 2011 /// // second row with same parameter as defined above 2012 /// nk_widget(...); 2013 /// nk_widget(...); 2014 /// // 2015 /// // third row uses 0 for height which will use auto layouting 2016 /// nk_layout_row_dynamic(&ctx, 0, 2); 2017 /// nk_widget(...); 2018 /// nk_widget(...); 2019 /// } 2020 /// nk_end(...); 2021 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2022 /// 2023 /// 2. __nk_layout_row_static__<br /><br /> 2024 /// Another easy layouting function is `nk_layout_row_static`. It provides each 2025 /// widget with same horizontal pixel width inside the row and does not grow 2026 /// if the owning window scales smaller or bigger. 2027 /// 2028 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2029 /// if (nk_begin_xxx(...) { 2030 /// // first row with height: 30 composed of two widgets with width: 80 2031 /// nk_layout_row_static(&ctx, 30, 80, 2); 2032 /// nk_widget(...); 2033 /// nk_widget(...); 2034 /// // 2035 /// // second row with same parameter as defined above 2036 /// nk_widget(...); 2037 /// nk_widget(...); 2038 /// // 2039 /// // third row uses 0 for height which will use auto layouting 2040 /// nk_layout_row_static(&ctx, 0, 80, 2); 2041 /// nk_widget(...); 2042 /// nk_widget(...); 2043 /// } 2044 /// nk_end(...); 2045 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2046 /// 2047 /// 3. __nk_layout_row_xxx__<br /><br /> 2048 /// A little bit more advanced layouting API are functions `nk_layout_row_begin`, 2049 /// `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly 2050 /// specify each column pixel or window ratio in a row. It supports either 2051 /// directly setting per column pixel width or widget window ratio but not 2052 /// both. Furthermore it is a immediate mode API so each value is directly 2053 /// pushed before calling a widget. Therefore the layout is not automatically 2054 /// repeating like the last two layouting functions. 2055 /// 2056 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2057 /// if (nk_begin_xxx(...) { 2058 /// // first row with height: 25 composed of two widgets with width 60 and 40 2059 /// nk_layout_row_begin(ctx, NK_STATIC, 25, 2); 2060 /// nk_layout_row_push(ctx, 60); 2061 /// nk_widget(...); 2062 /// nk_layout_row_push(ctx, 40); 2063 /// nk_widget(...); 2064 /// nk_layout_row_end(ctx); 2065 /// // 2066 /// // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75 2067 /// nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2); 2068 /// nk_layout_row_push(ctx, 0.25f); 2069 /// nk_widget(...); 2070 /// nk_layout_row_push(ctx, 0.75f); 2071 /// nk_widget(...); 2072 /// nk_layout_row_end(ctx); 2073 /// // 2074 /// // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75 2075 /// nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2); 2076 /// nk_layout_row_push(ctx, 0.25f); 2077 /// nk_widget(...); 2078 /// nk_layout_row_push(ctx, 0.75f); 2079 /// nk_widget(...); 2080 /// nk_layout_row_end(ctx); 2081 /// } 2082 /// nk_end(...); 2083 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2084 /// 2085 /// 4. __nk_layout_row__<br /><br /> 2086 /// The array counterpart to API nk_layout_row_xxx is the single nk_layout_row 2087 /// functions. Instead of pushing either pixel or window ratio for every widget 2088 /// it allows to define it by array. The trade of for less control is that 2089 /// `nk_layout_row` is automatically repeating. Otherwise the behavior is the 2090 /// same. 2091 /// 2092 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2093 /// if (nk_begin_xxx(...) { 2094 /// // two rows with height: 30 composed of two widgets with width 60 and 40 2095 /// const float size[] = {60,40}; 2096 /// nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); 2097 /// nk_widget(...); 2098 /// nk_widget(...); 2099 /// nk_widget(...); 2100 /// nk_widget(...); 2101 /// // 2102 /// // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75 2103 /// const float ratio[] = {0.25, 0.75}; 2104 /// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2105 /// nk_widget(...); 2106 /// nk_widget(...); 2107 /// nk_widget(...); 2108 /// nk_widget(...); 2109 /// // 2110 /// // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75 2111 /// const float ratio[] = {0.25, 0.75}; 2112 /// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2113 /// nk_widget(...); 2114 /// nk_widget(...); 2115 /// nk_widget(...); 2116 /// nk_widget(...); 2117 /// } 2118 /// nk_end(...); 2119 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2120 /// 2121 /// 5. __nk_layout_row_template_xxx__<br /><br /> 2122 /// The most complex and second most flexible API is a simplified flexbox version without 2123 /// line wrapping and weights for dynamic widgets. It is an immediate mode API but 2124 /// unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called 2125 /// before calling the templated widgets. 2126 /// The row template layout has three different per widget size specifier. The first 2127 /// one is the `nk_layout_row_template_push_static` with fixed widget pixel width. 2128 /// They do not grow if the row grows and will always stay the same. 2129 /// The second size specifier is `nk_layout_row_template_push_variable` 2130 /// which defines a minimum widget size but it also can grow if more space is available 2131 /// not taken by other widgets. 2132 /// Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic` 2133 /// which are completely flexible and unlike variable widgets can even shrink 2134 /// to zero if not enough space is provided. 2135 /// 2136 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2137 /// if (nk_begin_xxx(...) { 2138 /// // two rows with height: 30 composed of three widgets 2139 /// nk_layout_row_template_begin(ctx, 30); 2140 /// nk_layout_row_template_push_dynamic(ctx); 2141 /// nk_layout_row_template_push_variable(ctx, 80); 2142 /// nk_layout_row_template_push_static(ctx, 80); 2143 /// nk_layout_row_template_end(ctx); 2144 /// // 2145 /// // first row 2146 /// nk_widget(...); // dynamic widget can go to zero if not enough space 2147 /// nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space 2148 /// nk_widget(...); // static widget with fixed 80 pixel width 2149 /// // 2150 /// // second row same layout 2151 /// nk_widget(...); 2152 /// nk_widget(...); 2153 /// nk_widget(...); 2154 /// } 2155 /// nk_end(...); 2156 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2157 /// 2158 /// 6. __nk_layout_space_xxx__<br /><br /> 2159 /// Finally the most flexible API directly allows you to place widgets inside the 2160 /// window. The space layout API is an immediate mode API which does not support 2161 /// row auto repeat and directly sets position and size of a widget. Position 2162 /// and size hereby can be either specified as ratio of allocated space or 2163 /// allocated space local position and pixel size. Since this API is quite 2164 /// powerful there are a number of utility functions to get the available space 2165 /// and convert between local allocated space and screen space. 2166 /// 2167 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2168 /// if (nk_begin_xxx(...) { 2169 /// // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2170 /// nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX); 2171 /// nk_layout_space_push(ctx, nk_rect(0,0,150,200)); 2172 /// nk_widget(...); 2173 /// nk_layout_space_push(ctx, nk_rect(200,200,100,200)); 2174 /// nk_widget(...); 2175 /// nk_layout_space_end(ctx); 2176 /// // 2177 /// // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2178 /// nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX); 2179 /// nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1)); 2180 /// nk_widget(...); 2181 /// nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1)); 2182 /// nk_widget(...); 2183 /// } 2184 /// nk_end(...); 2185 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2186 /// 2187 /// #### Reference 2188 /// Function | Description 2189 /// ----------------------------------------|------------------------------------ 2190 /// nk_layout_set_min_row_height | Set the currently used minimum row height to a specified value 2191 /// nk_layout_reset_min_row_height | Resets the currently used minimum row height to font height 2192 /// nk_layout_widget_bounds | Calculates current width a static layout row can fit inside a window 2193 /// nk_layout_ratio_from_pixel | Utility functions to calculate window ratio from pixel size 2194 // 2195 /// nk_layout_row_dynamic | Current layout is divided into n same sized growing columns 2196 /// nk_layout_row_static | Current layout is divided into n same fixed sized columns 2197 /// nk_layout_row_begin | Starts a new row with given height and number of columns 2198 /// nk_layout_row_push | Pushes another column with given size or window ratio 2199 /// nk_layout_row_end | Finished previously started row 2200 /// nk_layout_row | Specifies row columns in array as either window ratio or size 2201 // 2202 /// nk_layout_row_template_begin | Begins the row template declaration 2203 /// nk_layout_row_template_push_dynamic | Adds a dynamic column that dynamically grows and can go to zero if not enough space 2204 /// nk_layout_row_template_push_variable | Adds a variable column that dynamically grows but does not shrink below specified pixel width 2205 /// nk_layout_row_template_push_static | Adds a static column that does not grow and will always have the same size 2206 /// nk_layout_row_template_end | Marks the end of the row template 2207 // 2208 /// nk_layout_space_begin | Begins a new layouting space that allows to specify each widgets position and size 2209 /// nk_layout_space_push | Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2210 /// nk_layout_space_end | Marks the end of the layouting space 2211 // 2212 /// nk_layout_space_bounds | Callable after nk_layout_space_begin and returns total space allocated 2213 /// nk_layout_space_to_screen | Converts vector from nk_layout_space coordinate space into screen space 2214 /// nk_layout_space_to_local | Converts vector from screen space into nk_layout_space coordinates 2215 /// nk_layout_space_rect_to_screen | Converts rectangle from nk_layout_space coordinate space into screen space 2216 /// nk_layout_space_rect_to_local | Converts rectangle from screen space into nk_layout_space coordinates 2217 */ 2218 /*/// #### nk_layout_set_min_row_height 2219 /// Sets the currently used minimum row height. 2220 /// !!! WARNING 2221 /// The passed height needs to include both your preferred row height 2222 /// as well as padding. No internal padding is added. 2223 /// 2224 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2225 /// void nk_layout_set_min_row_height(struct nk_context*, float height); 2226 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2227 /// 2228 /// Parameter | Description 2229 /// ------------|----------------------------------------------------------- 2230 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2231 /// __height__ | New minimum row height to be used for auto generating the row height 2232 */ 2233 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height); 2234 /*/// #### nk_layout_reset_min_row_height 2235 /// Reset the currently used minimum row height back to `font_height + text_padding + padding` 2236 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2237 /// void nk_layout_reset_min_row_height(struct nk_context*); 2238 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2239 /// 2240 /// Parameter | Description 2241 /// ------------|----------------------------------------------------------- 2242 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2243 */ 2244 NK_API void nk_layout_reset_min_row_height(struct nk_context*); 2245 /*/// #### nk_layout_widget_bounds 2246 /// Returns the width of the next row allocate by one of the layouting functions 2247 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2248 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2249 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2250 /// 2251 /// Parameter | Description 2252 /// ------------|----------------------------------------------------------- 2253 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2254 /// 2255 /// Return `nk_rect` with both position and size of the next row 2256 */ 2257 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2258 /*/// #### nk_layout_ratio_from_pixel 2259 /// Utility functions to calculate window ratio from pixel size 2260 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2261 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2262 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2263 /// 2264 /// Parameter | Description 2265 /// ------------|----------------------------------------------------------- 2266 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2267 /// __pixel__ | Pixel_width to convert to window ratio 2268 /// 2269 /// Returns `nk_rect` with both position and size of the next row 2270 */ 2271 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2272 /*/// #### nk_layout_row_dynamic 2273 /// Sets current row layout to share horizontal space 2274 /// between @cols number of widgets evenly. Once called all subsequent widget 2275 /// calls greater than @cols will allocate a new row with same layout. 2276 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2277 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2278 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2279 /// 2280 /// Parameter | Description 2281 /// ------------|----------------------------------------------------------- 2282 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2283 /// __height__ | Holds height of each widget in row or zero for auto layouting 2284 /// __columns__ | Number of widget inside row 2285 */ 2286 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2287 /*/// #### nk_layout_row_static 2288 /// Sets current row layout to fill @cols number of widgets 2289 /// in row with same @item_width horizontal size. Once called all subsequent widget 2290 /// calls greater than @cols will allocate a new row with same layout. 2291 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2292 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2293 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2294 /// 2295 /// Parameter | Description 2296 /// ------------|----------------------------------------------------------- 2297 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2298 /// __height__ | Holds height of each widget in row or zero for auto layouting 2299 /// __width__ | Holds pixel width of each widget in the row 2300 /// __columns__ | Number of widget inside row 2301 */ 2302 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2303 /*/// #### nk_layout_row_begin 2304 /// Starts a new dynamic or fixed row with given height and columns. 2305 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2306 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2307 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2308 /// 2309 /// Parameter | Description 2310 /// ------------|----------------------------------------------------------- 2311 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2312 /// __fmt__ | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2313 /// __height__ | holds height of each widget in row or zero for auto layouting 2314 /// __columns__ | Number of widget inside row 2315 */ 2316 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2317 /*/// #### nk_layout_row_push 2318 /// Specifies either window ratio or width of a single column 2319 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2320 /// void nk_layout_row_push(struct nk_context*, float value); 2321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2322 /// 2323 /// Parameter | Description 2324 /// ------------|----------------------------------------------------------- 2325 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2326 /// __value__ | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call 2327 */ 2328 NK_API void nk_layout_row_push(struct nk_context*, float value); 2329 /*/// #### nk_layout_row_end 2330 /// Finished previously started row 2331 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2332 /// void nk_layout_row_end(struct nk_context*); 2333 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2334 /// 2335 /// Parameter | Description 2336 /// ------------|----------------------------------------------------------- 2337 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2338 */ 2339 NK_API void nk_layout_row_end(struct nk_context*); 2340 /*/// #### nk_layout_row 2341 /// Specifies row columns in array as either window ratio or size 2342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2343 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2344 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2345 /// 2346 /// Parameter | Description 2347 /// ------------|----------------------------------------------------------- 2348 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2349 /// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2350 /// __height__ | Holds height of each widget in row or zero for auto layouting 2351 /// __columns__ | Number of widget inside row 2352 */ 2353 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2354 /*/// #### nk_layout_row_template_begin 2355 /// Begins the row template declaration 2356 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2357 /// void nk_layout_row_template_begin(struct nk_context*, float row_height); 2358 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2359 /// 2360 /// Parameter | Description 2361 /// ------------|----------------------------------------------------------- 2362 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2363 /// __height__ | Holds height of each widget in row or zero for auto layouting 2364 */ 2365 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height); 2366 /*/// #### nk_layout_row_template_push_dynamic 2367 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space 2368 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2369 /// void nk_layout_row_template_push_dynamic(struct nk_context*); 2370 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2371 /// 2372 /// Parameter | Description 2373 /// ------------|----------------------------------------------------------- 2374 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2375 /// __height__ | Holds height of each widget in row or zero for auto layouting 2376 */ 2377 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*); 2378 /*/// #### nk_layout_row_template_push_variable 2379 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width 2380 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2381 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2382 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2383 /// 2384 /// Parameter | Description 2385 /// ------------|----------------------------------------------------------- 2386 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2387 /// __width__ | Holds the minimum pixel width the next column must always be 2388 */ 2389 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2390 /*/// #### nk_layout_row_template_push_static 2391 /// Adds a static column that does not grow and will always have the same size 2392 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2393 /// void nk_layout_row_template_push_static(struct nk_context*, float width); 2394 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2395 /// 2396 /// Parameter | Description 2397 /// ------------|----------------------------------------------------------- 2398 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2399 /// __width__ | Holds the absolute pixel width value the next column must be 2400 */ 2401 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width); 2402 /*/// #### nk_layout_row_template_end 2403 /// Marks the end of the row template 2404 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2405 /// void nk_layout_row_template_end(struct nk_context*); 2406 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2407 /// 2408 /// Parameter | Description 2409 /// ------------|----------------------------------------------------------- 2410 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2411 */ 2412 NK_API void nk_layout_row_template_end(struct nk_context*); 2413 /*/// #### nk_layout_space_begin 2414 /// Begins a new layouting space that allows to specify each widgets position and size. 2415 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2416 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2417 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2418 /// 2419 /// Parameter | Description 2420 /// ------------|----------------------------------------------------------- 2421 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2422 /// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2423 /// __height__ | Holds height of each widget in row or zero for auto layouting 2424 /// __columns__ | Number of widgets inside row 2425 */ 2426 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2427 /*/// #### nk_layout_space_push 2428 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2429 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2430 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds); 2431 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2432 /// 2433 /// Parameter | Description 2434 /// ------------|----------------------------------------------------------- 2435 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2436 /// __bounds__ | Position and size in laoyut space local coordinates 2437 */ 2438 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds); 2439 /*/// #### nk_layout_space_end 2440 /// Marks the end of the layout space 2441 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2442 /// void nk_layout_space_end(struct nk_context*); 2443 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2444 /// 2445 /// Parameter | Description 2446 /// ------------|----------------------------------------------------------- 2447 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2448 */ 2449 NK_API void nk_layout_space_end(struct nk_context*); 2450 /*/// #### nk_layout_space_bounds 2451 /// Utility function to calculate total space allocated for `nk_layout_space` 2452 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2453 /// struct nk_rect nk_layout_space_bounds(struct nk_context*); 2454 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2455 /// 2456 /// Parameter | Description 2457 /// ------------|----------------------------------------------------------- 2458 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2459 /// 2460 /// Returns `nk_rect` holding the total space allocated 2461 */ 2462 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*); 2463 /*/// #### nk_layout_space_to_screen 2464 /// Converts vector from nk_layout_space coordinate space into screen space 2465 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2466 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2467 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2468 /// 2469 /// Parameter | Description 2470 /// ------------|----------------------------------------------------------- 2471 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2472 /// __vec__ | Position to convert from layout space into screen coordinate space 2473 /// 2474 /// Returns transformed `nk_vec2` in screen space coordinates 2475 */ 2476 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2477 /*/// #### nk_layout_space_to_local 2478 /// Converts vector from layout space into screen space 2479 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2480 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2481 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2482 /// 2483 /// Parameter | Description 2484 /// ------------|----------------------------------------------------------- 2485 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2486 /// __vec__ | Position to convert from screen space into layout coordinate space 2487 /// 2488 /// Returns transformed `nk_vec2` in layout space coordinates 2489 */ 2490 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2491 /*/// #### nk_layout_space_rect_to_screen 2492 /// Converts rectangle from screen space into layout space 2493 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2494 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2495 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2496 /// 2497 /// Parameter | Description 2498 /// ------------|----------------------------------------------------------- 2499 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2500 /// __bounds__ | Rectangle to convert from layout space into screen space 2501 /// 2502 /// Returns transformed `nk_rect` in screen space coordinates 2503 */ 2504 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2505 /*/// #### nk_layout_space_rect_to_local 2506 /// Converts rectangle from layout space into screen space 2507 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2508 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2509 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2510 /// 2511 /// Parameter | Description 2512 /// ------------|----------------------------------------------------------- 2513 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2514 /// __bounds__ | Rectangle to convert from layout space into screen space 2515 /// 2516 /// Returns transformed `nk_rect` in layout space coordinates 2517 */ 2518 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2519 /* ============================================================================= 2520 * 2521 * GROUP 2522 * 2523 * ============================================================================= 2524 /// ### Groups 2525 /// Groups are basically windows inside windows. They allow to subdivide space 2526 /// in a window to layout widgets as a group. Almost all more complex widget 2527 /// layouting requirements can be solved using groups and basic layouting 2528 /// fuctionality. Groups just like windows are identified by an unique name and 2529 /// internally keep track of scrollbar offsets by default. However additional 2530 /// versions are provided to directly manage the scrollbar. 2531 /// 2532 /// #### Usage 2533 /// To create a group you have to call one of the three `nk_group_begin_xxx` 2534 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it 2535 /// is required to check the return value of `nk_group_begin_xxx` and only process 2536 /// widgets inside the window if the value is not 0. 2537 /// Nesting groups is possible and even encouraged since many layouting schemes 2538 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end` 2539 /// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0: 2540 /// 2541 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2542 /// if (nk_group_begin_xxx(ctx, ...) { 2543 /// // [... widgets ...] 2544 /// nk_group_end(ctx); 2545 /// } 2546 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2547 /// 2548 /// In the grand concept groups can be called after starting a window 2549 /// with `nk_begin_xxx` and before calling `nk_end`: 2550 /// 2551 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2552 /// struct nk_context ctx; 2553 /// nk_init_xxx(&ctx, ...); 2554 /// while (1) { 2555 /// // Input 2556 /// Event evt; 2557 /// nk_input_begin(&ctx); 2558 /// while (GetEvent(&evt)) { 2559 /// if (evt.type == MOUSE_MOVE) 2560 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 2561 /// else if (evt.type == [...]) { 2562 /// nk_input_xxx(...); 2563 /// } 2564 /// } 2565 /// nk_input_end(&ctx); 2566 /// // 2567 /// // Window 2568 /// if (nk_begin_xxx(...) { 2569 /// // [...widgets...] 2570 /// nk_layout_row_dynamic(...); 2571 /// if (nk_group_begin_xxx(ctx, ...) { 2572 /// //[... widgets ...] 2573 /// nk_group_end(ctx); 2574 /// } 2575 /// } 2576 /// nk_end(ctx); 2577 /// // 2578 /// // Draw 2579 /// const struct nk_command *cmd = 0; 2580 /// nk_foreach(cmd, &ctx) { 2581 /// switch (cmd->type) { 2582 /// case NK_COMMAND_LINE: 2583 /// your_draw_line_function(...) 2584 /// break; 2585 /// case NK_COMMAND_RECT 2586 /// your_draw_rect_function(...) 2587 /// break; 2588 /// case ...: 2589 /// // [...] 2590 /// } 2591 // nk_clear(&ctx); 2592 /// } 2593 /// nk_free(&ctx); 2594 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2595 /// #### Reference 2596 /// Function | Description 2597 /// --------------------------------|------------------------------------------- 2598 /// nk_group_begin | Start a new group with internal scrollbar handling 2599 /// nk_group_begin_titled | Start a new group with separeted name and title and internal scrollbar handling 2600 /// nk_group_end | Ends a group. Should only be called if nk_group_begin returned non-zero 2601 /// nk_group_scrolled_offset_begin | Start a new group with manual separated handling of scrollbar x- and y-offset 2602 /// nk_group_scrolled_begin | Start a new group with manual scrollbar handling 2603 /// nk_group_scrolled_end | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero 2604 */ 2605 /*/// #### nk_group_begin 2606 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2607 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2608 /// int nk_group_begin(struct nk_context*, const char *title, nk_flags); 2609 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2610 /// 2611 /// Parameter | Description 2612 /// ------------|----------------------------------------------------------- 2613 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2614 /// __title__ | Must be an unique identifier for this group that is also used for the group header 2615 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2616 /// 2617 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2618 */ 2619 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags); 2620 /*/// #### nk_group_begin_titled 2621 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2622 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2623 /// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2624 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2625 /// 2626 /// Parameter | Description 2627 /// ------------|----------------------------------------------------------- 2628 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2629 /// __id__ | Must be an unique identifier for this group 2630 /// __title__ | Group header title 2631 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2632 /// 2633 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2634 */ 2635 NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2636 /*/// #### nk_group_end 2637 /// Ends a widget group 2638 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2639 /// void nk_group_end(struct nk_context*); 2640 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2641 /// 2642 /// Parameter | Description 2643 /// ------------|----------------------------------------------------------- 2644 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2645 */ 2646 NK_API void nk_group_end(struct nk_context*); 2647 /*/// #### nk_group_scrolled_offset_begin 2648 /// starts a new widget group. requires a previous layouting function to specify 2649 /// a size. Does not keep track of scrollbar. 2650 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2651 /// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2653 /// 2654 /// Parameter | Description 2655 /// ------------|----------------------------------------------------------- 2656 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2657 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally. 2658 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically 2659 /// __title__ | Window unique group title used to both identify and display in the group header 2660 /// __flags__ | Window flags from the nk_panel_flags section 2661 /// 2662 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2663 */ 2664 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2665 /*/// #### nk_group_scrolled_begin 2666 /// Starts a new widget group. requires a previous 2667 /// layouting function to specify a size. Does not keep track of scrollbar. 2668 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2669 /// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2670 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2671 /// 2672 /// Parameter | Description 2673 /// ------------|----------------------------------------------------------- 2674 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2675 /// __off__ | Both x- and y- scroll offset. Allows for manual scrollbar control 2676 /// __title__ | Window unique group title used to both identify and display in the group header 2677 /// __flags__ | Window flags from nk_panel_flags section 2678 /// 2679 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2680 */ 2681 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2682 /*/// #### nk_group_scrolled_end 2683 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin. 2684 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2685 /// void nk_group_scrolled_end(struct nk_context*); 2686 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2687 /// 2688 /// Parameter | Description 2689 /// ------------|----------------------------------------------------------- 2690 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2691 */ 2692 NK_API void nk_group_scrolled_end(struct nk_context*); 2693 /* ============================================================================= 2694 * 2695 * TREE 2696 * 2697 * ============================================================================= 2698 /// ### Tree 2699 /// Trees represent two different concept. First the concept of a collapsable 2700 /// UI section that can be either in a hidden or visibile state. They allow the UI 2701 /// user to selectively minimize the current set of visible UI to comprehend. 2702 /// The second concept are tree widgets for visual UI representation of trees.<br /><br /> 2703 /// 2704 /// Trees thereby can be nested for tree representations and multiple nested 2705 /// collapsable UI sections. All trees are started by calling of the 2706 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the 2707 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label 2708 /// and optionally an image to be displayed and the initial collapse state from 2709 /// the nk_collapse_states section.<br /><br /> 2710 /// 2711 /// The runtime state of the tree is either stored outside the library by the caller 2712 /// or inside which requires a unique ID. The unique ID can either be generated 2713 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`, 2714 /// by `__FILE__` and a user provided ID generated for example by loop index with 2715 /// function `nk_tree_push_id` or completely provided from outside by user with 2716 /// function `nk_tree_push_hashed`. 2717 /// 2718 /// #### Usage 2719 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx` 2720 /// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the 2721 /// end. 2722 /// Each starting function will either return `false(0)` if the tree is collapsed 2723 /// or hidden and therefore does not need to be filled with content or `true(1)` 2724 /// if visible and required to be filled. 2725 /// 2726 /// !!! Note 2727 /// The tree header does not require and layouting function and instead 2728 /// calculates a auto height based on the currently used font size 2729 /// 2730 /// The tree ending functions only need to be called if the tree content is 2731 /// actually visible. So make sure the tree push function is guarded by `if` 2732 /// and the pop call is only taken if the tree is visible. 2733 /// 2734 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2735 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) { 2736 /// nk_layout_row_dynamic(...); 2737 /// nk_widget(...); 2738 /// nk_tree_pop(ctx); 2739 /// } 2740 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2741 /// 2742 /// #### Reference 2743 /// Function | Description 2744 /// ----------------------------|------------------------------------------- 2745 /// nk_tree_push | Start a collapsable UI section with internal state management 2746 /// nk_tree_push_id | Start a collapsable UI section with internal state management callable in a look 2747 /// nk_tree_push_hashed | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state 2748 /// nk_tree_image_push | Start a collapsable UI section with image and label header 2749 /// nk_tree_image_push_id | Start a collapsable UI section with image and label header and internal state management callable in a look 2750 /// nk_tree_image_push_hashed | Start a collapsable UI section with image and label header and internal state management with full control over internal unique ID use to store state 2751 /// nk_tree_pop | Ends a collapsable UI section 2752 // 2753 /// nk_tree_state_push | Start a collapsable UI section with external state management 2754 /// nk_tree_state_image_push | Start a collapsable UI section with image and label header and external state management 2755 /// nk_tree_state_pop | Ends a collapsabale UI section 2756 /// 2757 /// #### nk_tree_type 2758 /// Flag | Description 2759 /// ----------------|---------------------------------------- 2760 /// NK_TREE_NODE | Highlighted tree header to mark a collapsable UI section 2761 /// NK_TREE_TAB | Non-highighted tree header closer to tree representations 2762 */ 2763 /*/// #### nk_tree_push 2764 /// Starts a collapsable UI section with internal state management 2765 /// !!! WARNING 2766 /// To keep track of the runtime tree collapsable state this function uses 2767 /// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2768 /// to call this function in a loop please use `nk_tree_push_id` or 2769 /// `nk_tree_push_hashed` instead. 2770 /// 2771 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2772 /// #define nk_tree_push(ctx, type, title, state) 2773 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2774 /// 2775 /// Parameter | Description 2776 /// ------------|----------------------------------------------------------- 2777 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2778 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2779 /// __title__ | Label printed in the tree header 2780 /// __state__ | Initial tree state value out of nk_collapse_states 2781 /// 2782 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2783 */ 2784 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__) 2785 /*/// #### nk_tree_push_id 2786 /// Starts a collapsable UI section with internal state management callable in a look 2787 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2788 /// #define nk_tree_push_id(ctx, type, title, state, id) 2789 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2790 /// 2791 /// Parameter | Description 2792 /// ------------|----------------------------------------------------------- 2793 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2794 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2795 /// __title__ | Label printed in the tree header 2796 /// __state__ | Initial tree state value out of nk_collapse_states 2797 /// __id__ | Loop counter index if this function is called in a loop 2798 /// 2799 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2800 */ 2801 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id) 2802 /*/// #### nk_tree_push_hashed 2803 /// Start a collapsable UI section with internal state management with full 2804 /// control over internal unique ID used to store state 2805 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2806 /// int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2807 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2808 /// 2809 /// Parameter | Description 2810 /// ------------|----------------------------------------------------------- 2811 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2812 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2813 /// __title__ | Label printed in the tree header 2814 /// __state__ | Initial tree state value out of nk_collapse_states 2815 /// __hash__ | Memory block or string to generate the ID from 2816 /// __len__ | Size of passed memory block or string in __hash__ 2817 /// __seed__ | Seeding value if this function is called in a loop or default to `0` 2818 /// 2819 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2820 */ 2821 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2822 /*/// #### nk_tree_image_push 2823 /// Start a collapsable UI section with image and label header 2824 /// !!! WARNING 2825 /// To keep track of the runtime tree collapsable state this function uses 2826 /// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2827 /// to call this function in a loop please use `nk_tree_image_push_id` or 2828 /// `nk_tree_image_push_hashed` instead. 2829 /// 2830 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2831 /// #define nk_tree_image_push(ctx, type, img, title, state) 2832 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2833 // 2834 /// Parameter | Description 2835 /// ------------|----------------------------------------------------------- 2836 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2837 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2838 /// __img__ | Image to display inside the header on the left of the label 2839 /// __title__ | Label printed in the tree header 2840 /// __state__ | Initial tree state value out of nk_collapse_states 2841 /// 2842 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2843 */ 2844 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__) 2845 /*/// #### nk_tree_image_push_id 2846 /// Start a collapsable UI section with image and label header and internal state 2847 /// management callable in a look 2848 /// 2849 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2850 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id) 2851 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2852 /// 2853 /// Parameter | Description 2854 /// ------------|----------------------------------------------------------- 2855 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2856 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2857 /// __img__ | Image to display inside the header on the left of the label 2858 /// __title__ | Label printed in the tree header 2859 /// __state__ | Initial tree state value out of nk_collapse_states 2860 /// __id__ | Loop counter index if this function is called in a loop 2861 /// 2862 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2863 */ 2864 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id) 2865 /*/// #### nk_tree_image_push_hashed 2866 /// Start a collapsable UI section with internal state management with full 2867 /// control over internal unique ID used to store state 2868 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2869 /// int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2870 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2871 /// 2872 /// Parameter | Description 2873 /// ------------|----------------------------------------------------------- 2874 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2875 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2876 /// __img__ | Image to display inside the header on the left of the label 2877 /// __title__ | Label printed in the tree header 2878 /// __state__ | Initial tree state value out of nk_collapse_states 2879 /// __hash__ | Memory block or string to generate the ID from 2880 /// __len__ | Size of passed memory block or string in __hash__ 2881 /// __seed__ | Seeding value if this function is called in a loop or default to `0` 2882 /// 2883 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2884 */ 2885 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2886 /*/// #### nk_tree_pop 2887 /// Ends a collapsabale UI section 2888 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2889 /// void nk_tree_pop(struct nk_context*); 2890 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2891 /// 2892 /// Parameter | Description 2893 /// ------------|----------------------------------------------------------- 2894 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2895 */ 2896 NK_API void nk_tree_pop(struct nk_context*); 2897 /*/// #### nk_tree_state_push 2898 /// Start a collapsable UI section with external state management 2899 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2900 /// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 2901 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2902 /// 2903 /// Parameter | Description 2904 /// ------------|----------------------------------------------------------- 2905 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2906 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2907 /// __title__ | Label printed in the tree header 2908 /// __state__ | Persistent state to update 2909 /// 2910 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2911 */ 2912 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 2913 /*/// #### nk_tree_state_image_push 2914 /// Start a collapsable UI section with image and label header and external state management 2915 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2916 /// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); 2917 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2918 /// 2919 /// Parameter | Description 2920 /// ------------|----------------------------------------------------------- 2921 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2922 /// __img__ | Image to display inside the header on the left of the label 2923 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2924 /// __title__ | Label printed in the tree header 2925 /// __state__ | Persistent state to update 2926 /// 2927 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2928 */ 2929 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); 2930 /*/// #### nk_tree_state_pop 2931 /// Ends a collapsabale UI section 2932 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2933 /// void nk_tree_state_pop(struct nk_context*); 2934 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2935 /// 2936 /// Parameter | Description 2937 /// ------------|----------------------------------------------------------- 2938 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2939 */ 2940 NK_API void nk_tree_state_pop(struct nk_context*); 2941 2942 #define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__) 2943 #define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id) 2944 NK_API int nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len, int seed); 2945 NK_API int nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, int *selected, const char *hash, int len,int seed); 2946 NK_API void nk_tree_element_pop(struct nk_context*); 2947 2948 /* ============================================================================= 2949 * 2950 * LIST VIEW 2951 * 2952 * ============================================================================= */ 2953 struct nk_list_view { 2954 /* public: */ 2955 int begin, end, count; 2956 /* private: */ 2957 int total_height; 2958 struct nk_context *ctx; 2959 nk_uint *scroll_pointer; 2960 nk_uint scroll_value; 2961 }; 2962 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count); 2963 NK_API void nk_list_view_end(struct nk_list_view*); 2964 /* ============================================================================= 2965 * 2966 * WIDGET 2967 * 2968 * ============================================================================= */ 2969 enum nk_widget_layout_states { 2970 NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */ 2971 NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */ 2972 NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */ 2973 }; 2974 enum nk_widget_states { 2975 NK_WIDGET_STATE_MODIFIED = NK_FLAG(1), 2976 NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */ 2977 NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */ 2978 NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */ 2979 NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */ 2980 NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */ 2981 NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */ 2982 NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */ 2983 }; 2984 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*); 2985 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2); 2986 NK_API struct nk_rect nk_widget_bounds(struct nk_context*); 2987 NK_API struct nk_vec2 nk_widget_position(struct nk_context*); 2988 NK_API struct nk_vec2 nk_widget_size(struct nk_context*); 2989 NK_API float nk_widget_width(struct nk_context*); 2990 NK_API float nk_widget_height(struct nk_context*); 2991 NK_API int nk_widget_is_hovered(struct nk_context*); 2992 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons); 2993 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down); 2994 NK_API void nk_spacing(struct nk_context*, int cols); 2995 /* ============================================================================= 2996 * 2997 * TEXT 2998 * 2999 * ============================================================================= */ 3000 enum nk_text_align { 3001 NK_TEXT_ALIGN_LEFT = 0x01, 3002 NK_TEXT_ALIGN_CENTERED = 0x02, 3003 NK_TEXT_ALIGN_RIGHT = 0x04, 3004 NK_TEXT_ALIGN_TOP = 0x08, 3005 NK_TEXT_ALIGN_MIDDLE = 0x10, 3006 NK_TEXT_ALIGN_BOTTOM = 0x20 3007 }; 3008 enum nk_text_alignment { 3009 NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT, 3010 NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED, 3011 NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT 3012 }; 3013 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags); 3014 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color); 3015 NK_API void nk_text_wrap(struct nk_context*, const char*, int); 3016 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color); 3017 NK_API void nk_label(struct nk_context*, const char*, nk_flags align); 3018 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color); 3019 NK_API void nk_label_wrap(struct nk_context*, const char*); 3020 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color); 3021 NK_API void nk_image(struct nk_context*, struct nk_image); 3022 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color); 3023 #ifdef NK_INCLUDE_STANDARD_VARARGS 3024 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3); 3025 NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4); 3026 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2); 3027 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3); 3028 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3); 3029 NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4); 3030 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3031 NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3); 3032 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int); 3033 NK_API void nk_value_int(struct nk_context*, const char *prefix, int); 3034 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int); 3035 NK_API void nk_value_float(struct nk_context*, const char *prefix, float); 3036 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color); 3037 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color); 3038 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color); 3039 #endif 3040 /* ============================================================================= 3041 * 3042 * BUTTON 3043 * 3044 * ============================================================================= */ 3045 NK_API int nk_button_text(struct nk_context*, const char *title, int len); 3046 NK_API int nk_button_label(struct nk_context*, const char *title); 3047 NK_API int nk_button_color(struct nk_context*, struct nk_color); 3048 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type); 3049 NK_API int nk_button_image(struct nk_context*, struct nk_image img); 3050 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment); 3051 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3052 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment); 3053 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment); 3054 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len); 3055 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title); 3056 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type); 3057 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img); 3058 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3059 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align); 3060 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment); 3061 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment); 3062 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior); 3063 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior); 3064 NK_API int nk_button_pop_behavior(struct nk_context*); 3065 /* ============================================================================= 3066 * 3067 * CHECKBOX 3068 * 3069 * ============================================================================= */ 3070 NK_API int nk_check_label(struct nk_context*, const char*, int active); 3071 NK_API int nk_check_text(struct nk_context*, const char*, int,int active); 3072 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value); 3073 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value); 3074 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active); 3075 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active); 3076 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value); 3077 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value); 3078 /* ============================================================================= 3079 * 3080 * RADIO BUTTON 3081 * 3082 * ============================================================================= */ 3083 NK_API int nk_radio_label(struct nk_context*, const char*, int *active); 3084 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active); 3085 NK_API int nk_option_label(struct nk_context*, const char*, int active); 3086 NK_API int nk_option_text(struct nk_context*, const char*, int, int active); 3087 /* ============================================================================= 3088 * 3089 * SELECTABLE 3090 * 3091 * ============================================================================= */ 3092 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value); 3093 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value); 3094 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value); 3095 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value); 3096 NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int *value); 3097 NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value); 3098 3099 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value); 3100 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value); 3101 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value); 3102 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value); 3103 NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int value); 3104 NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value); 3105 3106 /* ============================================================================= 3107 * 3108 * SLIDER 3109 * 3110 * ============================================================================= */ 3111 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step); 3112 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); 3113 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step); 3114 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step); 3115 /* ============================================================================= 3116 * 3117 * PROGRESSBAR 3118 * 3119 * ============================================================================= */ 3120 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable); 3121 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable); 3122 3123 /* ============================================================================= 3124 * 3125 * COLOR PICKER 3126 * 3127 * ============================================================================= */ 3128 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format); 3129 NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format); 3130 /* ============================================================================= 3131 * 3132 * PROPERTIES 3133 * 3134 * ============================================================================= 3135 /// ### Properties 3136 /// Properties are the main value modification widgets in Nuklear. Changing a value 3137 /// can be achieved by dragging, adding/removing incremental steps on button click 3138 /// or by directly typing a number. 3139 /// 3140 /// #### Usage 3141 /// Each property requires a unique name for identifaction that is also used for 3142 /// displaying a label. If you want to use the same name multiple times make sure 3143 /// add a '#' before your name. The '#' will not be shown but will generate a 3144 /// unique ID. Each propery also takes in a minimum and maximum value. If you want 3145 /// to make use of the complete number range of a type just use the provided 3146 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for 3147 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in 3148 /// a increment value that will be added or subtracted if either the increment 3149 /// decrement button is clicked. Finally there is a value for increment per pixel 3150 /// dragged that is added or subtracted from the value. 3151 /// 3152 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3153 /// int value = 0; 3154 /// struct nk_context ctx; 3155 /// nk_init_xxx(&ctx, ...); 3156 /// while (1) { 3157 /// // Input 3158 /// Event evt; 3159 /// nk_input_begin(&ctx); 3160 /// while (GetEvent(&evt)) { 3161 /// if (evt.type == MOUSE_MOVE) 3162 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 3163 /// else if (evt.type == [...]) { 3164 /// nk_input_xxx(...); 3165 /// } 3166 /// } 3167 /// nk_input_end(&ctx); 3168 /// // 3169 /// // Window 3170 /// if (nk_begin_xxx(...) { 3171 /// // Property 3172 /// nk_layout_row_dynamic(...); 3173 /// nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1); 3174 /// } 3175 /// nk_end(ctx); 3176 /// // 3177 /// // Draw 3178 /// const struct nk_command *cmd = 0; 3179 /// nk_foreach(cmd, &ctx) { 3180 /// switch (cmd->type) { 3181 /// case NK_COMMAND_LINE: 3182 /// your_draw_line_function(...) 3183 /// break; 3184 /// case NK_COMMAND_RECT 3185 /// your_draw_rect_function(...) 3186 /// break; 3187 /// case ...: 3188 /// // [...] 3189 /// } 3190 // nk_clear(&ctx); 3191 /// } 3192 /// nk_free(&ctx); 3193 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3194 /// 3195 /// #### Reference 3196 /// Function | Description 3197 /// --------------------|------------------------------------------- 3198 /// nk_property_int | Integer property directly modifing a passed in value 3199 /// nk_property_float | Float property directly modifing a passed in value 3200 /// nk_property_double | Double property directly modifing a passed in value 3201 /// nk_propertyi | Integer property returning the modified int value 3202 /// nk_propertyf | Float property returning the modified float value 3203 /// nk_propertyd | Double property returning the modified double value 3204 /// 3205 */ 3206 /*/// #### nk_property_int 3207 /// Integer property directly modifing a passed in value 3208 /// !!! WARNING 3209 /// To generate a unique property ID using the same label make sure to insert 3210 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3211 /// 3212 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3213 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3214 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3215 /// 3216 /// Parameter | Description 3217 /// --------------------|----------------------------------------------------------- 3218 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3219 /// __name__ | String used both as a label as well as a unique identifier 3220 /// __min__ | Minimum value not allowed to be underflown 3221 /// __val__ | Integer pointer to be modified 3222 /// __max__ | Maximum value not allowed to be overflown 3223 /// __step__ | Increment added and subtracted on increment and decrement button 3224 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3225 */ 3226 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3227 /*/// #### nk_property_float 3228 /// Float property directly modifing a passed in value 3229 /// !!! WARNING 3230 /// To generate a unique property ID using the same label make sure to insert 3231 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3232 /// 3233 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3234 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3235 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3236 /// 3237 /// Parameter | Description 3238 /// --------------------|----------------------------------------------------------- 3239 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3240 /// __name__ | String used both as a label as well as a unique identifier 3241 /// __min__ | Minimum value not allowed to be underflown 3242 /// __val__ | Float pointer to be modified 3243 /// __max__ | Maximum value not allowed to be overflown 3244 /// __step__ | Increment added and subtracted on increment and decrement button 3245 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3246 */ 3247 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3248 /*/// #### nk_property_double 3249 /// Double property directly modifing a passed in value 3250 /// !!! WARNING 3251 /// To generate a unique property ID using the same label make sure to insert 3252 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3253 /// 3254 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3255 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel); 3256 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3257 /// 3258 /// Parameter | Description 3259 /// --------------------|----------------------------------------------------------- 3260 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3261 /// __name__ | String used both as a label as well as a unique identifier 3262 /// __min__ | Minimum value not allowed to be underflown 3263 /// __val__ | Double pointer to be modified 3264 /// __max__ | Maximum value not allowed to be overflown 3265 /// __step__ | Increment added and subtracted on increment and decrement button 3266 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3267 */ 3268 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel); 3269 /*/// #### nk_propertyi 3270 /// Integer property modifing a passed in value and returning the new value 3271 /// !!! WARNING 3272 /// To generate a unique property ID using the same label make sure to insert 3273 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3274 /// 3275 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3276 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3277 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3278 /// 3279 /// Parameter | Description 3280 /// --------------------|----------------------------------------------------------- 3281 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3282 /// __name__ | String used both as a label as well as a unique identifier 3283 /// __min__ | Minimum value not allowed to be underflown 3284 /// __val__ | Current integer value to be modified and returned 3285 /// __max__ | Maximum value not allowed to be overflown 3286 /// __step__ | Increment added and subtracted on increment and decrement button 3287 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3288 /// 3289 /// Returns the new modified integer value 3290 */ 3291 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3292 /*/// #### nk_propertyf 3293 /// Float property modifing a passed in value and returning the new value 3294 /// !!! WARNING 3295 /// To generate a unique property ID using the same label make sure to insert 3296 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3297 /// 3298 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3299 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3300 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3301 /// 3302 /// Parameter | Description 3303 /// --------------------|----------------------------------------------------------- 3304 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3305 /// __name__ | String used both as a label as well as a unique identifier 3306 /// __min__ | Minimum value not allowed to be underflown 3307 /// __val__ | Current float value to be modified and returned 3308 /// __max__ | Maximum value not allowed to be overflown 3309 /// __step__ | Increment added and subtracted on increment and decrement button 3310 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3311 /// 3312 /// Returns the new modified float value 3313 */ 3314 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3315 /*/// #### nk_propertyd 3316 /// Float property modifing a passed in value and returning the new value 3317 /// !!! WARNING 3318 /// To generate a unique property ID using the same label make sure to insert 3319 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3320 /// 3321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3322 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel); 3323 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3324 /// 3325 /// Parameter | Description 3326 /// --------------------|----------------------------------------------------------- 3327 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3328 /// __name__ | String used both as a label as well as a unique identifier 3329 /// __min__ | Minimum value not allowed to be underflown 3330 /// __val__ | Current double value to be modified and returned 3331 /// __max__ | Maximum value not allowed to be overflown 3332 /// __step__ | Increment added and subtracted on increment and decrement button 3333 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3334 /// 3335 /// Returns the new modified double value 3336 */ 3337 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel); 3338 /* ============================================================================= 3339 * 3340 * TEXT EDIT 3341 * 3342 * ============================================================================= */ 3343 enum nk_edit_flags { 3344 NK_EDIT_DEFAULT = 0, 3345 NK_EDIT_READ_ONLY = NK_FLAG(0), 3346 NK_EDIT_AUTO_SELECT = NK_FLAG(1), 3347 NK_EDIT_SIG_ENTER = NK_FLAG(2), 3348 NK_EDIT_ALLOW_TAB = NK_FLAG(3), 3349 NK_EDIT_NO_CURSOR = NK_FLAG(4), 3350 NK_EDIT_SELECTABLE = NK_FLAG(5), 3351 NK_EDIT_CLIPBOARD = NK_FLAG(6), 3352 NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7), 3353 NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8), 3354 NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9), 3355 NK_EDIT_MULTILINE = NK_FLAG(10), 3356 NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(11) 3357 }; 3358 enum nk_edit_types { 3359 NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE, 3360 NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD, 3361 NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD, 3362 NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD 3363 }; 3364 enum nk_edit_events { 3365 NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */ 3366 NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */ 3367 NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */ 3368 NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */ 3369 NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */ 3370 }; 3371 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter); 3372 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter); 3373 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter); 3374 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags); 3375 NK_API void nk_edit_unfocus(struct nk_context*); 3376 /* ============================================================================= 3377 * 3378 * CHART 3379 * 3380 * ============================================================================= */ 3381 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max); 3382 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max); 3383 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value); 3384 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value); 3385 NK_API nk_flags nk_chart_push(struct nk_context*, float); 3386 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int); 3387 NK_API void nk_chart_end(struct nk_context*); 3388 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset); 3389 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset); 3390 /* ============================================================================= 3391 * 3392 * POPUP 3393 * 3394 * ============================================================================= */ 3395 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); 3396 NK_API void nk_popup_close(struct nk_context*); 3397 NK_API void nk_popup_end(struct nk_context*); 3398 /* ============================================================================= 3399 * 3400 * COMBOBOX 3401 * 3402 * ============================================================================= */ 3403 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size); 3404 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size); 3405 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size); 3406 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size); 3407 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); 3408 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size); 3409 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size); 3410 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size); 3411 /* ============================================================================= 3412 * 3413 * ABSTRACT COMBOBOX 3414 * 3415 * ============================================================================= */ 3416 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size); 3417 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size); 3418 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size); 3419 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size); 3420 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size); 3421 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size); 3422 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size); 3423 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size); 3424 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size); 3425 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment); 3426 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment); 3427 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3428 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment); 3429 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3430 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3431 NK_API void nk_combo_close(struct nk_context*); 3432 NK_API void nk_combo_end(struct nk_context*); 3433 /* ============================================================================= 3434 * 3435 * CONTEXTUAL 3436 * 3437 * ============================================================================= */ 3438 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds); 3439 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align); 3440 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align); 3441 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3442 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3443 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3444 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3445 NK_API void nk_contextual_close(struct nk_context*); 3446 NK_API void nk_contextual_end(struct nk_context*); 3447 /* ============================================================================= 3448 * 3449 * TOOLTIP 3450 * 3451 * ============================================================================= */ 3452 NK_API void nk_tooltip(struct nk_context*, const char*); 3453 #ifdef NK_INCLUDE_STANDARD_VARARGS 3454 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2); 3455 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3456 #endif 3457 NK_API int nk_tooltip_begin(struct nk_context*, float width); 3458 NK_API void nk_tooltip_end(struct nk_context*); 3459 /* ============================================================================= 3460 * 3461 * MENU 3462 * 3463 * ============================================================================= */ 3464 NK_API void nk_menubar_begin(struct nk_context*); 3465 NK_API void nk_menubar_end(struct nk_context*); 3466 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size); 3467 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size); 3468 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size); 3469 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size); 3470 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size); 3471 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size); 3472 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3473 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3474 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align); 3475 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment); 3476 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3477 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3478 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3479 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3480 NK_API void nk_menu_close(struct nk_context*); 3481 NK_API void nk_menu_end(struct nk_context*); 3482 /* ============================================================================= 3483 * 3484 * STYLE 3485 * 3486 * ============================================================================= */ 3487 enum nk_style_colors { 3488 NK_COLOR_TEXT, 3489 NK_COLOR_WINDOW, 3490 NK_COLOR_HEADER, 3491 NK_COLOR_BORDER, 3492 NK_COLOR_BUTTON, 3493 NK_COLOR_BUTTON_HOVER, 3494 NK_COLOR_BUTTON_ACTIVE, 3495 NK_COLOR_TOGGLE, 3496 NK_COLOR_TOGGLE_HOVER, 3497 NK_COLOR_TOGGLE_CURSOR, 3498 NK_COLOR_SELECT, 3499 NK_COLOR_SELECT_ACTIVE, 3500 NK_COLOR_SLIDER, 3501 NK_COLOR_SLIDER_CURSOR, 3502 NK_COLOR_SLIDER_CURSOR_HOVER, 3503 NK_COLOR_SLIDER_CURSOR_ACTIVE, 3504 NK_COLOR_PROPERTY, 3505 NK_COLOR_EDIT, 3506 NK_COLOR_EDIT_CURSOR, 3507 NK_COLOR_COMBO, 3508 NK_COLOR_CHART, 3509 NK_COLOR_CHART_COLOR, 3510 NK_COLOR_CHART_COLOR_HIGHLIGHT, 3511 NK_COLOR_SCROLLBAR, 3512 NK_COLOR_SCROLLBAR_CURSOR, 3513 NK_COLOR_SCROLLBAR_CURSOR_HOVER, 3514 NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 3515 NK_COLOR_TAB_HEADER, 3516 NK_COLOR_COUNT 3517 }; 3518 enum nk_style_cursor { 3519 NK_CURSOR_ARROW, 3520 NK_CURSOR_TEXT, 3521 NK_CURSOR_MOVE, 3522 NK_CURSOR_RESIZE_VERTICAL, 3523 NK_CURSOR_RESIZE_HORIZONTAL, 3524 NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT, 3525 NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT, 3526 NK_CURSOR_COUNT 3527 }; 3528 NK_API void nk_style_default(struct nk_context*); 3529 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*); 3530 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*); 3531 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*); 3532 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors); 3533 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*); 3534 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor); 3535 NK_API void nk_style_show_cursor(struct nk_context*); 3536 NK_API void nk_style_hide_cursor(struct nk_context*); 3537 3538 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*); 3539 NK_API int nk_style_push_float(struct nk_context*, float*, float); 3540 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2); 3541 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item); 3542 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags); 3543 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color); 3544 3545 NK_API int nk_style_pop_font(struct nk_context*); 3546 NK_API int nk_style_pop_float(struct nk_context*); 3547 NK_API int nk_style_pop_vec2(struct nk_context*); 3548 NK_API int nk_style_pop_style_item(struct nk_context*); 3549 NK_API int nk_style_pop_flags(struct nk_context*); 3550 NK_API int nk_style_pop_color(struct nk_context*); 3551 /* ============================================================================= 3552 * 3553 * COLOR 3554 * 3555 * ============================================================================= */ 3556 NK_API struct nk_color nk_rgb(int r, int g, int b); 3557 NK_API struct nk_color nk_rgb_iv(const int *rgb); 3558 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb); 3559 NK_API struct nk_color nk_rgb_f(float r, float g, float b); 3560 NK_API struct nk_color nk_rgb_fv(const float *rgb); 3561 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c); 3562 NK_API struct nk_color nk_rgb_hex(const char *rgb); 3563 3564 NK_API struct nk_color nk_rgba(int r, int g, int b, int a); 3565 NK_API struct nk_color nk_rgba_u32(nk_uint); 3566 NK_API struct nk_color nk_rgba_iv(const int *rgba); 3567 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba); 3568 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a); 3569 NK_API struct nk_color nk_rgba_fv(const float *rgba); 3570 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c); 3571 NK_API struct nk_color nk_rgba_hex(const char *rgb); 3572 3573 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a); 3574 NK_API struct nk_colorf nk_hsva_colorfv(float *c); 3575 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in); 3576 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in); 3577 3578 NK_API struct nk_color nk_hsv(int h, int s, int v); 3579 NK_API struct nk_color nk_hsv_iv(const int *hsv); 3580 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv); 3581 NK_API struct nk_color nk_hsv_f(float h, float s, float v); 3582 NK_API struct nk_color nk_hsv_fv(const float *hsv); 3583 3584 NK_API struct nk_color nk_hsva(int h, int s, int v, int a); 3585 NK_API struct nk_color nk_hsva_iv(const int *hsva); 3586 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva); 3587 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a); 3588 NK_API struct nk_color nk_hsva_fv(const float *hsva); 3589 3590 /* color (conversion nuklear --> user) */ 3591 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color); 3592 NK_API void nk_color_fv(float *rgba_out, struct nk_color); 3593 NK_API struct nk_colorf nk_color_cf(struct nk_color); 3594 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color); 3595 NK_API void nk_color_dv(double *rgba_out, struct nk_color); 3596 3597 NK_API nk_uint nk_color_u32(struct nk_color); 3598 NK_API void nk_color_hex_rgba(char *output, struct nk_color); 3599 NK_API void nk_color_hex_rgb(char *output, struct nk_color); 3600 3601 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color); 3602 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color); 3603 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color); 3604 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color); 3605 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color); 3606 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color); 3607 3608 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color); 3609 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color); 3610 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color); 3611 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color); 3612 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color); 3613 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color); 3614 /* ============================================================================= 3615 * 3616 * IMAGE 3617 * 3618 * ============================================================================= */ 3619 NK_API nk_handle nk_handle_ptr(void*); 3620 NK_API nk_handle nk_handle_id(int); 3621 NK_API struct nk_image nk_image_handle(nk_handle); 3622 NK_API struct nk_image nk_image_ptr(void*); 3623 NK_API struct nk_image nk_image_id(int); 3624 NK_API int nk_image_is_subimage(const struct nk_image* img); 3625 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region); 3626 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region); 3627 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region); 3628 /* ============================================================================= 3629 * 3630 * MATH 3631 * 3632 * ============================================================================= */ 3633 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed); 3634 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading); 3635 3636 NK_API struct nk_vec2 nk_vec2(float x, float y); 3637 NK_API struct nk_vec2 nk_vec2i(int x, int y); 3638 NK_API struct nk_vec2 nk_vec2v(const float *xy); 3639 NK_API struct nk_vec2 nk_vec2iv(const int *xy); 3640 3641 NK_API struct nk_rect nk_get_null_rect(void); 3642 NK_API struct nk_rect nk_rect(float x, float y, float w, float h); 3643 NK_API struct nk_rect nk_recti(int x, int y, int w, int h); 3644 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size); 3645 NK_API struct nk_rect nk_rectv(const float *xywh); 3646 NK_API struct nk_rect nk_rectiv(const int *xywh); 3647 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect); 3648 NK_API struct nk_vec2 nk_rect_size(struct nk_rect); 3649 /* ============================================================================= 3650 * 3651 * STRING 3652 * 3653 * ============================================================================= */ 3654 NK_API int nk_strlen(const char *str); 3655 NK_API int nk_stricmp(const char *s1, const char *s2); 3656 NK_API int nk_stricmpn(const char *s1, const char *s2, int n); 3657 NK_API int nk_strtoi(const char *str, const char **endptr); 3658 NK_API float nk_strtof(const char *str, const char **endptr); 3659 NK_API double nk_strtod(const char *str, const char **endptr); 3660 NK_API int nk_strfilter(const char *text, const char *regexp); 3661 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score); 3662 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score); 3663 /* ============================================================================= 3664 * 3665 * UTF-8 3666 * 3667 * ============================================================================= */ 3668 NK_API int nk_utf_decode(const char*, nk_rune*, int); 3669 NK_API int nk_utf_encode(nk_rune, char*, int); 3670 NK_API int nk_utf_len(const char*, int byte_len); 3671 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len); 3672 /* =============================================================== 3673 * 3674 * FONT 3675 * 3676 * ===============================================================*/ 3677 /* Font handling in this library was designed to be quite customizable and lets 3678 you decide what you want to use and what you want to provide. There are three 3679 different ways to use the font atlas. The first two will use your font 3680 handling scheme and only requires essential data to run nuklear. The next 3681 slightly more advanced features is font handling with vertex buffer output. 3682 Finally the most complex API wise is using nuklear's font baking API. 3683 3684 1.) Using your own implementation without vertex buffer output 3685 -------------------------------------------------------------- 3686 So first up the easiest way to do font handling is by just providing a 3687 `nk_user_font` struct which only requires the height in pixel of the used 3688 font and a callback to calculate the width of a string. This way of handling 3689 fonts is best fitted for using the normal draw shape command API where you 3690 do all the text drawing yourself and the library does not require any kind 3691 of deeper knowledge about which font handling mechanism you use. 3692 IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist 3693 over the complete life time! I know this sucks but it is currently the only 3694 way to switch between fonts. 3695 3696 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3697 { 3698 your_font_type *type = handle.ptr; 3699 float text_width = ...; 3700 return text_width; 3701 } 3702 3703 struct nk_user_font font; 3704 font.userdata.ptr = &your_font_class_or_struct; 3705 font.height = your_font_height; 3706 font.width = your_text_width_calculation; 3707 3708 struct nk_context ctx; 3709 nk_init_default(&ctx, &font); 3710 3711 2.) Using your own implementation with vertex buffer output 3712 -------------------------------------------------------------- 3713 While the first approach works fine if you don't want to use the optional 3714 vertex buffer output it is not enough if you do. To get font handling working 3715 for these cases you have to provide two additional parameters inside the 3716 `nk_user_font`. First a texture atlas handle used to draw text as subimages 3717 of a bigger font atlas texture and a callback to query a character's glyph 3718 information (offset, size, ...). So it is still possible to provide your own 3719 font and use the vertex buffer output. 3720 3721 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3722 { 3723 your_font_type *type = handle.ptr; 3724 float text_width = ...; 3725 return text_width; 3726 } 3727 void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 3728 { 3729 your_font_type *type = handle.ptr; 3730 glyph.width = ...; 3731 glyph.height = ...; 3732 glyph.xadvance = ...; 3733 glyph.uv[0].x = ...; 3734 glyph.uv[0].y = ...; 3735 glyph.uv[1].x = ...; 3736 glyph.uv[1].y = ...; 3737 glyph.offset.x = ...; 3738 glyph.offset.y = ...; 3739 } 3740 3741 struct nk_user_font font; 3742 font.userdata.ptr = &your_font_class_or_struct; 3743 font.height = your_font_height; 3744 font.width = your_text_width_calculation; 3745 font.query = query_your_font_glyph; 3746 font.texture.id = your_font_texture; 3747 3748 struct nk_context ctx; 3749 nk_init_default(&ctx, &font); 3750 3751 3.) Nuklear font baker 3752 ------------------------------------ 3753 The final approach if you do not have a font handling functionality or don't 3754 want to use it in this library is by using the optional font baker. 3755 The font baker APIs can be used to create a font plus font atlas texture 3756 and can be used with or without the vertex buffer output. 3757 3758 It still uses the `nk_user_font` struct and the two different approaches 3759 previously stated still work. The font baker is not located inside 3760 `nk_context` like all other systems since it can be understood as more of 3761 an extension to nuklear and does not really depend on any `nk_context` state. 3762 3763 Font baker need to be initialized first by one of the nk_font_atlas_init_xxx 3764 functions. If you don't care about memory just call the default version 3765 `nk_font_atlas_init_default` which will allocate all memory from the standard library. 3766 If you want to control memory allocation but you don't care if the allocated 3767 memory is temporary and therefore can be freed directly after the baking process 3768 is over or permanent you can call `nk_font_atlas_init`. 3769 3770 After successfully initializing the font baker you can add Truetype(.ttf) fonts from 3771 different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`. 3772 functions. Adding font will permanently store each font, font config and ttf memory block(!) 3773 inside the font atlas and allows to reuse the font atlas. If you don't want to reuse 3774 the font baker by for example adding additional fonts you can call 3775 `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end). 3776 3777 As soon as you added all fonts you wanted you can now start the baking process 3778 for every selected glyph to image by calling `nk_font_atlas_bake`. 3779 The baking process returns image memory, width and height which can be used to 3780 either create your own image object or upload it to any graphics library. 3781 No matter which case you finally have to call `nk_font_atlas_end` which 3782 will free all temporary memory including the font atlas image so make sure 3783 you created our texture beforehand. `nk_font_atlas_end` requires a handle 3784 to your font texture or object and optionally fills a `struct nk_draw_null_texture` 3785 which can be used for the optional vertex output. If you don't want it just 3786 set the argument to `NULL`. 3787 3788 At this point you are done and if you don't want to reuse the font atlas you 3789 can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration 3790 memory. Finally if you don't use the font atlas and any of it's fonts anymore 3791 you need to call `nk_font_atlas_clear` to free all memory still being used. 3792 3793 struct nk_font_atlas atlas; 3794 nk_font_atlas_init_default(&atlas); 3795 nk_font_atlas_begin(&atlas); 3796 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0); 3797 nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0); 3798 const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32); 3799 nk_font_atlas_end(&atlas, nk_handle_id(texture), 0); 3800 3801 struct nk_context ctx; 3802 nk_init_default(&ctx, &font->handle); 3803 while (1) { 3804 3805 } 3806 nk_font_atlas_clear(&atlas); 3807 3808 The font baker API is probably the most complex API inside this library and 3809 I would suggest reading some of my examples `example/` to get a grip on how 3810 to use the font atlas. There are a number of details I left out. For example 3811 how to merge fonts, configure a font with `nk_font_config` to use other languages, 3812 use another texture coordinate format and a lot more: 3813 3814 struct nk_font_config cfg = nk_font_config(font_pixel_height); 3815 cfg.merge_mode = nk_false or nk_true; 3816 cfg.range = nk_font_korean_glyph_ranges(); 3817 cfg.coord_type = NK_COORD_PIXEL; 3818 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg); 3819 3820 */ 3821 struct nk_user_font_glyph; 3822 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len); 3823 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height, 3824 struct nk_user_font_glyph *glyph, 3825 nk_rune codepoint, nk_rune next_codepoint); 3826 3827 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT) 3828 struct nk_user_font_glyph { 3829 struct nk_vec2 uv[2]; 3830 /* texture coordinates */ 3831 struct nk_vec2 offset; 3832 /* offset between top left and glyph */ 3833 float width, height; 3834 /* size of the glyph */ 3835 float xadvance; 3836 /* offset to the next glyph */ 3837 }; 3838 #endif 3839 3840 struct nk_user_font { 3841 nk_handle userdata; 3842 /* user provided font handle */ 3843 float height; 3844 /* max height of the font */ 3845 nk_text_width_f width; 3846 /* font string width in pixel callback */ 3847 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 3848 nk_query_font_glyph_f query; 3849 /* font glyph callback to query drawing info */ 3850 nk_handle texture; 3851 /* texture handle to the used font atlas or texture */ 3852 #endif 3853 }; 3854 3855 #ifdef NK_INCLUDE_FONT_BAKING 3856 enum nk_font_coord_type { 3857 NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */ 3858 NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */ 3859 }; 3860 3861 struct nk_font; 3862 struct nk_baked_font { 3863 float height; 3864 /* height of the font */ 3865 float ascent, descent; 3866 /* font glyphs ascent and descent */ 3867 nk_rune glyph_offset; 3868 /* glyph array offset inside the font glyph baking output array */ 3869 nk_rune glyph_count; 3870 /* number of glyphs of this font inside the glyph baking array output */ 3871 const nk_rune *ranges; 3872 /* font codepoint ranges as pairs of (from/to) and 0 as last element */ 3873 }; 3874 3875 struct nk_font_config { 3876 struct nk_font_config *next; 3877 /* NOTE: only used internally */ 3878 void *ttf_blob; 3879 /* pointer to loaded TTF file memory block. 3880 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 3881 nk_size ttf_size; 3882 /* size of the loaded TTF file memory block 3883 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 3884 3885 unsigned char ttf_data_owned_by_atlas; 3886 /* used inside font atlas: default to: 0*/ 3887 unsigned char merge_mode; 3888 /* merges this font into the last font */ 3889 unsigned char pixel_snap; 3890 /* align every character to pixel boundary (if true set oversample (1,1)) */ 3891 unsigned char oversample_v, oversample_h; 3892 /* rasterize at hight quality for sub-pixel position */ 3893 unsigned char padding[3]; 3894 3895 float size; 3896 /* baked pixel height of the font */ 3897 enum nk_font_coord_type coord_type; 3898 /* texture coordinate format with either pixel or UV coordinates */ 3899 struct nk_vec2 spacing; 3900 /* extra pixel spacing between glyphs */ 3901 const nk_rune *range; 3902 /* list of unicode ranges (2 values per range, zero terminated) */ 3903 struct nk_baked_font *font; 3904 /* font to setup in the baking process: NOTE: not needed for font atlas */ 3905 nk_rune fallback_glyph; 3906 /* fallback glyph to use if a given rune is not found */ 3907 struct nk_font_config *n; 3908 struct nk_font_config *p; 3909 }; 3910 3911 struct nk_font_glyph { 3912 nk_rune codepoint; 3913 float xadvance; 3914 float x0, y0, x1, y1, w, h; 3915 float u0, v0, u1, v1; 3916 }; 3917 3918 struct nk_font { 3919 struct nk_font *next; 3920 struct nk_user_font handle; 3921 struct nk_baked_font info; 3922 float scale; 3923 struct nk_font_glyph *glyphs; 3924 const struct nk_font_glyph *fallback; 3925 nk_rune fallback_codepoint; 3926 nk_handle texture; 3927 struct nk_font_config *config; 3928 }; 3929 3930 enum nk_font_atlas_format { 3931 NK_FONT_ATLAS_ALPHA8, 3932 NK_FONT_ATLAS_RGBA32 3933 }; 3934 3935 struct nk_font_atlas { 3936 void *pixel; 3937 int tex_width; 3938 int tex_height; 3939 3940 struct nk_allocator permanent; 3941 struct nk_allocator temporary; 3942 3943 struct nk_recti custom; 3944 struct nk_cursor cursors[NK_CURSOR_COUNT]; 3945 3946 int glyph_count; 3947 struct nk_font_glyph *glyphs; 3948 struct nk_font *default_font; 3949 struct nk_font *fonts; 3950 struct nk_font_config *config; 3951 int font_num; 3952 }; 3953 3954 /* some language glyph codepoint ranges */ 3955 NK_API const nk_rune *nk_font_default_glyph_ranges(void); 3956 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void); 3957 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void); 3958 NK_API const nk_rune *nk_font_korean_glyph_ranges(void); 3959 3960 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 3961 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*); 3962 #endif 3963 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*); 3964 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient); 3965 NK_API void nk_font_atlas_begin(struct nk_font_atlas*); 3966 NK_API struct nk_font_config nk_font_config(float pixel_height); 3967 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*); 3968 #ifdef NK_INCLUDE_DEFAULT_FONT 3969 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*); 3970 #endif 3971 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config); 3972 #ifdef NK_INCLUDE_STANDARD_IO 3973 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*); 3974 #endif 3975 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*); 3976 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config); 3977 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format); 3978 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*); 3979 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode); 3980 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas); 3981 NK_API void nk_font_atlas_clear(struct nk_font_atlas*); 3982 3983 #endif 3984 3985 /* ============================================================== 3986 * 3987 * MEMORY BUFFER 3988 * 3989 * ===============================================================*/ 3990 /* A basic (double)-buffer with linear allocation and resetting as only 3991 freeing policy. The buffer's main purpose is to control all memory management 3992 inside the GUI toolkit and still leave memory control as much as possible in 3993 the hand of the user while also making sure the library is easy to use if 3994 not as much control is needed. 3995 In general all memory inside this library can be provided from the user in 3996 three different ways. 3997 3998 The first way and the one providing most control is by just passing a fixed 3999 size memory block. In this case all control lies in the hand of the user 4000 since he can exactly control where the memory comes from and how much memory 4001 the library should consume. Of course using the fixed size API removes the 4002 ability to automatically resize a buffer if not enough memory is provided so 4003 you have to take over the resizing. While being a fixed sized buffer sounds 4004 quite limiting, it is very effective in this library since the actual memory 4005 consumption is quite stable and has a fixed upper bound for a lot of cases. 4006 4007 If you don't want to think about how much memory the library should allocate 4008 at all time or have a very dynamic UI with unpredictable memory consumption 4009 habits but still want control over memory allocation you can use the dynamic 4010 allocator based API. The allocator consists of two callbacks for allocating 4011 and freeing memory and optional userdata so you can plugin your own allocator. 4012 4013 The final and easiest way can be used by defining 4014 NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory 4015 allocation functions malloc and free and takes over complete control over 4016 memory in this library. 4017 */ 4018 struct nk_memory_status { 4019 void *memory; 4020 unsigned int type; 4021 nk_size size; 4022 nk_size allocated; 4023 nk_size needed; 4024 nk_size calls; 4025 }; 4026 4027 enum nk_allocation_type { 4028 NK_BUFFER_FIXED, 4029 NK_BUFFER_DYNAMIC 4030 }; 4031 4032 enum nk_buffer_allocation_type { 4033 NK_BUFFER_FRONT, 4034 NK_BUFFER_BACK, 4035 NK_BUFFER_MAX 4036 }; 4037 4038 struct nk_buffer_marker { 4039 int active; 4040 nk_size offset; 4041 }; 4042 4043 struct nk_memory {void *ptr;nk_size size;}; 4044 struct nk_buffer { 4045 struct nk_buffer_marker marker[NK_BUFFER_MAX]; 4046 /* buffer marker to free a buffer to a certain offset */ 4047 struct nk_allocator pool; 4048 /* allocator callback for dynamic buffers */ 4049 enum nk_allocation_type type; 4050 /* memory management type */ 4051 struct nk_memory memory; 4052 /* memory and size of the current memory block */ 4053 float grow_factor; 4054 /* growing factor for dynamic memory management */ 4055 nk_size allocated; 4056 /* total amount of memory allocated */ 4057 nk_size needed; 4058 /* totally consumed memory given that enough memory is present */ 4059 nk_size calls; 4060 /* number of allocation calls */ 4061 nk_size size; 4062 /* current size of the buffer */ 4063 }; 4064 4065 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4066 NK_API void nk_buffer_init_default(struct nk_buffer*); 4067 #endif 4068 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size); 4069 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size); 4070 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*); 4071 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align); 4072 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type); 4073 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type); 4074 NK_API void nk_buffer_clear(struct nk_buffer*); 4075 NK_API void nk_buffer_free(struct nk_buffer*); 4076 NK_API void *nk_buffer_memory(struct nk_buffer*); 4077 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*); 4078 NK_API nk_size nk_buffer_total(struct nk_buffer*); 4079 4080 /* ============================================================== 4081 * 4082 * STRING 4083 * 4084 * ===============================================================*/ 4085 /* Basic string buffer which is only used in context with the text editor 4086 * to manage and manipulate dynamic or fixed size string content. This is _NOT_ 4087 * the default string handling method. The only instance you should have any contact 4088 * with this API is if you interact with an `nk_text_edit` object inside one of the 4089 * copy and paste functions and even there only for more advanced cases. */ 4090 struct nk_str { 4091 struct nk_buffer buffer; 4092 int len; /* in codepoints/runes/glyphs */ 4093 }; 4094 4095 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4096 NK_API void nk_str_init_default(struct nk_str*); 4097 #endif 4098 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size); 4099 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size); 4100 NK_API void nk_str_clear(struct nk_str*); 4101 NK_API void nk_str_free(struct nk_str*); 4102 4103 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int); 4104 NK_API int nk_str_append_str_char(struct nk_str*, const char*); 4105 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int); 4106 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*); 4107 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int); 4108 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*); 4109 4110 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int); 4111 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int); 4112 4113 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int); 4114 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*); 4115 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int); 4116 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*); 4117 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int); 4118 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*); 4119 4120 NK_API void nk_str_remove_chars(struct nk_str*, int len); 4121 NK_API void nk_str_remove_runes(struct nk_str *str, int len); 4122 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len); 4123 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len); 4124 4125 NK_API char *nk_str_at_char(struct nk_str*, int pos); 4126 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len); 4127 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos); 4128 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos); 4129 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len); 4130 4131 NK_API char *nk_str_get(struct nk_str*); 4132 NK_API const char *nk_str_get_const(const struct nk_str*); 4133 NK_API int nk_str_len(struct nk_str*); 4134 NK_API int nk_str_len_char(struct nk_str*); 4135 4136 /*=============================================================== 4137 * 4138 * TEXT EDITOR 4139 * 4140 * ===============================================================*/ 4141 /* Editing text in this library is handled by either `nk_edit_string` or 4142 * `nk_edit_buffer`. But like almost everything in this library there are multiple 4143 * ways of doing it and a balance between control and ease of use with memory 4144 * as well as functionality controlled by flags. 4145 * 4146 * This library generally allows three different levels of memory control: 4147 * First of is the most basic way of just providing a simple char array with 4148 * string length. This method is probably the easiest way of handling simple 4149 * user text input. Main upside is complete control over memory while the biggest 4150 * downside in comparison with the other two approaches is missing undo/redo. 4151 * 4152 * For UIs that require undo/redo the second way was created. It is based on 4153 * a fixed size nk_text_edit struct, which has an internal undo/redo stack. 4154 * This is mainly useful if you want something more like a text editor but don't want 4155 * to have a dynamically growing buffer. 4156 * 4157 * The final way is using a dynamically growing nk_text_edit struct, which 4158 * has both a default version if you don't care where memory comes from and an 4159 * allocator version if you do. While the text editor is quite powerful for its 4160 * complexity I would not recommend editing gigabytes of data with it. 4161 * It is rather designed for uses cases which make sense for a GUI library not for 4162 * an full blown text editor. 4163 */ 4164 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT 4165 #define NK_TEXTEDIT_UNDOSTATECOUNT 99 4166 #endif 4167 4168 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT 4169 #define NK_TEXTEDIT_UNDOCHARCOUNT 999 4170 #endif 4171 4172 struct nk_text_edit; 4173 struct nk_clipboard { 4174 nk_handle userdata; 4175 nk_plugin_paste paste; 4176 nk_plugin_copy copy; 4177 }; 4178 4179 struct nk_text_undo_record { 4180 int where; 4181 short insert_length; 4182 short delete_length; 4183 short char_storage; 4184 }; 4185 4186 struct nk_text_undo_state { 4187 struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]; 4188 nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]; 4189 short undo_point; 4190 short redo_point; 4191 short undo_char_point; 4192 short redo_char_point; 4193 }; 4194 4195 enum nk_text_edit_type { 4196 NK_TEXT_EDIT_SINGLE_LINE, 4197 NK_TEXT_EDIT_MULTI_LINE 4198 }; 4199 4200 enum nk_text_edit_mode { 4201 NK_TEXT_EDIT_MODE_VIEW, 4202 NK_TEXT_EDIT_MODE_INSERT, 4203 NK_TEXT_EDIT_MODE_REPLACE 4204 }; 4205 4206 struct nk_text_edit { 4207 struct nk_clipboard clip; 4208 struct nk_str string; 4209 nk_plugin_filter filter; 4210 struct nk_vec2 scrollbar; 4211 4212 int cursor; 4213 int select_start; 4214 int select_end; 4215 unsigned char mode; 4216 unsigned char cursor_at_end_of_line; 4217 unsigned char initialized; 4218 unsigned char has_preferred_x; 4219 unsigned char single_line; 4220 unsigned char active; 4221 unsigned char padding1; 4222 float preferred_x; 4223 struct nk_text_undo_state undo; 4224 }; 4225 4226 /* filter function */ 4227 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode); 4228 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode); 4229 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode); 4230 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode); 4231 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode); 4232 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode); 4233 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode); 4234 4235 /* text editor */ 4236 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4237 NK_API void nk_textedit_init_default(struct nk_text_edit*); 4238 #endif 4239 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size); 4240 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size); 4241 NK_API void nk_textedit_free(struct nk_text_edit*); 4242 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len); 4243 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len); 4244 NK_API void nk_textedit_delete_selection(struct nk_text_edit*); 4245 NK_API void nk_textedit_select_all(struct nk_text_edit*); 4246 NK_API int nk_textedit_cut(struct nk_text_edit*); 4247 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len); 4248 NK_API void nk_textedit_undo(struct nk_text_edit*); 4249 NK_API void nk_textedit_redo(struct nk_text_edit*); 4250 4251 /* =============================================================== 4252 * 4253 * DRAWING 4254 * 4255 * ===============================================================*/ 4256 /* This library was designed to be render backend agnostic so it does 4257 not draw anything to screen. Instead all drawn shapes, widgets 4258 are made of, are buffered into memory and make up a command queue. 4259 Each frame therefore fills the command buffer with draw commands 4260 that then need to be executed by the user and his own render backend. 4261 After that the command buffer needs to be cleared and a new frame can be 4262 started. It is probably important to note that the command buffer is the main 4263 drawing API and the optional vertex buffer API only takes this format and 4264 converts it into a hardware accessible format. 4265 4266 To use the command queue to draw your own widgets you can access the 4267 command buffer of each window by calling `nk_window_get_canvas` after 4268 previously having called `nk_begin`: 4269 4270 void draw_red_rectangle_widget(struct nk_context *ctx) 4271 { 4272 struct nk_command_buffer *canvas; 4273 struct nk_input *input = &ctx->input; 4274 canvas = nk_window_get_canvas(ctx); 4275 4276 struct nk_rect space; 4277 enum nk_widget_layout_states state; 4278 state = nk_widget(&space, ctx); 4279 if (!state) return; 4280 4281 if (state != NK_WIDGET_ROM) 4282 update_your_widget_by_user_input(...); 4283 nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0)); 4284 } 4285 4286 if (nk_begin(...)) { 4287 nk_layout_row_dynamic(ctx, 25, 1); 4288 draw_red_rectangle_widget(ctx); 4289 } 4290 nk_end(..) 4291 4292 Important to know if you want to create your own widgets is the `nk_widget` 4293 call. It allocates space on the panel reserved for this widget to be used, 4294 but also returns the state of the widget space. If your widget is not seen and does 4295 not have to be updated it is '0' and you can just return. If it only has 4296 to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both 4297 update and draw your widget. The reason for separating is to only draw and 4298 update what is actually necessary which is crucial for performance. 4299 */ 4300 enum nk_command_type { 4301 NK_COMMAND_NOP, 4302 NK_COMMAND_SCISSOR, 4303 NK_COMMAND_LINE, 4304 NK_COMMAND_CURVE, 4305 NK_COMMAND_RECT, 4306 NK_COMMAND_RECT_FILLED, 4307 NK_COMMAND_RECT_MULTI_COLOR, 4308 NK_COMMAND_CIRCLE, 4309 NK_COMMAND_CIRCLE_FILLED, 4310 NK_COMMAND_ARC, 4311 NK_COMMAND_ARC_FILLED, 4312 NK_COMMAND_TRIANGLE, 4313 NK_COMMAND_TRIANGLE_FILLED, 4314 NK_COMMAND_POLYGON, 4315 NK_COMMAND_POLYGON_FILLED, 4316 NK_COMMAND_POLYLINE, 4317 NK_COMMAND_TEXT, 4318 NK_COMMAND_IMAGE, 4319 NK_COMMAND_CUSTOM 4320 }; 4321 4322 /* command base and header of every command inside the buffer */ 4323 struct nk_command { 4324 enum nk_command_type type; 4325 nk_size next; 4326 #ifdef NK_INCLUDE_COMMAND_USERDATA 4327 nk_handle userdata; 4328 #endif 4329 }; 4330 4331 struct nk_command_scissor { 4332 struct nk_command header; 4333 short x, y; 4334 unsigned short w, h; 4335 }; 4336 4337 struct nk_command_line { 4338 struct nk_command header; 4339 unsigned short line_thickness; 4340 struct nk_vec2i begin; 4341 struct nk_vec2i end; 4342 struct nk_color color; 4343 }; 4344 4345 struct nk_command_curve { 4346 struct nk_command header; 4347 unsigned short line_thickness; 4348 struct nk_vec2i begin; 4349 struct nk_vec2i end; 4350 struct nk_vec2i ctrl[2]; 4351 struct nk_color color; 4352 }; 4353 4354 struct nk_command_rect { 4355 struct nk_command header; 4356 unsigned short rounding; 4357 unsigned short line_thickness; 4358 short x, y; 4359 unsigned short w, h; 4360 struct nk_color color; 4361 }; 4362 4363 struct nk_command_rect_filled { 4364 struct nk_command header; 4365 unsigned short rounding; 4366 short x, y; 4367 unsigned short w, h; 4368 struct nk_color color; 4369 }; 4370 4371 struct nk_command_rect_multi_color { 4372 struct nk_command header; 4373 short x, y; 4374 unsigned short w, h; 4375 struct nk_color left; 4376 struct nk_color top; 4377 struct nk_color bottom; 4378 struct nk_color right; 4379 }; 4380 4381 struct nk_command_triangle { 4382 struct nk_command header; 4383 unsigned short line_thickness; 4384 struct nk_vec2i a; 4385 struct nk_vec2i b; 4386 struct nk_vec2i c; 4387 struct nk_color color; 4388 }; 4389 4390 struct nk_command_triangle_filled { 4391 struct nk_command header; 4392 struct nk_vec2i a; 4393 struct nk_vec2i b; 4394 struct nk_vec2i c; 4395 struct nk_color color; 4396 }; 4397 4398 struct nk_command_circle { 4399 struct nk_command header; 4400 short x, y; 4401 unsigned short line_thickness; 4402 unsigned short w, h; 4403 struct nk_color color; 4404 }; 4405 4406 struct nk_command_circle_filled { 4407 struct nk_command header; 4408 short x, y; 4409 unsigned short w, h; 4410 struct nk_color color; 4411 }; 4412 4413 struct nk_command_arc { 4414 struct nk_command header; 4415 short cx, cy; 4416 unsigned short r; 4417 unsigned short line_thickness; 4418 float a[2]; 4419 struct nk_color color; 4420 }; 4421 4422 struct nk_command_arc_filled { 4423 struct nk_command header; 4424 short cx, cy; 4425 unsigned short r; 4426 float a[2]; 4427 struct nk_color color; 4428 }; 4429 4430 struct nk_command_polygon { 4431 struct nk_command header; 4432 struct nk_color color; 4433 unsigned short line_thickness; 4434 unsigned short point_count; 4435 struct nk_vec2i points[1]; 4436 }; 4437 4438 struct nk_command_polygon_filled { 4439 struct nk_command header; 4440 struct nk_color color; 4441 unsigned short point_count; 4442 struct nk_vec2i points[1]; 4443 }; 4444 4445 struct nk_command_polyline { 4446 struct nk_command header; 4447 struct nk_color color; 4448 unsigned short line_thickness; 4449 unsigned short point_count; 4450 struct nk_vec2i points[1]; 4451 }; 4452 4453 struct nk_command_image { 4454 struct nk_command header; 4455 short x, y; 4456 unsigned short w, h; 4457 struct nk_image img; 4458 struct nk_color col; 4459 }; 4460 4461 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y, 4462 unsigned short w, unsigned short h, nk_handle callback_data); 4463 struct nk_command_custom { 4464 struct nk_command header; 4465 short x, y; 4466 unsigned short w, h; 4467 nk_handle callback_data; 4468 nk_command_custom_callback callback; 4469 }; 4470 4471 struct nk_command_text { 4472 struct nk_command header; 4473 const struct nk_user_font *font; 4474 struct nk_color background; 4475 struct nk_color foreground; 4476 short x, y; 4477 unsigned short w, h; 4478 float height; 4479 int length; 4480 char string[1]; 4481 }; 4482 4483 enum nk_command_clipping { 4484 NK_CLIPPING_OFF = nk_false, 4485 NK_CLIPPING_ON = nk_true 4486 }; 4487 4488 struct nk_command_buffer { 4489 struct nk_buffer *base; 4490 struct nk_rect clip; 4491 int use_clipping; 4492 nk_handle userdata; 4493 nk_size begin, end, last; 4494 }; 4495 4496 /* shape outlines */ 4497 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color); 4498 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color); 4499 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color); 4500 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color); 4501 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color); 4502 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color); 4503 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col); 4504 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color); 4505 4506 /* filled shades */ 4507 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color); 4508 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom); 4509 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color); 4510 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color); 4511 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color); 4512 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color); 4513 4514 /* misc */ 4515 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color); 4516 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color); 4517 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect); 4518 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr); 4519 4520 /* =============================================================== 4521 * 4522 * INPUT 4523 * 4524 * ===============================================================*/ 4525 struct nk_mouse_button { 4526 int down; 4527 unsigned int clicked; 4528 struct nk_vec2 clicked_pos; 4529 }; 4530 struct nk_mouse { 4531 struct nk_mouse_button buttons[NK_BUTTON_MAX]; 4532 struct nk_vec2 pos; 4533 struct nk_vec2 prev; 4534 struct nk_vec2 delta; 4535 struct nk_vec2 scroll_delta; 4536 unsigned char grab; 4537 unsigned char grabbed; 4538 unsigned char ungrab; 4539 }; 4540 4541 struct nk_key { 4542 int down; 4543 unsigned int clicked; 4544 }; 4545 struct nk_keyboard { 4546 struct nk_key keys[NK_KEY_MAX]; 4547 char text[NK_INPUT_MAX]; 4548 int text_len; 4549 }; 4550 4551 struct nk_input { 4552 struct nk_keyboard keyboard; 4553 struct nk_mouse mouse; 4554 }; 4555 4556 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons); 4557 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4558 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down); 4559 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4560 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down); 4561 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect); 4562 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect); 4563 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect); 4564 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect); 4565 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons); 4566 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons); 4567 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons); 4568 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys); 4569 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys); 4570 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys); 4571 4572 /* =============================================================== 4573 * 4574 * DRAW LIST 4575 * 4576 * ===============================================================*/ 4577 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 4578 /* The optional vertex buffer draw list provides a 2D drawing context 4579 with antialiasing functionality which takes basic filled or outlined shapes 4580 or a path and outputs vertexes, elements and draw commands. 4581 The actual draw list API is not required to be used directly while using this 4582 library since converting the default library draw command output is done by 4583 just calling `nk_convert` but I decided to still make this library accessible 4584 since it can be useful. 4585 4586 The draw list is based on a path buffering and polygon and polyline 4587 rendering API which allows a lot of ways to draw 2D content to screen. 4588 In fact it is probably more powerful than needed but allows even more crazy 4589 things than this library provides by default. 4590 */ 4591 typedef nk_ushort nk_draw_index; 4592 enum nk_draw_list_stroke { 4593 NK_STROKE_OPEN = nk_false, 4594 /* build up path has no connection back to the beginning */ 4595 NK_STROKE_CLOSED = nk_true 4596 /* build up path has a connection back to the beginning */ 4597 }; 4598 4599 enum nk_draw_vertex_layout_attribute { 4600 NK_VERTEX_POSITION, 4601 NK_VERTEX_COLOR, 4602 NK_VERTEX_TEXCOORD, 4603 NK_VERTEX_ATTRIBUTE_COUNT 4604 }; 4605 4606 enum nk_draw_vertex_layout_format { 4607 NK_FORMAT_SCHAR, 4608 NK_FORMAT_SSHORT, 4609 NK_FORMAT_SINT, 4610 NK_FORMAT_UCHAR, 4611 NK_FORMAT_USHORT, 4612 NK_FORMAT_UINT, 4613 NK_FORMAT_FLOAT, 4614 NK_FORMAT_DOUBLE, 4615 4616 NK_FORMAT_COLOR_BEGIN, 4617 NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN, 4618 NK_FORMAT_R16G15B16, 4619 NK_FORMAT_R32G32B32, 4620 4621 NK_FORMAT_R8G8B8A8, 4622 NK_FORMAT_B8G8R8A8, 4623 NK_FORMAT_R16G15B16A16, 4624 NK_FORMAT_R32G32B32A32, 4625 NK_FORMAT_R32G32B32A32_FLOAT, 4626 NK_FORMAT_R32G32B32A32_DOUBLE, 4627 4628 NK_FORMAT_RGB32, 4629 NK_FORMAT_RGBA32, 4630 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32, 4631 NK_FORMAT_COUNT 4632 }; 4633 4634 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0 4635 struct nk_draw_vertex_layout_element { 4636 enum nk_draw_vertex_layout_attribute attribute; 4637 enum nk_draw_vertex_layout_format format; 4638 nk_size offset; 4639 }; 4640 4641 struct nk_draw_command { 4642 unsigned int elem_count; 4643 /* number of elements in the current draw batch */ 4644 struct nk_rect clip_rect; 4645 /* current screen clipping rectangle */ 4646 nk_handle texture; 4647 /* current texture to set */ 4648 #ifdef NK_INCLUDE_COMMAND_USERDATA 4649 nk_handle userdata; 4650 #endif 4651 }; 4652 4653 struct nk_draw_list { 4654 struct nk_rect clip_rect; 4655 struct nk_vec2 circle_vtx[12]; 4656 struct nk_convert_config config; 4657 4658 struct nk_buffer *buffer; 4659 struct nk_buffer *vertices; 4660 struct nk_buffer *elements; 4661 4662 unsigned int element_count; 4663 unsigned int vertex_count; 4664 unsigned int cmd_count; 4665 nk_size cmd_offset; 4666 4667 unsigned int path_count; 4668 unsigned int path_offset; 4669 4670 enum nk_anti_aliasing line_AA; 4671 enum nk_anti_aliasing shape_AA; 4672 4673 #ifdef NK_INCLUDE_COMMAND_USERDATA 4674 nk_handle userdata; 4675 #endif 4676 }; 4677 4678 /* draw list */ 4679 NK_API void nk_draw_list_init(struct nk_draw_list*); 4680 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa); 4681 4682 /* drawing */ 4683 #define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can)) 4684 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*); 4685 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*); 4686 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*); 4687 4688 /* path */ 4689 NK_API void nk_draw_list_path_clear(struct nk_draw_list*); 4690 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos); 4691 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max); 4692 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments); 4693 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding); 4694 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments); 4695 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color); 4696 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness); 4697 4698 /* stroke */ 4699 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness); 4700 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness); 4701 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness); 4702 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness); 4703 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness); 4704 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing); 4705 4706 /* fill */ 4707 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding); 4708 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom); 4709 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color); 4710 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs); 4711 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing); 4712 4713 /* misc */ 4714 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color); 4715 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color); 4716 #ifdef NK_INCLUDE_COMMAND_USERDATA 4717 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata); 4718 #endif 4719 4720 #endif 4721 4722 /* =============================================================== 4723 * 4724 * GUI 4725 * 4726 * ===============================================================*/ 4727 enum nk_style_item_type { 4728 NK_STYLE_ITEM_COLOR, 4729 NK_STYLE_ITEM_IMAGE 4730 }; 4731 4732 union nk_style_item_data { 4733 struct nk_image image; 4734 struct nk_color color; 4735 }; 4736 4737 struct nk_style_item { 4738 enum nk_style_item_type type; 4739 union nk_style_item_data data; 4740 }; 4741 4742 struct nk_style_text { 4743 struct nk_color color; 4744 struct nk_vec2 padding; 4745 }; 4746 4747 struct nk_style_button { 4748 /* background */ 4749 struct nk_style_item normal; 4750 struct nk_style_item hover; 4751 struct nk_style_item active; 4752 struct nk_color border_color; 4753 4754 /* text */ 4755 struct nk_color text_background; 4756 struct nk_color text_normal; 4757 struct nk_color text_hover; 4758 struct nk_color text_active; 4759 nk_flags text_alignment; 4760 4761 /* properties */ 4762 float border; 4763 float rounding; 4764 struct nk_vec2 padding; 4765 struct nk_vec2 image_padding; 4766 struct nk_vec2 touch_padding; 4767 4768 /* optional user callbacks */ 4769 nk_handle userdata; 4770 void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata); 4771 void(*draw_end)(struct nk_command_buffer*, nk_handle userdata); 4772 }; 4773 4774 struct nk_style_toggle { 4775 /* background */ 4776 struct nk_style_item normal; 4777 struct nk_style_item hover; 4778 struct nk_style_item active; 4779 struct nk_color border_color; 4780 4781 /* cursor */ 4782 struct nk_style_item cursor_normal; 4783 struct nk_style_item cursor_hover; 4784 4785 /* text */ 4786 struct nk_color text_normal; 4787 struct nk_color text_hover; 4788 struct nk_color text_active; 4789 struct nk_color text_background; 4790 nk_flags text_alignment; 4791 4792 /* properties */ 4793 struct nk_vec2 padding; 4794 struct nk_vec2 touch_padding; 4795 float spacing; 4796 float border; 4797 4798 /* optional user callbacks */ 4799 nk_handle userdata; 4800 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4801 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4802 }; 4803 4804 struct nk_style_selectable { 4805 /* background (inactive) */ 4806 struct nk_style_item normal; 4807 struct nk_style_item hover; 4808 struct nk_style_item pressed; 4809 4810 /* background (active) */ 4811 struct nk_style_item normal_active; 4812 struct nk_style_item hover_active; 4813 struct nk_style_item pressed_active; 4814 4815 /* text color (inactive) */ 4816 struct nk_color text_normal; 4817 struct nk_color text_hover; 4818 struct nk_color text_pressed; 4819 4820 /* text color (active) */ 4821 struct nk_color text_normal_active; 4822 struct nk_color text_hover_active; 4823 struct nk_color text_pressed_active; 4824 struct nk_color text_background; 4825 nk_flags text_alignment; 4826 4827 /* properties */ 4828 float rounding; 4829 struct nk_vec2 padding; 4830 struct nk_vec2 touch_padding; 4831 struct nk_vec2 image_padding; 4832 4833 /* optional user callbacks */ 4834 nk_handle userdata; 4835 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4836 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4837 }; 4838 4839 struct nk_style_slider { 4840 /* background */ 4841 struct nk_style_item normal; 4842 struct nk_style_item hover; 4843 struct nk_style_item active; 4844 struct nk_color border_color; 4845 4846 /* background bar */ 4847 struct nk_color bar_normal; 4848 struct nk_color bar_hover; 4849 struct nk_color bar_active; 4850 struct nk_color bar_filled; 4851 4852 /* cursor */ 4853 struct nk_style_item cursor_normal; 4854 struct nk_style_item cursor_hover; 4855 struct nk_style_item cursor_active; 4856 4857 /* properties */ 4858 float border; 4859 float rounding; 4860 float bar_height; 4861 struct nk_vec2 padding; 4862 struct nk_vec2 spacing; 4863 struct nk_vec2 cursor_size; 4864 4865 /* optional buttons */ 4866 int show_buttons; 4867 struct nk_style_button inc_button; 4868 struct nk_style_button dec_button; 4869 enum nk_symbol_type inc_symbol; 4870 enum nk_symbol_type dec_symbol; 4871 4872 /* optional user callbacks */ 4873 nk_handle userdata; 4874 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4875 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4876 }; 4877 4878 struct nk_style_progress { 4879 /* background */ 4880 struct nk_style_item normal; 4881 struct nk_style_item hover; 4882 struct nk_style_item active; 4883 struct nk_color border_color; 4884 4885 /* cursor */ 4886 struct nk_style_item cursor_normal; 4887 struct nk_style_item cursor_hover; 4888 struct nk_style_item cursor_active; 4889 struct nk_color cursor_border_color; 4890 4891 /* properties */ 4892 float rounding; 4893 float border; 4894 float cursor_border; 4895 float cursor_rounding; 4896 struct nk_vec2 padding; 4897 4898 /* optional user callbacks */ 4899 nk_handle userdata; 4900 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4901 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4902 }; 4903 4904 struct nk_style_scrollbar { 4905 /* background */ 4906 struct nk_style_item normal; 4907 struct nk_style_item hover; 4908 struct nk_style_item active; 4909 struct nk_color border_color; 4910 4911 /* cursor */ 4912 struct nk_style_item cursor_normal; 4913 struct nk_style_item cursor_hover; 4914 struct nk_style_item cursor_active; 4915 struct nk_color cursor_border_color; 4916 4917 /* properties */ 4918 float border; 4919 float rounding; 4920 float border_cursor; 4921 float rounding_cursor; 4922 struct nk_vec2 padding; 4923 4924 /* optional buttons */ 4925 int show_buttons; 4926 struct nk_style_button inc_button; 4927 struct nk_style_button dec_button; 4928 enum nk_symbol_type inc_symbol; 4929 enum nk_symbol_type dec_symbol; 4930 4931 /* optional user callbacks */ 4932 nk_handle userdata; 4933 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4934 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4935 }; 4936 4937 struct nk_style_edit { 4938 /* background */ 4939 struct nk_style_item normal; 4940 struct nk_style_item hover; 4941 struct nk_style_item active; 4942 struct nk_color border_color; 4943 struct nk_style_scrollbar scrollbar; 4944 4945 /* cursor */ 4946 struct nk_color cursor_normal; 4947 struct nk_color cursor_hover; 4948 struct nk_color cursor_text_normal; 4949 struct nk_color cursor_text_hover; 4950 4951 /* text (unselected) */ 4952 struct nk_color text_normal; 4953 struct nk_color text_hover; 4954 struct nk_color text_active; 4955 4956 /* text (selected) */ 4957 struct nk_color selected_normal; 4958 struct nk_color selected_hover; 4959 struct nk_color selected_text_normal; 4960 struct nk_color selected_text_hover; 4961 4962 /* properties */ 4963 float border; 4964 float rounding; 4965 float cursor_size; 4966 struct nk_vec2 scrollbar_size; 4967 struct nk_vec2 padding; 4968 float row_padding; 4969 }; 4970 4971 struct nk_style_property { 4972 /* background */ 4973 struct nk_style_item normal; 4974 struct nk_style_item hover; 4975 struct nk_style_item active; 4976 struct nk_color border_color; 4977 4978 /* text */ 4979 struct nk_color label_normal; 4980 struct nk_color label_hover; 4981 struct nk_color label_active; 4982 4983 /* symbols */ 4984 enum nk_symbol_type sym_left; 4985 enum nk_symbol_type sym_right; 4986 4987 /* properties */ 4988 float border; 4989 float rounding; 4990 struct nk_vec2 padding; 4991 4992 struct nk_style_edit edit; 4993 struct nk_style_button inc_button; 4994 struct nk_style_button dec_button; 4995 4996 /* optional user callbacks */ 4997 nk_handle userdata; 4998 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4999 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5000 }; 5001 5002 struct nk_style_chart { 5003 /* colors */ 5004 struct nk_style_item background; 5005 struct nk_color border_color; 5006 struct nk_color selected_color; 5007 struct nk_color color; 5008 5009 /* properties */ 5010 float border; 5011 float rounding; 5012 struct nk_vec2 padding; 5013 }; 5014 5015 struct nk_style_combo { 5016 /* background */ 5017 struct nk_style_item normal; 5018 struct nk_style_item hover; 5019 struct nk_style_item active; 5020 struct nk_color border_color; 5021 5022 /* label */ 5023 struct nk_color label_normal; 5024 struct nk_color label_hover; 5025 struct nk_color label_active; 5026 5027 /* symbol */ 5028 struct nk_color symbol_normal; 5029 struct nk_color symbol_hover; 5030 struct nk_color symbol_active; 5031 5032 /* button */ 5033 struct nk_style_button button; 5034 enum nk_symbol_type sym_normal; 5035 enum nk_symbol_type sym_hover; 5036 enum nk_symbol_type sym_active; 5037 5038 /* properties */ 5039 float border; 5040 float rounding; 5041 struct nk_vec2 content_padding; 5042 struct nk_vec2 button_padding; 5043 struct nk_vec2 spacing; 5044 }; 5045 5046 struct nk_style_tab { 5047 /* background */ 5048 struct nk_style_item background; 5049 struct nk_color border_color; 5050 struct nk_color text; 5051 5052 /* button */ 5053 struct nk_style_button tab_maximize_button; 5054 struct nk_style_button tab_minimize_button; 5055 struct nk_style_button node_maximize_button; 5056 struct nk_style_button node_minimize_button; 5057 enum nk_symbol_type sym_minimize; 5058 enum nk_symbol_type sym_maximize; 5059 5060 /* properties */ 5061 float border; 5062 float rounding; 5063 float indent; 5064 struct nk_vec2 padding; 5065 struct nk_vec2 spacing; 5066 }; 5067 5068 enum nk_style_header_align { 5069 NK_HEADER_LEFT, 5070 NK_HEADER_RIGHT 5071 }; 5072 struct nk_style_window_header { 5073 /* background */ 5074 struct nk_style_item normal; 5075 struct nk_style_item hover; 5076 struct nk_style_item active; 5077 5078 /* button */ 5079 struct nk_style_button close_button; 5080 struct nk_style_button minimize_button; 5081 enum nk_symbol_type close_symbol; 5082 enum nk_symbol_type minimize_symbol; 5083 enum nk_symbol_type maximize_symbol; 5084 5085 /* title */ 5086 struct nk_color label_normal; 5087 struct nk_color label_hover; 5088 struct nk_color label_active; 5089 5090 /* properties */ 5091 enum nk_style_header_align align; 5092 struct nk_vec2 padding; 5093 struct nk_vec2 label_padding; 5094 struct nk_vec2 spacing; 5095 }; 5096 5097 struct nk_style_window { 5098 struct nk_style_window_header header; 5099 struct nk_style_item fixed_background; 5100 struct nk_color background; 5101 5102 struct nk_color border_color; 5103 struct nk_color popup_border_color; 5104 struct nk_color combo_border_color; 5105 struct nk_color contextual_border_color; 5106 struct nk_color menu_border_color; 5107 struct nk_color group_border_color; 5108 struct nk_color tooltip_border_color; 5109 struct nk_style_item scaler; 5110 5111 float border; 5112 float combo_border; 5113 float contextual_border; 5114 float menu_border; 5115 float group_border; 5116 float tooltip_border; 5117 float popup_border; 5118 float min_row_height_padding; 5119 5120 float rounding; 5121 struct nk_vec2 spacing; 5122 struct nk_vec2 scrollbar_size; 5123 struct nk_vec2 min_size; 5124 5125 struct nk_vec2 padding; 5126 struct nk_vec2 group_padding; 5127 struct nk_vec2 popup_padding; 5128 struct nk_vec2 combo_padding; 5129 struct nk_vec2 contextual_padding; 5130 struct nk_vec2 menu_padding; 5131 struct nk_vec2 tooltip_padding; 5132 }; 5133 5134 struct nk_style { 5135 const struct nk_user_font *font; 5136 const struct nk_cursor *cursors[NK_CURSOR_COUNT]; 5137 const struct nk_cursor *cursor_active; 5138 struct nk_cursor *cursor_last; 5139 int cursor_visible; 5140 5141 struct nk_style_text text; 5142 struct nk_style_button button; 5143 struct nk_style_button contextual_button; 5144 struct nk_style_button menu_button; 5145 struct nk_style_toggle option; 5146 struct nk_style_toggle checkbox; 5147 struct nk_style_selectable selectable; 5148 struct nk_style_slider slider; 5149 struct nk_style_progress progress; 5150 struct nk_style_property property; 5151 struct nk_style_edit edit; 5152 struct nk_style_chart chart; 5153 struct nk_style_scrollbar scrollh; 5154 struct nk_style_scrollbar scrollv; 5155 struct nk_style_tab tab; 5156 struct nk_style_combo combo; 5157 struct nk_style_window window; 5158 }; 5159 5160 NK_API struct nk_style_item nk_style_item_image(struct nk_image img); 5161 NK_API struct nk_style_item nk_style_item_color(struct nk_color); 5162 NK_API struct nk_style_item nk_style_item_hide(void); 5163 5164 /*============================================================== 5165 * PANEL 5166 * =============================================================*/ 5167 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 5168 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16 5169 #endif 5170 #ifndef NK_CHART_MAX_SLOT 5171 #define NK_CHART_MAX_SLOT 4 5172 #endif 5173 5174 enum nk_panel_type { 5175 NK_PANEL_NONE = 0, 5176 NK_PANEL_WINDOW = NK_FLAG(0), 5177 NK_PANEL_GROUP = NK_FLAG(1), 5178 NK_PANEL_POPUP = NK_FLAG(2), 5179 NK_PANEL_CONTEXTUAL = NK_FLAG(4), 5180 NK_PANEL_COMBO = NK_FLAG(5), 5181 NK_PANEL_MENU = NK_FLAG(6), 5182 NK_PANEL_TOOLTIP = NK_FLAG(7) 5183 }; 5184 enum nk_panel_set { 5185 NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP, 5186 NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP, 5187 NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP 5188 }; 5189 5190 struct nk_chart_slot { 5191 enum nk_chart_type type; 5192 struct nk_color color; 5193 struct nk_color highlight; 5194 float min, max, range; 5195 int count; 5196 struct nk_vec2 last; 5197 int index; 5198 }; 5199 5200 struct nk_chart { 5201 int slot; 5202 float x, y, w, h; 5203 struct nk_chart_slot slots[NK_CHART_MAX_SLOT]; 5204 }; 5205 5206 enum nk_panel_row_layout_type { 5207 NK_LAYOUT_DYNAMIC_FIXED = 0, 5208 NK_LAYOUT_DYNAMIC_ROW, 5209 NK_LAYOUT_DYNAMIC_FREE, 5210 NK_LAYOUT_DYNAMIC, 5211 NK_LAYOUT_STATIC_FIXED, 5212 NK_LAYOUT_STATIC_ROW, 5213 NK_LAYOUT_STATIC_FREE, 5214 NK_LAYOUT_STATIC, 5215 NK_LAYOUT_TEMPLATE, 5216 NK_LAYOUT_COUNT 5217 }; 5218 struct nk_row_layout { 5219 enum nk_panel_row_layout_type type; 5220 int index; 5221 float height; 5222 float min_height; 5223 int columns; 5224 const float *ratio; 5225 float item_width; 5226 float item_height; 5227 float item_offset; 5228 float filled; 5229 struct nk_rect item; 5230 int tree_depth; 5231 float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]; 5232 }; 5233 5234 struct nk_popup_buffer { 5235 nk_size begin; 5236 nk_size parent; 5237 nk_size last; 5238 nk_size end; 5239 int active; 5240 }; 5241 5242 struct nk_menu_state { 5243 float x, y, w, h; 5244 struct nk_scroll offset; 5245 }; 5246 5247 struct nk_panel { 5248 enum nk_panel_type type; 5249 nk_flags flags; 5250 struct nk_rect bounds; 5251 nk_uint *offset_x; 5252 nk_uint *offset_y; 5253 float at_x, at_y, max_x; 5254 float footer_height; 5255 float header_height; 5256 float border; 5257 unsigned int has_scrolling; 5258 struct nk_rect clip; 5259 struct nk_menu_state menu; 5260 struct nk_row_layout row; 5261 struct nk_chart chart; 5262 struct nk_command_buffer *buffer; 5263 struct nk_panel *parent; 5264 }; 5265 5266 /*============================================================== 5267 * WINDOW 5268 * =============================================================*/ 5269 #ifndef NK_WINDOW_MAX_NAME 5270 #define NK_WINDOW_MAX_NAME 64 5271 #endif 5272 5273 struct nk_table; 5274 enum nk_window_flags { 5275 NK_WINDOW_PRIVATE = NK_FLAG(11), 5276 NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE, 5277 /* special window type growing up in height while being filled to a certain maximum height */ 5278 NK_WINDOW_ROM = NK_FLAG(12), 5279 /* sets window widgets into a read only mode and does not allow input changes */ 5280 NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT, 5281 /* prevents all interaction caused by input to either window or widgets inside */ 5282 NK_WINDOW_HIDDEN = NK_FLAG(13), 5283 /* Hides window and stops any window interaction and drawing */ 5284 NK_WINDOW_CLOSED = NK_FLAG(14), 5285 /* Directly closes and frees the window at the end of the frame */ 5286 NK_WINDOW_MINIMIZED = NK_FLAG(15), 5287 /* marks the window as minimized */ 5288 NK_WINDOW_REMOVE_ROM = NK_FLAG(16) 5289 /* Removes read only mode at the end of the window */ 5290 }; 5291 5292 struct nk_popup_state { 5293 struct nk_window *win; 5294 enum nk_panel_type type; 5295 struct nk_popup_buffer buf; 5296 nk_hash name; 5297 int active; 5298 unsigned combo_count; 5299 unsigned con_count, con_old; 5300 unsigned active_con; 5301 struct nk_rect header; 5302 }; 5303 5304 struct nk_edit_state { 5305 nk_hash name; 5306 unsigned int seq; 5307 unsigned int old; 5308 int active, prev; 5309 int cursor; 5310 int sel_start; 5311 int sel_end; 5312 struct nk_scroll scrollbar; 5313 unsigned char mode; 5314 unsigned char single_line; 5315 }; 5316 5317 struct nk_property_state { 5318 int active, prev; 5319 char buffer[NK_MAX_NUMBER_BUFFER]; 5320 int length; 5321 int cursor; 5322 int select_start; 5323 int select_end; 5324 nk_hash name; 5325 unsigned int seq; 5326 unsigned int old; 5327 int state; 5328 }; 5329 5330 struct nk_window { 5331 unsigned int seq; 5332 nk_hash name; 5333 char name_string[NK_WINDOW_MAX_NAME]; 5334 nk_flags flags; 5335 5336 struct nk_rect bounds; 5337 struct nk_scroll scrollbar; 5338 struct nk_command_buffer buffer; 5339 struct nk_panel *layout; 5340 float scrollbar_hiding_timer; 5341 5342 /* persistent widget state */ 5343 struct nk_property_state property; 5344 struct nk_popup_state popup; 5345 struct nk_edit_state edit; 5346 unsigned int scrolled; 5347 5348 struct nk_table *tables; 5349 unsigned int table_count; 5350 5351 /* window list hooks */ 5352 struct nk_window *next; 5353 struct nk_window *prev; 5354 struct nk_window *parent; 5355 }; 5356 5357 /*============================================================== 5358 * STACK 5359 * =============================================================*/ 5360 /* The style modifier stack can be used to temporarily change a 5361 * property inside `nk_style`. For example if you want a special 5362 * red button you can temporarily push the old button color onto a stack 5363 * draw the button with a red color and then you just pop the old color 5364 * back from the stack: 5365 * 5366 * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0))); 5367 * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0))); 5368 * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0))); 5369 * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2)); 5370 * 5371 * nk_button(...); 5372 * 5373 * nk_style_pop_style_item(ctx); 5374 * nk_style_pop_style_item(ctx); 5375 * nk_style_pop_style_item(ctx); 5376 * nk_style_pop_vec2(ctx); 5377 * 5378 * Nuklear has a stack for style_items, float properties, vector properties, 5379 * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack 5380 * which can be changed at compile time. 5381 */ 5382 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE 5383 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8 5384 #endif 5385 5386 #ifndef NK_FONT_STACK_SIZE 5387 #define NK_FONT_STACK_SIZE 8 5388 #endif 5389 5390 #ifndef NK_STYLE_ITEM_STACK_SIZE 5391 #define NK_STYLE_ITEM_STACK_SIZE 16 5392 #endif 5393 5394 #ifndef NK_FLOAT_STACK_SIZE 5395 #define NK_FLOAT_STACK_SIZE 32 5396 #endif 5397 5398 #ifndef NK_VECTOR_STACK_SIZE 5399 #define NK_VECTOR_STACK_SIZE 16 5400 #endif 5401 5402 #ifndef NK_FLAGS_STACK_SIZE 5403 #define NK_FLAGS_STACK_SIZE 32 5404 #endif 5405 5406 #ifndef NK_COLOR_STACK_SIZE 5407 #define NK_COLOR_STACK_SIZE 32 5408 #endif 5409 5410 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\ 5411 struct nk_config_stack_##name##_element {\ 5412 prefix##_##type *address;\ 5413 prefix##_##type old_value;\ 5414 } 5415 #define NK_CONFIG_STACK(type,size)\ 5416 struct nk_config_stack_##type {\ 5417 int head;\ 5418 struct nk_config_stack_##type##_element elements[size];\ 5419 } 5420 5421 #define nk_float float 5422 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item); 5423 NK_CONFIGURATION_STACK_TYPE(nk ,float, float); 5424 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2); 5425 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags); 5426 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color); 5427 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*); 5428 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior); 5429 5430 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE); 5431 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE); 5432 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE); 5433 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE); 5434 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE); 5435 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE); 5436 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE); 5437 5438 struct nk_configuration_stacks { 5439 struct nk_config_stack_style_item style_items; 5440 struct nk_config_stack_float floats; 5441 struct nk_config_stack_vec2 vectors; 5442 struct nk_config_stack_flags flags; 5443 struct nk_config_stack_color colors; 5444 struct nk_config_stack_user_font fonts; 5445 struct nk_config_stack_button_behavior button_behaviors; 5446 }; 5447 5448 /*============================================================== 5449 * CONTEXT 5450 * =============================================================*/ 5451 #define NK_VALUE_PAGE_CAPACITY \ 5452 (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2) 5453 5454 struct nk_table { 5455 unsigned int seq; 5456 unsigned int size; 5457 nk_hash keys[NK_VALUE_PAGE_CAPACITY]; 5458 nk_uint values[NK_VALUE_PAGE_CAPACITY]; 5459 struct nk_table *next, *prev; 5460 }; 5461 5462 union nk_page_data { 5463 struct nk_table tbl; 5464 struct nk_panel pan; 5465 struct nk_window win; 5466 }; 5467 5468 struct nk_page_element { 5469 union nk_page_data data; 5470 struct nk_page_element *next; 5471 struct nk_page_element *prev; 5472 }; 5473 5474 struct nk_page { 5475 unsigned int size; 5476 struct nk_page *next; 5477 struct nk_page_element win[1]; 5478 }; 5479 5480 struct nk_pool { 5481 struct nk_allocator alloc; 5482 enum nk_allocation_type type; 5483 unsigned int page_count; 5484 struct nk_page *pages; 5485 struct nk_page_element *freelist; 5486 unsigned capacity; 5487 nk_size size; 5488 nk_size cap; 5489 }; 5490 5491 struct nk_context { 5492 /* public: can be accessed freely */ 5493 struct nk_input input; 5494 struct nk_style style; 5495 struct nk_buffer memory; 5496 struct nk_clipboard clip; 5497 nk_flags last_widget_state; 5498 enum nk_button_behavior button_behavior; 5499 struct nk_configuration_stacks stacks; 5500 float delta_time_seconds; 5501 5502 /* private: 5503 should only be accessed if you 5504 know what you are doing */ 5505 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 5506 struct nk_draw_list draw_list; 5507 #endif 5508 #ifdef NK_INCLUDE_COMMAND_USERDATA 5509 nk_handle userdata; 5510 #endif 5511 /* text editor objects are quite big because of an internal 5512 * undo/redo stack. Therefore it does not make sense to have one for 5513 * each window for temporary use cases, so I only provide *one* instance 5514 * for all windows. This works because the content is cleared anyway */ 5515 struct nk_text_edit text_edit; 5516 /* draw buffer used for overlay drawing operation like cursor */ 5517 struct nk_command_buffer overlay; 5518 5519 /* windows */ 5520 int build; 5521 int use_pool; 5522 struct nk_pool pool; 5523 struct nk_window *begin; 5524 struct nk_window *end; 5525 struct nk_window *active; 5526 struct nk_window *current; 5527 struct nk_page_element *freelist; 5528 unsigned int count; 5529 unsigned int seq; 5530 }; 5531 5532 /* ============================================================== 5533 * MATH 5534 * =============================================================== */ 5535 #define NK_PI 3.141592654f 5536 #define NK_UTF_INVALID 0xFFFD 5537 #define NK_MAX_FLOAT_PRECISION 2 5538 5539 #define NK_UNUSED(x) ((void)(x)) 5540 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x))) 5541 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0]) 5542 #define NK_ABS(a) (((a) < 0) ? -(a) : (a)) 5543 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b)) 5544 #define NK_INBOX(px, py, x, y, w, h)\ 5545 (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h)) 5546 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \ 5547 (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0))) 5548 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\ 5549 (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh)) 5550 5551 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y) 5552 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y) 5553 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y) 5554 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t)) 5555 5556 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i)))) 5557 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i)))) 5558 #define nk_zero_struct(s) nk_zero(&s, sizeof(s)) 5559 5560 /* ============================================================== 5561 * ALIGNMENT 5562 * =============================================================== */ 5563 /* Pointer to Integer type conversion for pointer alignment */ 5564 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/ 5565 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x)) 5566 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x)) 5567 #elif !defined(__GNUC__) /* works for compilers other than LLVM */ 5568 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x]) 5569 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0)) 5570 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */ 5571 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) 5572 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x)) 5573 #else /* generates warning but works */ 5574 # define NK_UINT_TO_PTR(x) ((void*)(x)) 5575 # define NK_PTR_TO_UINT(x) ((nk_size)(x)) 5576 #endif 5577 5578 #define NK_ALIGN_PTR(x, mask)\ 5579 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1)))) 5580 #define NK_ALIGN_PTR_BACK(x, mask)\ 5581 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1)))) 5582 5583 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) 5584 #define NK_CONTAINER_OF(ptr,type,member)\ 5585 (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) 5586 5587 #ifdef __cplusplus 5588 } 5589 #endif 5590 5591 #ifdef __cplusplus 5592 template<typename T> struct nk_alignof; 5593 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};}; 5594 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};}; 5595 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum { 5596 diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};}; 5597 #define NK_ALIGNOF(t) (nk_alignof<t>::value) 5598 #elif defined(_MSC_VER) 5599 #define NK_ALIGNOF(t) (__alignof(t)) 5600 #else 5601 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) 5602 #endif 5603 5604 #endif /* NK_NUKLEAR_H_ */ 5605 5606 5607 #ifdef NK_IMPLEMENTATION 5608 5609 #ifndef NK_INTERNAL_H 5610 #define NK_INTERNAL_H 5611 5612 #ifndef NK_POOL_DEFAULT_CAPACITY 5613 #define NK_POOL_DEFAULT_CAPACITY 16 5614 #endif 5615 5616 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE 5617 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) 5618 #endif 5619 5620 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE 5621 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024) 5622 #endif 5623 5624 /* standard library headers */ 5625 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5626 #include <stdlib.h> /* malloc, free */ 5627 #endif 5628 #ifdef NK_INCLUDE_STANDARD_IO 5629 #include <stdio.h> /* fopen, fclose,... */ 5630 #endif 5631 #ifndef NK_ASSERT 5632 #include <assert.h> 5633 #define NK_ASSERT(expr) assert(expr) 5634 #endif 5635 5636 #ifndef NK_MEMSET 5637 #define NK_MEMSET nk_memset 5638 #endif 5639 #ifndef NK_MEMCPY 5640 #define NK_MEMCPY nk_memcopy 5641 #endif 5642 #ifndef NK_SQRT 5643 #define NK_SQRT nk_sqrt 5644 #endif 5645 #ifndef NK_SIN 5646 #define NK_SIN nk_sin 5647 #endif 5648 #ifndef NK_COS 5649 #define NK_COS nk_cos 5650 #endif 5651 #ifndef NK_STRTOD 5652 #define NK_STRTOD nk_strtod 5653 #endif 5654 #ifndef NK_DTOA 5655 #define NK_DTOA nk_dtoa 5656 #endif 5657 5658 #define NK_DEFAULT (-1) 5659 5660 #ifndef NK_VSNPRINTF 5661 /* If your compiler does support `vsnprintf` I would highly recommend 5662 * defining this to vsnprintf instead since `vsprintf` is basically 5663 * unbelievable unsafe and should *NEVER* be used. But I have to support 5664 * it since C89 only provides this unsafe version. */ 5665 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\ 5666 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 5667 (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\ 5668 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\ 5669 defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE) 5670 #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a) 5671 #else 5672 #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a) 5673 #endif 5674 #endif 5675 5676 #define NK_SCHAR_MIN (-127) 5677 #define NK_SCHAR_MAX 127 5678 #define NK_UCHAR_MIN 0 5679 #define NK_UCHAR_MAX 256 5680 #define NK_SSHORT_MIN (-32767) 5681 #define NK_SSHORT_MAX 32767 5682 #define NK_USHORT_MIN 0 5683 #define NK_USHORT_MAX 65535 5684 #define NK_SINT_MIN (-2147483647) 5685 #define NK_SINT_MAX 2147483647 5686 #define NK_UINT_MIN 0 5687 #define NK_UINT_MAX 4294967295u 5688 5689 /* Make sure correct type size: 5690 * This will fire with a negative subscript error if the type sizes 5691 * are set incorrectly by the compiler, and compile out if not */ 5692 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 5693 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*)); 5694 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 5695 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 5696 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 5697 NK_STATIC_ASSERT(sizeof(nk_short) == 2); 5698 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 5699 NK_STATIC_ASSERT(sizeof(nk_int) == 4); 5700 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 5701 5702 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384}; 5703 #define NK_FLOAT_PRECISION 0.00000000000001 5704 5705 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255}; 5706 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255}; 5707 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255}; 5708 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255}; 5709 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255}; 5710 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255}; 5711 5712 /* widget */ 5713 #define nk_widget_state_reset(s)\ 5714 if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\ 5715 (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\ 5716 else (*(s)) = NK_WIDGET_STATE_INACTIVE; 5717 5718 /* math */ 5719 NK_LIB float nk_inv_sqrt(float n); 5720 NK_LIB float nk_sqrt(float x); 5721 NK_LIB float nk_sin(float x); 5722 NK_LIB float nk_cos(float x); 5723 NK_LIB nk_uint nk_round_up_pow2(nk_uint v); 5724 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount); 5725 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad); 5726 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1); 5727 NK_LIB double nk_pow(double x, int n); 5728 NK_LIB int nk_ifloord(double x); 5729 NK_LIB int nk_ifloorf(float x); 5730 NK_LIB int nk_iceilf(float x); 5731 NK_LIB int nk_log10(double n); 5732 5733 /* util */ 5734 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE}; 5735 NK_LIB int nk_is_lower(int c); 5736 NK_LIB int nk_is_upper(int c); 5737 NK_LIB int nk_to_upper(int c); 5738 NK_LIB int nk_to_lower(int c); 5739 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); 5740 NK_LIB void nk_memset(void *ptr, int c0, nk_size size); 5741 NK_LIB void nk_zero(void *ptr, nk_size size); 5742 NK_LIB char *nk_itoa(char *s, long n); 5743 NK_LIB int nk_string_float_limit(char *string, int prec); 5744 NK_LIB char *nk_dtoa(char *s, double n); 5745 NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count); 5746 NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op); 5747 #ifdef NK_INCLUDE_STANDARD_VARARGS 5748 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args); 5749 #endif 5750 #ifdef NK_INCLUDE_STANDARD_IO 5751 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc); 5752 #endif 5753 5754 /* buffer */ 5755 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5756 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size); 5757 NK_LIB void nk_mfree(nk_handle unused, void *ptr); 5758 #endif 5759 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type); 5760 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align); 5761 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size); 5762 5763 /* draw */ 5764 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip); 5765 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b); 5766 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size); 5767 NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font); 5768 5769 /* buffering */ 5770 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5771 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win); 5772 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win); 5773 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*); 5774 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5775 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w); 5776 NK_LIB void nk_build(struct nk_context *ctx); 5777 5778 /* text editor */ 5779 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter); 5780 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5781 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5782 NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height); 5783 5784 /* window */ 5785 enum nk_window_insert_location { 5786 NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */ 5787 NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */ 5788 }; 5789 NK_LIB void *nk_create_window(struct nk_context *ctx); 5790 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*); 5791 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win); 5792 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name); 5793 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc); 5794 5795 /* pool */ 5796 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity); 5797 NK_LIB void nk_pool_free(struct nk_pool *pool); 5798 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size); 5799 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool); 5800 5801 /* page-element */ 5802 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx); 5803 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem); 5804 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem); 5805 5806 /* table */ 5807 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx); 5808 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl); 5809 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl); 5810 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl); 5811 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value); 5812 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name); 5813 5814 /* panel */ 5815 NK_LIB void *nk_create_panel(struct nk_context *ctx); 5816 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan); 5817 NK_LIB int nk_panel_has_header(nk_flags flags, const char *title); 5818 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type); 5819 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type); 5820 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type); 5821 NK_LIB int nk_panel_is_sub(enum nk_panel_type type); 5822 NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type); 5823 NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type); 5824 NK_LIB void nk_panel_end(struct nk_context *ctx); 5825 5826 /* layout */ 5827 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns); 5828 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols); 5829 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width); 5830 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win); 5831 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify); 5832 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx); 5833 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx); 5834 5835 /* popup */ 5836 NK_LIB int nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type); 5837 5838 /* text */ 5839 struct nk_text { 5840 struct nk_vec2 padding; 5841 struct nk_color background; 5842 struct nk_color text; 5843 }; 5844 NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f); 5845 NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f); 5846 5847 /* button */ 5848 NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior); 5849 NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style); 5850 NK_LIB int nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content); 5851 NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font); 5852 NK_LIB int nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font); 5853 NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font); 5854 NK_LIB int nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font); 5855 NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img); 5856 NK_LIB int nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in); 5857 NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font); 5858 NK_LIB int nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in); 5859 NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img); 5860 NK_LIB int nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in); 5861 5862 /* toggle */ 5863 enum nk_toggle_type { 5864 NK_TOGGLE_CHECK, 5865 NK_TOGGLE_OPTION 5866 }; 5867 NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active); 5868 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font); 5869 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, int active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font); 5870 NK_LIB int nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, int *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font); 5871 5872 /* progress */ 5873 NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable); 5874 NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max); 5875 NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, int modifiable, const struct nk_style_progress *style, struct nk_input *in); 5876 5877 /* slider */ 5878 NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps); 5879 NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max); 5880 NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font); 5881 5882 /* scrollbar */ 5883 NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o); 5884 NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll); 5885 NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font); 5886 NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font); 5887 5888 /* selectable */ 5889 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, int active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font); 5890 NK_LIB int nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font); 5891 NK_LIB int nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font); 5892 5893 /* edit */ 5894 NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, int is_selected); 5895 NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font); 5896 5897 /* color-picker */ 5898 NK_LIB int nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in); 5899 NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col); 5900 NK_LIB int nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font); 5901 5902 /* property */ 5903 enum nk_property_status { 5904 NK_PROPERTY_DEFAULT, 5905 NK_PROPERTY_EDIT, 5906 NK_PROPERTY_DRAG 5907 }; 5908 enum nk_property_filter { 5909 NK_FILTER_INT, 5910 NK_FILTER_FLOAT 5911 }; 5912 enum nk_property_kind { 5913 NK_PROPERTY_INT, 5914 NK_PROPERTY_FLOAT, 5915 NK_PROPERTY_DOUBLE 5916 }; 5917 union nk_property { 5918 int i; 5919 float f; 5920 double d; 5921 }; 5922 struct nk_property_variant { 5923 enum nk_property_kind kind; 5924 union nk_property value; 5925 union nk_property min_value; 5926 union nk_property max_value; 5927 union nk_property step; 5928 }; 5929 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step); 5930 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step); 5931 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step); 5932 5933 NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel); 5934 NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property, struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel); 5935 NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font); 5936 NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior); 5937 NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter); 5938 5939 #endif 5940 5941 5942 5943 5944 5945 /* =============================================================== 5946 * 5947 * MATH 5948 * 5949 * ===============================================================*/ 5950 /* Since nuklear is supposed to work on all systems providing floating point 5951 math without any dependencies I also had to implement my own math functions 5952 for sqrt, sin and cos. Since the actual highly accurate implementations for 5953 the standard library functions are quite complex and I do not need high 5954 precision for my use cases I use approximations. 5955 5956 Sqrt 5957 ---- 5958 For square root nuklear uses the famous fast inverse square root: 5959 https://en.wikipedia.org/wiki/Fast_inverse_square_root with 5960 slightly tweaked magic constant. While on today's hardware it is 5961 probably not faster it is still fast and accurate enough for 5962 nuklear's use cases. IMPORTANT: this requires float format IEEE 754 5963 5964 Sine/Cosine 5965 ----------- 5966 All constants inside both function are generated Remez's minimax 5967 approximations for value range 0...2*PI. The reason why I decided to 5968 approximate exactly that range is that nuklear only needs sine and 5969 cosine to generate circles which only requires that exact range. 5970 In addition I used Remez instead of Taylor for additional precision: 5971 www.lolengine.net/blog/2011/12/21/better-function-approximations. 5972 5973 The tool I used to generate constants for both sine and cosine 5974 (it can actually approximate a lot more functions) can be 5975 found here: www.lolengine.net/wiki/oss/lolremez 5976 */ 5977 NK_LIB float 5978 nk_inv_sqrt(float n) 5979 { 5980 float x2; 5981 const float threehalfs = 1.5f; 5982 union {nk_uint i; float f;} conv = {0}; 5983 conv.f = n; 5984 x2 = n * 0.5f; 5985 conv.i = 0x5f375A84 - (conv.i >> 1); 5986 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f)); 5987 return conv.f; 5988 } 5989 NK_LIB float 5990 nk_sqrt(float x) 5991 { 5992 return x * nk_inv_sqrt(x); 5993 } 5994 NK_LIB float 5995 nk_sin(float x) 5996 { 5997 NK_STORAGE const float a0 = +1.91059300966915117e-31f; 5998 NK_STORAGE const float a1 = +1.00086760103908896f; 5999 NK_STORAGE const float a2 = -1.21276126894734565e-2f; 6000 NK_STORAGE const float a3 = -1.38078780785773762e-1f; 6001 NK_STORAGE const float a4 = -2.67353392911981221e-2f; 6002 NK_STORAGE const float a5 = +2.08026600266304389e-2f; 6003 NK_STORAGE const float a6 = -3.03996055049204407e-3f; 6004 NK_STORAGE const float a7 = +1.38235642404333740e-4f; 6005 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); 6006 } 6007 NK_LIB float 6008 nk_cos(float x) 6009 { 6010 NK_STORAGE const float a0 = +1.00238601909309722f; 6011 NK_STORAGE const float a1 = -3.81919947353040024e-2f; 6012 NK_STORAGE const float a2 = -3.94382342128062756e-1f; 6013 NK_STORAGE const float a3 = -1.18134036025221444e-1f; 6014 NK_STORAGE const float a4 = +1.07123798512170878e-1f; 6015 NK_STORAGE const float a5 = -1.86637164165180873e-2f; 6016 NK_STORAGE const float a6 = +9.90140908664079833e-4f; 6017 NK_STORAGE const float a7 = -5.23022132118824778e-14f; 6018 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); 6019 } 6020 NK_LIB nk_uint 6021 nk_round_up_pow2(nk_uint v) 6022 { 6023 v--; 6024 v |= v >> 1; 6025 v |= v >> 2; 6026 v |= v >> 4; 6027 v |= v >> 8; 6028 v |= v >> 16; 6029 v++; 6030 return v; 6031 } 6032 NK_LIB double 6033 nk_pow(double x, int n) 6034 { 6035 /* check the sign of n */ 6036 double r = 1; 6037 int plus = n >= 0; 6038 n = (plus) ? n : -n; 6039 while (n > 0) { 6040 if ((n & 1) == 1) 6041 r *= x; 6042 n /= 2; 6043 x *= x; 6044 } 6045 return plus ? r : 1.0 / r; 6046 } 6047 NK_LIB int 6048 nk_ifloord(double x) 6049 { 6050 x = (double)((int)x - ((x < 0.0) ? 1 : 0)); 6051 return (int)x; 6052 } 6053 NK_LIB int 6054 nk_ifloorf(float x) 6055 { 6056 x = (float)((int)x - ((x < 0.0f) ? 1 : 0)); 6057 return (int)x; 6058 } 6059 NK_LIB int 6060 nk_iceilf(float x) 6061 { 6062 if (x >= 0) { 6063 int i = (int)x; 6064 return (x > i) ? i+1: i; 6065 } else { 6066 int t = (int)x; 6067 float r = x - (float)t; 6068 return (r > 0.0f) ? t+1: t; 6069 } 6070 } 6071 NK_LIB int 6072 nk_log10(double n) 6073 { 6074 int neg; 6075 int ret; 6076 int exp = 0; 6077 6078 neg = (n < 0) ? 1 : 0; 6079 ret = (neg) ? (int)-n : (int)n; 6080 while ((ret / 10) > 0) { 6081 ret /= 10; 6082 exp++; 6083 } 6084 if (neg) exp = -exp; 6085 return exp; 6086 } 6087 NK_API struct nk_rect 6088 nk_get_null_rect(void) 6089 { 6090 return nk_null_rect; 6091 } 6092 NK_API struct nk_rect 6093 nk_rect(float x, float y, float w, float h) 6094 { 6095 struct nk_rect r; 6096 r.x = x; r.y = y; 6097 r.w = w; r.h = h; 6098 return r; 6099 } 6100 NK_API struct nk_rect 6101 nk_recti(int x, int y, int w, int h) 6102 { 6103 struct nk_rect r; 6104 r.x = (float)x; 6105 r.y = (float)y; 6106 r.w = (float)w; 6107 r.h = (float)h; 6108 return r; 6109 } 6110 NK_API struct nk_rect 6111 nk_recta(struct nk_vec2 pos, struct nk_vec2 size) 6112 { 6113 return nk_rect(pos.x, pos.y, size.x, size.y); 6114 } 6115 NK_API struct nk_rect 6116 nk_rectv(const float *r) 6117 { 6118 return nk_rect(r[0], r[1], r[2], r[3]); 6119 } 6120 NK_API struct nk_rect 6121 nk_rectiv(const int *r) 6122 { 6123 return nk_recti(r[0], r[1], r[2], r[3]); 6124 } 6125 NK_API struct nk_vec2 6126 nk_rect_pos(struct nk_rect r) 6127 { 6128 struct nk_vec2 ret; 6129 ret.x = r.x; ret.y = r.y; 6130 return ret; 6131 } 6132 NK_API struct nk_vec2 6133 nk_rect_size(struct nk_rect r) 6134 { 6135 struct nk_vec2 ret; 6136 ret.x = r.w; ret.y = r.h; 6137 return ret; 6138 } 6139 NK_LIB struct nk_rect 6140 nk_shrink_rect(struct nk_rect r, float amount) 6141 { 6142 struct nk_rect res; 6143 r.w = NK_MAX(r.w, 2 * amount); 6144 r.h = NK_MAX(r.h, 2 * amount); 6145 res.x = r.x + amount; 6146 res.y = r.y + amount; 6147 res.w = r.w - 2 * amount; 6148 res.h = r.h - 2 * amount; 6149 return res; 6150 } 6151 NK_LIB struct nk_rect 6152 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad) 6153 { 6154 r.w = NK_MAX(r.w, 2 * pad.x); 6155 r.h = NK_MAX(r.h, 2 * pad.y); 6156 r.x += pad.x; r.y += pad.y; 6157 r.w -= 2 * pad.x; 6158 r.h -= 2 * pad.y; 6159 return r; 6160 } 6161 NK_API struct nk_vec2 6162 nk_vec2(float x, float y) 6163 { 6164 struct nk_vec2 ret; 6165 ret.x = x; ret.y = y; 6166 return ret; 6167 } 6168 NK_API struct nk_vec2 6169 nk_vec2i(int x, int y) 6170 { 6171 struct nk_vec2 ret; 6172 ret.x = (float)x; 6173 ret.y = (float)y; 6174 return ret; 6175 } 6176 NK_API struct nk_vec2 6177 nk_vec2v(const float *v) 6178 { 6179 return nk_vec2(v[0], v[1]); 6180 } 6181 NK_API struct nk_vec2 6182 nk_vec2iv(const int *v) 6183 { 6184 return nk_vec2i(v[0], v[1]); 6185 } 6186 NK_LIB void 6187 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, 6188 float x1, float y1) 6189 { 6190 NK_ASSERT(a); 6191 NK_ASSERT(clip); 6192 clip->x = NK_MAX(a->x, x0); 6193 clip->y = NK_MAX(a->y, y0); 6194 clip->w = NK_MIN(a->x + a->w, x1) - clip->x; 6195 clip->h = NK_MIN(a->y + a->h, y1) - clip->y; 6196 clip->w = NK_MAX(0, clip->w); 6197 clip->h = NK_MAX(0, clip->h); 6198 } 6199 6200 NK_API void 6201 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, 6202 float pad_x, float pad_y, enum nk_heading direction) 6203 { 6204 float w_half, h_half; 6205 NK_ASSERT(result); 6206 6207 r.w = NK_MAX(2 * pad_x, r.w); 6208 r.h = NK_MAX(2 * pad_y, r.h); 6209 r.w = r.w - 2 * pad_x; 6210 r.h = r.h - 2 * pad_y; 6211 6212 r.x = r.x + pad_x; 6213 r.y = r.y + pad_y; 6214 6215 w_half = r.w / 2.0f; 6216 h_half = r.h / 2.0f; 6217 6218 if (direction == NK_UP) { 6219 result[0] = nk_vec2(r.x + w_half, r.y); 6220 result[1] = nk_vec2(r.x + r.w, r.y + r.h); 6221 result[2] = nk_vec2(r.x, r.y + r.h); 6222 } else if (direction == NK_RIGHT) { 6223 result[0] = nk_vec2(r.x, r.y); 6224 result[1] = nk_vec2(r.x + r.w, r.y + h_half); 6225 result[2] = nk_vec2(r.x, r.y + r.h); 6226 } else if (direction == NK_DOWN) { 6227 result[0] = nk_vec2(r.x, r.y); 6228 result[1] = nk_vec2(r.x + r.w, r.y); 6229 result[2] = nk_vec2(r.x + w_half, r.y + r.h); 6230 } else { 6231 result[0] = nk_vec2(r.x, r.y + h_half); 6232 result[1] = nk_vec2(r.x + r.w, r.y); 6233 result[2] = nk_vec2(r.x + r.w, r.y + r.h); 6234 } 6235 } 6236 6237 6238 6239 6240 6241 /* =============================================================== 6242 * 6243 * UTIL 6244 * 6245 * ===============================================================*/ 6246 NK_INTERN int nk_str_match_here(const char *regexp, const char *text); 6247 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text); 6248 NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);} 6249 NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);} 6250 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;} 6251 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;} 6252 6253 NK_LIB void* 6254 nk_memcopy(void *dst0, const void *src0, nk_size length) 6255 { 6256 nk_ptr t; 6257 char *dst = (char*)dst0; 6258 const char *src = (const char*)src0; 6259 if (length == 0 || dst == src) 6260 goto done; 6261 6262 #define nk_word int 6263 #define nk_wsize sizeof(nk_word) 6264 #define nk_wmask (nk_wsize-1) 6265 #define NK_TLOOP(s) if (t) NK_TLOOP1(s) 6266 #define NK_TLOOP1(s) do { s; } while (--t) 6267 6268 if (dst < src) { 6269 t = (nk_ptr)src; /* only need low bits */ 6270 if ((t | (nk_ptr)dst) & nk_wmask) { 6271 if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize) 6272 t = length; 6273 else 6274 t = nk_wsize - (t & nk_wmask); 6275 length -= t; 6276 NK_TLOOP1(*dst++ = *src++); 6277 } 6278 t = length / nk_wsize; 6279 NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src; 6280 src += nk_wsize; dst += nk_wsize); 6281 t = length & nk_wmask; 6282 NK_TLOOP(*dst++ = *src++); 6283 } else { 6284 src += length; 6285 dst += length; 6286 t = (nk_ptr)src; 6287 if ((t | (nk_ptr)dst) & nk_wmask) { 6288 if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize) 6289 t = length; 6290 else 6291 t &= nk_wmask; 6292 length -= t; 6293 NK_TLOOP1(*--dst = *--src); 6294 } 6295 t = length / nk_wsize; 6296 NK_TLOOP(src -= nk_wsize; dst -= nk_wsize; 6297 *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src); 6298 t = length & nk_wmask; 6299 NK_TLOOP(*--dst = *--src); 6300 } 6301 #undef nk_word 6302 #undef nk_wsize 6303 #undef nk_wmask 6304 #undef NK_TLOOP 6305 #undef NK_TLOOP1 6306 done: 6307 return (dst0); 6308 } 6309 NK_LIB void 6310 nk_memset(void *ptr, int c0, nk_size size) 6311 { 6312 #define nk_word unsigned 6313 #define nk_wsize sizeof(nk_word) 6314 #define nk_wmask (nk_wsize - 1) 6315 nk_byte *dst = (nk_byte*)ptr; 6316 unsigned c = 0; 6317 nk_size t = 0; 6318 6319 if ((c = (nk_byte)c0) != 0) { 6320 c = (c << 8) | c; /* at least 16-bits */ 6321 if (sizeof(unsigned int) > 2) 6322 c = (c << 16) | c; /* at least 32-bits*/ 6323 } 6324 6325 /* too small of a word count */ 6326 dst = (nk_byte*)ptr; 6327 if (size < 3 * nk_wsize) { 6328 while (size--) *dst++ = (nk_byte)c0; 6329 return; 6330 } 6331 6332 /* align destination */ 6333 if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) { 6334 t = nk_wsize -t; 6335 size -= t; 6336 do { 6337 *dst++ = (nk_byte)c0; 6338 } while (--t != 0); 6339 } 6340 6341 /* fill word */ 6342 t = size / nk_wsize; 6343 do { 6344 *(nk_word*)((void*)dst) = c; 6345 dst += nk_wsize; 6346 } while (--t != 0); 6347 6348 /* fill trailing bytes */ 6349 t = (size & nk_wmask); 6350 if (t != 0) { 6351 do { 6352 *dst++ = (nk_byte)c0; 6353 } while (--t != 0); 6354 } 6355 6356 #undef nk_word 6357 #undef nk_wsize 6358 #undef nk_wmask 6359 } 6360 NK_LIB void 6361 nk_zero(void *ptr, nk_size size) 6362 { 6363 NK_ASSERT(ptr); 6364 NK_MEMSET(ptr, 0, size); 6365 } 6366 NK_API int 6367 nk_strlen(const char *str) 6368 { 6369 int siz = 0; 6370 NK_ASSERT(str); 6371 while (str && *str++ != '\0') siz++; 6372 return siz; 6373 } 6374 NK_API int 6375 nk_strtoi(const char *str, const char **endptr) 6376 { 6377 int neg = 1; 6378 const char *p = str; 6379 int value = 0; 6380 6381 NK_ASSERT(str); 6382 if (!str) return 0; 6383 6384 /* skip whitespace */ 6385 while (*p == ' ') p++; 6386 if (*p == '-') { 6387 neg = -1; 6388 p++; 6389 } 6390 while (*p && *p >= '0' && *p <= '9') { 6391 value = value * 10 + (int) (*p - '0'); 6392 p++; 6393 } 6394 if (endptr) 6395 *endptr = p; 6396 return neg*value; 6397 } 6398 NK_API double 6399 nk_strtod(const char *str, const char **endptr) 6400 { 6401 double m; 6402 double neg = 1.0; 6403 const char *p = str; 6404 double value = 0; 6405 double number = 0; 6406 6407 NK_ASSERT(str); 6408 if (!str) return 0; 6409 6410 /* skip whitespace */ 6411 while (*p == ' ') p++; 6412 if (*p == '-') { 6413 neg = -1.0; 6414 p++; 6415 } 6416 6417 while (*p && *p != '.' && *p != 'e') { 6418 value = value * 10.0 + (double) (*p - '0'); 6419 p++; 6420 } 6421 6422 if (*p == '.') { 6423 p++; 6424 for(m = 0.1; *p && *p != 'e'; p++ ) { 6425 value = value + (double) (*p - '0') * m; 6426 m *= 0.1; 6427 } 6428 } 6429 if (*p == 'e') { 6430 int i, pow, div; 6431 p++; 6432 if (*p == '-') { 6433 div = nk_true; 6434 p++; 6435 } else if (*p == '+') { 6436 div = nk_false; 6437 p++; 6438 } else div = nk_false; 6439 6440 for (pow = 0; *p; p++) 6441 pow = pow * 10 + (int) (*p - '0'); 6442 6443 for (m = 1.0, i = 0; i < pow; i++) 6444 m *= 10.0; 6445 6446 if (div) 6447 value /= m; 6448 else value *= m; 6449 } 6450 number = value * neg; 6451 if (endptr) 6452 *endptr = p; 6453 return number; 6454 } 6455 NK_API float 6456 nk_strtof(const char *str, const char **endptr) 6457 { 6458 float float_value; 6459 double double_value; 6460 double_value = NK_STRTOD(str, endptr); 6461 float_value = (float)double_value; 6462 return float_value; 6463 } 6464 NK_API int 6465 nk_stricmp(const char *s1, const char *s2) 6466 { 6467 nk_int c1,c2,d; 6468 do { 6469 c1 = *s1++; 6470 c2 = *s2++; 6471 d = c1 - c2; 6472 while (d) { 6473 if (c1 <= 'Z' && c1 >= 'A') { 6474 d += ('a' - 'A'); 6475 if (!d) break; 6476 } 6477 if (c2 <= 'Z' && c2 >= 'A') { 6478 d -= ('a' - 'A'); 6479 if (!d) break; 6480 } 6481 return ((d >= 0) << 1) - 1; 6482 } 6483 } while (c1); 6484 return 0; 6485 } 6486 NK_API int 6487 nk_stricmpn(const char *s1, const char *s2, int n) 6488 { 6489 int c1,c2,d; 6490 NK_ASSERT(n >= 0); 6491 do { 6492 c1 = *s1++; 6493 c2 = *s2++; 6494 if (!n--) return 0; 6495 6496 d = c1 - c2; 6497 while (d) { 6498 if (c1 <= 'Z' && c1 >= 'A') { 6499 d += ('a' - 'A'); 6500 if (!d) break; 6501 } 6502 if (c2 <= 'Z' && c2 >= 'A') { 6503 d -= ('a' - 'A'); 6504 if (!d) break; 6505 } 6506 return ((d >= 0) << 1) - 1; 6507 } 6508 } while (c1); 6509 return 0; 6510 } 6511 NK_INTERN int 6512 nk_str_match_here(const char *regexp, const char *text) 6513 { 6514 if (regexp[0] == '\0') 6515 return 1; 6516 if (regexp[1] == '*') 6517 return nk_str_match_star(regexp[0], regexp+2, text); 6518 if (regexp[0] == '$' && regexp[1] == '\0') 6519 return *text == '\0'; 6520 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) 6521 return nk_str_match_here(regexp+1, text+1); 6522 return 0; 6523 } 6524 NK_INTERN int 6525 nk_str_match_star(int c, const char *regexp, const char *text) 6526 { 6527 do {/* a '* matches zero or more instances */ 6528 if (nk_str_match_here(regexp, text)) 6529 return 1; 6530 } while (*text != '\0' && (*text++ == c || c == '.')); 6531 return 0; 6532 } 6533 NK_API int 6534 nk_strfilter(const char *text, const char *regexp) 6535 { 6536 /* 6537 c matches any literal character c 6538 . matches any single character 6539 ^ matches the beginning of the input string 6540 $ matches the end of the input string 6541 * matches zero or more occurrences of the previous character*/ 6542 if (regexp[0] == '^') 6543 return nk_str_match_here(regexp+1, text); 6544 do { /* must look even if string is empty */ 6545 if (nk_str_match_here(regexp, text)) 6546 return 1; 6547 } while (*text++ != '\0'); 6548 return 0; 6549 } 6550 NK_API int 6551 nk_strmatch_fuzzy_text(const char *str, int str_len, 6552 const char *pattern, int *out_score) 6553 { 6554 /* Returns true if each character in pattern is found sequentially within str 6555 * if found then out_score is also set. Score value has no intrinsic meaning. 6556 * Range varies with pattern. Can only compare scores with same search pattern. */ 6557 6558 /* bonus for adjacent matches */ 6559 #define NK_ADJACENCY_BONUS 5 6560 /* bonus if match occurs after a separator */ 6561 #define NK_SEPARATOR_BONUS 10 6562 /* bonus if match is uppercase and prev is lower */ 6563 #define NK_CAMEL_BONUS 10 6564 /* penalty applied for every letter in str before the first match */ 6565 #define NK_LEADING_LETTER_PENALTY (-3) 6566 /* maximum penalty for leading letters */ 6567 #define NK_MAX_LEADING_LETTER_PENALTY (-9) 6568 /* penalty for every letter that doesn't matter */ 6569 #define NK_UNMATCHED_LETTER_PENALTY (-1) 6570 6571 /* loop variables */ 6572 int score = 0; 6573 char const * pattern_iter = pattern; 6574 int str_iter = 0; 6575 int prev_matched = nk_false; 6576 int prev_lower = nk_false; 6577 /* true so if first letter match gets separator bonus*/ 6578 int prev_separator = nk_true; 6579 6580 /* use "best" matched letter if multiple string letters match the pattern */ 6581 char const * best_letter = 0; 6582 int best_letter_score = 0; 6583 6584 /* loop over strings */ 6585 NK_ASSERT(str); 6586 NK_ASSERT(pattern); 6587 if (!str || !str_len || !pattern) return 0; 6588 while (str_iter < str_len) 6589 { 6590 const char pattern_letter = *pattern_iter; 6591 const char str_letter = str[str_iter]; 6592 6593 int next_match = *pattern_iter != '\0' && 6594 nk_to_lower(pattern_letter) == nk_to_lower(str_letter); 6595 int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter); 6596 6597 int advanced = next_match && best_letter; 6598 int pattern_repeat = best_letter && *pattern_iter != '\0'; 6599 pattern_repeat = pattern_repeat && 6600 nk_to_lower(*best_letter) == nk_to_lower(pattern_letter); 6601 6602 if (advanced || pattern_repeat) { 6603 score += best_letter_score; 6604 best_letter = 0; 6605 best_letter_score = 0; 6606 } 6607 6608 if (next_match || rematch) 6609 { 6610 int new_score = 0; 6611 /* Apply penalty for each letter before the first pattern match */ 6612 if (pattern_iter == pattern) { 6613 int count = (int)(&str[str_iter] - str); 6614 int penalty = NK_LEADING_LETTER_PENALTY * count; 6615 if (penalty < NK_MAX_LEADING_LETTER_PENALTY) 6616 penalty = NK_MAX_LEADING_LETTER_PENALTY; 6617 6618 score += penalty; 6619 } 6620 6621 /* apply bonus for consecutive bonuses */ 6622 if (prev_matched) 6623 new_score += NK_ADJACENCY_BONUS; 6624 6625 /* apply bonus for matches after a separator */ 6626 if (prev_separator) 6627 new_score += NK_SEPARATOR_BONUS; 6628 6629 /* apply bonus across camel case boundaries */ 6630 if (prev_lower && nk_is_upper(str_letter)) 6631 new_score += NK_CAMEL_BONUS; 6632 6633 /* update pattern iter IFF the next pattern letter was matched */ 6634 if (next_match) 6635 ++pattern_iter; 6636 6637 /* update best letter in str which may be for a "next" letter or a rematch */ 6638 if (new_score >= best_letter_score) { 6639 /* apply penalty for now skipped letter */ 6640 if (best_letter != 0) 6641 score += NK_UNMATCHED_LETTER_PENALTY; 6642 6643 best_letter = &str[str_iter]; 6644 best_letter_score = new_score; 6645 } 6646 prev_matched = nk_true; 6647 } else { 6648 score += NK_UNMATCHED_LETTER_PENALTY; 6649 prev_matched = nk_false; 6650 } 6651 6652 /* separators should be more easily defined */ 6653 prev_lower = nk_is_lower(str_letter) != 0; 6654 prev_separator = str_letter == '_' || str_letter == ' '; 6655 6656 ++str_iter; 6657 } 6658 6659 /* apply score for last match */ 6660 if (best_letter) 6661 score += best_letter_score; 6662 6663 /* did not match full pattern */ 6664 if (*pattern_iter != '\0') 6665 return nk_false; 6666 6667 if (out_score) 6668 *out_score = score; 6669 return nk_true; 6670 } 6671 NK_API int 6672 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score) 6673 { 6674 return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score); 6675 } 6676 NK_LIB int 6677 nk_string_float_limit(char *string, int prec) 6678 { 6679 int dot = 0; 6680 char *c = string; 6681 while (*c) { 6682 if (*c == '.') { 6683 dot = 1; 6684 c++; 6685 continue; 6686 } 6687 if (dot == (prec+1)) { 6688 *c = 0; 6689 break; 6690 } 6691 if (dot > 0) dot++; 6692 c++; 6693 } 6694 return (int)(c - string); 6695 } 6696 NK_INTERN void 6697 nk_strrev_ascii(char *s) 6698 { 6699 int len = nk_strlen(s); 6700 int end = len / 2; 6701 int i = 0; 6702 char t; 6703 for (; i < end; ++i) { 6704 t = s[i]; 6705 s[i] = s[len - 1 - i]; 6706 s[len -1 - i] = t; 6707 } 6708 } 6709 NK_LIB char* 6710 nk_itoa(char *s, long n) 6711 { 6712 long i = 0; 6713 if (n == 0) { 6714 s[i++] = '0'; 6715 s[i] = 0; 6716 return s; 6717 } 6718 if (n < 0) { 6719 s[i++] = '-'; 6720 n = -n; 6721 } 6722 while (n > 0) { 6723 s[i++] = (char)('0' + (n % 10)); 6724 n /= 10; 6725 } 6726 s[i] = 0; 6727 if (s[0] == '-') 6728 ++s; 6729 6730 nk_strrev_ascii(s); 6731 return s; 6732 } 6733 NK_LIB char* 6734 nk_dtoa(char *s, double n) 6735 { 6736 int useExp = 0; 6737 int digit = 0, m = 0, m1 = 0; 6738 char *c = s; 6739 int neg = 0; 6740 6741 NK_ASSERT(s); 6742 if (!s) return 0; 6743 6744 if (n == 0.0) { 6745 s[0] = '0'; s[1] = '\0'; 6746 return s; 6747 } 6748 6749 neg = (n < 0); 6750 if (neg) n = -n; 6751 6752 /* calculate magnitude */ 6753 m = nk_log10(n); 6754 useExp = (m >= 14 || (neg && m >= 9) || m <= -9); 6755 if (neg) *(c++) = '-'; 6756 6757 /* set up for scientific notation */ 6758 if (useExp) { 6759 if (m < 0) 6760 m -= 1; 6761 n = n / (double)nk_pow(10.0, m); 6762 m1 = m; 6763 m = 0; 6764 } 6765 if (m < 1.0) { 6766 m = 0; 6767 } 6768 6769 /* convert the number */ 6770 while (n > NK_FLOAT_PRECISION || m >= 0) { 6771 double weight = nk_pow(10.0, m); 6772 if (weight > 0) { 6773 double t = (double)n / weight; 6774 digit = nk_ifloord(t); 6775 n -= ((double)digit * weight); 6776 *(c++) = (char)('0' + (char)digit); 6777 } 6778 if (m == 0 && n > 0) 6779 *(c++) = '.'; 6780 m--; 6781 } 6782 6783 if (useExp) { 6784 /* convert the exponent */ 6785 int i, j; 6786 *(c++) = 'e'; 6787 if (m1 > 0) { 6788 *(c++) = '+'; 6789 } else { 6790 *(c++) = '-'; 6791 m1 = -m1; 6792 } 6793 m = 0; 6794 while (m1 > 0) { 6795 *(c++) = (char)('0' + (char)(m1 % 10)); 6796 m1 /= 10; 6797 m++; 6798 } 6799 c -= m; 6800 for (i = 0, j = m-1; i<j; i++, j--) { 6801 /* swap without temporary */ 6802 c[i] ^= c[j]; 6803 c[j] ^= c[i]; 6804 c[i] ^= c[j]; 6805 } 6806 c += m; 6807 } 6808 *(c) = '\0'; 6809 return s; 6810 } 6811 #ifdef NK_INCLUDE_STANDARD_VARARGS 6812 #ifndef NK_INCLUDE_STANDARD_IO 6813 NK_INTERN int 6814 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args) 6815 { 6816 enum nk_arg_type { 6817 NK_ARG_TYPE_CHAR, 6818 NK_ARG_TYPE_SHORT, 6819 NK_ARG_TYPE_DEFAULT, 6820 NK_ARG_TYPE_LONG 6821 }; 6822 enum nk_arg_flags { 6823 NK_ARG_FLAG_LEFT = 0x01, 6824 NK_ARG_FLAG_PLUS = 0x02, 6825 NK_ARG_FLAG_SPACE = 0x04, 6826 NK_ARG_FLAG_NUM = 0x10, 6827 NK_ARG_FLAG_ZERO = 0x20 6828 }; 6829 6830 char number_buffer[NK_MAX_NUMBER_BUFFER]; 6831 enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT; 6832 int precision = NK_DEFAULT; 6833 int width = NK_DEFAULT; 6834 nk_flags flag = 0; 6835 6836 int len = 0; 6837 int result = -1; 6838 const char *iter = fmt; 6839 6840 NK_ASSERT(buf); 6841 NK_ASSERT(buf_size); 6842 if (!buf || !buf_size || !fmt) return 0; 6843 for (iter = fmt; *iter && len < buf_size; iter++) { 6844 /* copy all non-format characters */ 6845 while (*iter && (*iter != '%') && (len < buf_size)) 6846 buf[len++] = *iter++; 6847 if (!(*iter) || len >= buf_size) break; 6848 iter++; 6849 6850 /* flag arguments */ 6851 while (*iter) { 6852 if (*iter == '-') flag |= NK_ARG_FLAG_LEFT; 6853 else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS; 6854 else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE; 6855 else if (*iter == '#') flag |= NK_ARG_FLAG_NUM; 6856 else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO; 6857 else break; 6858 iter++; 6859 } 6860 6861 /* width argument */ 6862 width = NK_DEFAULT; 6863 if (*iter >= '1' && *iter <= '9') { 6864 const char *end; 6865 width = nk_strtoi(iter, &end); 6866 if (end == iter) 6867 width = -1; 6868 else iter = end; 6869 } else if (*iter == '*') { 6870 width = va_arg(args, int); 6871 iter++; 6872 } 6873 6874 /* precision argument */ 6875 precision = NK_DEFAULT; 6876 if (*iter == '.') { 6877 iter++; 6878 if (*iter == '*') { 6879 precision = va_arg(args, int); 6880 iter++; 6881 } else { 6882 const char *end; 6883 precision = nk_strtoi(iter, &end); 6884 if (end == iter) 6885 precision = -1; 6886 else iter = end; 6887 } 6888 } 6889 6890 /* length modifier */ 6891 if (*iter == 'h') { 6892 if (*(iter+1) == 'h') { 6893 arg_type = NK_ARG_TYPE_CHAR; 6894 iter++; 6895 } else arg_type = NK_ARG_TYPE_SHORT; 6896 iter++; 6897 } else if (*iter == 'l') { 6898 arg_type = NK_ARG_TYPE_LONG; 6899 iter++; 6900 } else arg_type = NK_ARG_TYPE_DEFAULT; 6901 6902 /* specifier */ 6903 if (*iter == '%') { 6904 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 6905 NK_ASSERT(precision == NK_DEFAULT); 6906 NK_ASSERT(width == NK_DEFAULT); 6907 if (len < buf_size) 6908 buf[len++] = '%'; 6909 } else if (*iter == 's') { 6910 /* string */ 6911 const char *str = va_arg(args, const char*); 6912 NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!"); 6913 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 6914 NK_ASSERT(precision == NK_DEFAULT); 6915 NK_ASSERT(width == NK_DEFAULT); 6916 if (str == buf) return -1; 6917 while (str && *str && len < buf_size) 6918 buf[len++] = *str++; 6919 } else if (*iter == 'n') { 6920 /* current length callback */ 6921 signed int *n = va_arg(args, int*); 6922 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 6923 NK_ASSERT(precision == NK_DEFAULT); 6924 NK_ASSERT(width == NK_DEFAULT); 6925 if (n) *n = len; 6926 } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') { 6927 /* signed integer */ 6928 long value = 0; 6929 const char *num_iter; 6930 int num_len, num_print, padding; 6931 int cur_precision = NK_MAX(precision, 1); 6932 int cur_width = NK_MAX(width, 0); 6933 6934 /* retrieve correct value type */ 6935 if (arg_type == NK_ARG_TYPE_CHAR) 6936 value = (signed char)va_arg(args, int); 6937 else if (arg_type == NK_ARG_TYPE_SHORT) 6938 value = (signed short)va_arg(args, int); 6939 else if (arg_type == NK_ARG_TYPE_LONG) 6940 value = va_arg(args, signed long); 6941 else if (*iter == 'c') 6942 value = (unsigned char)va_arg(args, int); 6943 else value = va_arg(args, signed int); 6944 6945 /* convert number to string */ 6946 nk_itoa(number_buffer, value); 6947 num_len = nk_strlen(number_buffer); 6948 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 6949 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 6950 padding = NK_MAX(padding-1, 0); 6951 6952 /* fill left padding up to a total of `width` characters */ 6953 if (!(flag & NK_ARG_FLAG_LEFT)) { 6954 while (padding-- > 0 && (len < buf_size)) { 6955 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 6956 buf[len++] = '0'; 6957 else buf[len++] = ' '; 6958 } 6959 } 6960 6961 /* copy string value representation into buffer */ 6962 if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size) 6963 buf[len++] = '+'; 6964 else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size) 6965 buf[len++] = ' '; 6966 6967 /* fill up to precision number of digits with '0' */ 6968 num_print = NK_MAX(cur_precision, num_len); 6969 while (precision && (num_print > num_len) && (len < buf_size)) { 6970 buf[len++] = '0'; 6971 num_print--; 6972 } 6973 6974 /* copy string value representation into buffer */ 6975 num_iter = number_buffer; 6976 while (precision && *num_iter && len < buf_size) 6977 buf[len++] = *num_iter++; 6978 6979 /* fill right padding up to width characters */ 6980 if (flag & NK_ARG_FLAG_LEFT) { 6981 while ((padding-- > 0) && (len < buf_size)) 6982 buf[len++] = ' '; 6983 } 6984 } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') { 6985 /* unsigned integer */ 6986 unsigned long value = 0; 6987 int num_len = 0, num_print, padding = 0; 6988 int cur_precision = NK_MAX(precision, 1); 6989 int cur_width = NK_MAX(width, 0); 6990 unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16; 6991 6992 /* print oct/hex/dec value */ 6993 const char *upper_output_format = "0123456789ABCDEF"; 6994 const char *lower_output_format = "0123456789abcdef"; 6995 const char *output_format = (*iter == 'x') ? 6996 lower_output_format: upper_output_format; 6997 6998 /* retrieve correct value type */ 6999 if (arg_type == NK_ARG_TYPE_CHAR) 7000 value = (unsigned char)va_arg(args, int); 7001 else if (arg_type == NK_ARG_TYPE_SHORT) 7002 value = (unsigned short)va_arg(args, int); 7003 else if (arg_type == NK_ARG_TYPE_LONG) 7004 value = va_arg(args, unsigned long); 7005 else value = va_arg(args, unsigned int); 7006 7007 do { 7008 /* convert decimal number into hex/oct number */ 7009 int digit = output_format[value % base]; 7010 if (num_len < NK_MAX_NUMBER_BUFFER) 7011 number_buffer[num_len++] = (char)digit; 7012 value /= base; 7013 } while (value > 0); 7014 7015 num_print = NK_MAX(cur_precision, num_len); 7016 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7017 if (flag & NK_ARG_FLAG_NUM) 7018 padding = NK_MAX(padding-1, 0); 7019 7020 /* fill left padding up to a total of `width` characters */ 7021 if (!(flag & NK_ARG_FLAG_LEFT)) { 7022 while ((padding-- > 0) && (len < buf_size)) { 7023 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7024 buf[len++] = '0'; 7025 else buf[len++] = ' '; 7026 } 7027 } 7028 7029 /* fill up to precision number of digits */ 7030 if (num_print && (flag & NK_ARG_FLAG_NUM)) { 7031 if ((*iter == 'o') && (len < buf_size)) { 7032 buf[len++] = '0'; 7033 } else if ((*iter == 'x') && ((len+1) < buf_size)) { 7034 buf[len++] = '0'; 7035 buf[len++] = 'x'; 7036 } else if ((*iter == 'X') && ((len+1) < buf_size)) { 7037 buf[len++] = '0'; 7038 buf[len++] = 'X'; 7039 } 7040 } 7041 while (precision && (num_print > num_len) && (len < buf_size)) { 7042 buf[len++] = '0'; 7043 num_print--; 7044 } 7045 7046 /* reverse number direction */ 7047 while (num_len > 0) { 7048 if (precision && (len < buf_size)) 7049 buf[len++] = number_buffer[num_len-1]; 7050 num_len--; 7051 } 7052 7053 /* fill right padding up to width characters */ 7054 if (flag & NK_ARG_FLAG_LEFT) { 7055 while ((padding-- > 0) && (len < buf_size)) 7056 buf[len++] = ' '; 7057 } 7058 } else if (*iter == 'f') { 7059 /* floating point */ 7060 const char *num_iter; 7061 int cur_precision = (precision < 0) ? 6: precision; 7062 int prefix, cur_width = NK_MAX(width, 0); 7063 double value = va_arg(args, double); 7064 int num_len = 0, frac_len = 0, dot = 0; 7065 int padding = 0; 7066 7067 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7068 NK_DTOA(number_buffer, value); 7069 num_len = nk_strlen(number_buffer); 7070 7071 /* calculate padding */ 7072 num_iter = number_buffer; 7073 while (*num_iter && *num_iter != '.') 7074 num_iter++; 7075 7076 prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0; 7077 padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0); 7078 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7079 padding = NK_MAX(padding-1, 0); 7080 7081 /* fill left padding up to a total of `width` characters */ 7082 if (!(flag & NK_ARG_FLAG_LEFT)) { 7083 while (padding-- > 0 && (len < buf_size)) { 7084 if (flag & NK_ARG_FLAG_ZERO) 7085 buf[len++] = '0'; 7086 else buf[len++] = ' '; 7087 } 7088 } 7089 7090 /* copy string value representation into buffer */ 7091 num_iter = number_buffer; 7092 if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size)) 7093 buf[len++] = '+'; 7094 else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size)) 7095 buf[len++] = ' '; 7096 while (*num_iter) { 7097 if (dot) frac_len++; 7098 if (len < buf_size) 7099 buf[len++] = *num_iter; 7100 if (*num_iter == '.') dot = 1; 7101 if (frac_len >= cur_precision) break; 7102 num_iter++; 7103 } 7104 7105 /* fill number up to precision */ 7106 while (frac_len < cur_precision) { 7107 if (!dot && len < buf_size) { 7108 buf[len++] = '.'; 7109 dot = 1; 7110 } 7111 if (len < buf_size) 7112 buf[len++] = '0'; 7113 frac_len++; 7114 } 7115 7116 /* fill right padding up to width characters */ 7117 if (flag & NK_ARG_FLAG_LEFT) { 7118 while ((padding-- > 0) && (len < buf_size)) 7119 buf[len++] = ' '; 7120 } 7121 } else { 7122 /* Specifier not supported: g,G,e,E,p,z */ 7123 NK_ASSERT(0 && "specifier is not supported!"); 7124 return result; 7125 } 7126 } 7127 buf[(len >= buf_size)?(buf_size-1):len] = 0; 7128 result = (len >= buf_size)?-1:len; 7129 return result; 7130 } 7131 #endif 7132 NK_LIB int 7133 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args) 7134 { 7135 int result = -1; 7136 NK_ASSERT(buf); 7137 NK_ASSERT(buf_size); 7138 if (!buf || !buf_size || !fmt) return 0; 7139 #ifdef NK_INCLUDE_STANDARD_IO 7140 result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args); 7141 result = (result >= buf_size) ? -1: result; 7142 buf[buf_size-1] = 0; 7143 #else 7144 result = nk_vsnprintf(buf, buf_size, fmt, args); 7145 #endif 7146 return result; 7147 } 7148 #endif 7149 NK_API nk_hash 7150 nk_murmur_hash(const void * key, int len, nk_hash seed) 7151 { 7152 /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ 7153 #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) 7154 union {const nk_uint *i; const nk_byte *b;} conv = {0}; 7155 const nk_byte *data = (const nk_byte*)key; 7156 const int nblocks = len/4; 7157 nk_uint h1 = seed; 7158 const nk_uint c1 = 0xcc9e2d51; 7159 const nk_uint c2 = 0x1b873593; 7160 const nk_byte *tail; 7161 const nk_uint *blocks; 7162 nk_uint k1; 7163 int i; 7164 7165 /* body */ 7166 if (!key) return 0; 7167 conv.b = (data + nblocks*4); 7168 blocks = (const nk_uint*)conv.i; 7169 for (i = -nblocks; i; ++i) { 7170 k1 = blocks[i]; 7171 k1 *= c1; 7172 k1 = NK_ROTL(k1,15); 7173 k1 *= c2; 7174 7175 h1 ^= k1; 7176 h1 = NK_ROTL(h1,13); 7177 h1 = h1*5+0xe6546b64; 7178 } 7179 7180 /* tail */ 7181 tail = (const nk_byte*)(data + nblocks*4); 7182 k1 = 0; 7183 switch (len & 3) { 7184 case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */ 7185 case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */ 7186 case 1: k1 ^= tail[0]; 7187 k1 *= c1; 7188 k1 = NK_ROTL(k1,15); 7189 k1 *= c2; 7190 h1 ^= k1; 7191 break; 7192 default: break; 7193 } 7194 7195 /* finalization */ 7196 h1 ^= (nk_uint)len; 7197 /* fmix32 */ 7198 h1 ^= h1 >> 16; 7199 h1 *= 0x85ebca6b; 7200 h1 ^= h1 >> 13; 7201 h1 *= 0xc2b2ae35; 7202 h1 ^= h1 >> 16; 7203 7204 #undef NK_ROTL 7205 return h1; 7206 } 7207 #ifdef NK_INCLUDE_STANDARD_IO 7208 NK_LIB char* 7209 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc) 7210 { 7211 char *buf; 7212 FILE *fd; 7213 long ret; 7214 7215 NK_ASSERT(path); 7216 NK_ASSERT(siz); 7217 NK_ASSERT(alloc); 7218 if (!path || !siz || !alloc) 7219 return 0; 7220 7221 fd = fopen(path, "rb"); 7222 if (!fd) return 0; 7223 fseek(fd, 0, SEEK_END); 7224 ret = ftell(fd); 7225 if (ret < 0) { 7226 fclose(fd); 7227 return 0; 7228 } 7229 *siz = (nk_size)ret; 7230 fseek(fd, 0, SEEK_SET); 7231 buf = (char*)alloc->alloc(alloc->userdata,0, *siz); 7232 NK_ASSERT(buf); 7233 if (!buf) { 7234 fclose(fd); 7235 return 0; 7236 } 7237 *siz = (nk_size)fread(buf, 1,*siz, fd); 7238 fclose(fd); 7239 return buf; 7240 } 7241 #endif 7242 NK_LIB int 7243 nk_text_clamp(const struct nk_user_font *font, const char *text, 7244 int text_len, float space, int *glyphs, float *text_width, 7245 nk_rune *sep_list, int sep_count) 7246 { 7247 int i = 0; 7248 int glyph_len = 0; 7249 float last_width = 0; 7250 nk_rune unicode = 0; 7251 float width = 0; 7252 int len = 0; 7253 int g = 0; 7254 float s; 7255 7256 int sep_len = 0; 7257 int sep_g = 0; 7258 float sep_width = 0; 7259 sep_count = NK_MAX(sep_count,0); 7260 7261 glyph_len = nk_utf_decode(text, &unicode, text_len); 7262 while (glyph_len && (width < space) && (len < text_len)) { 7263 len += glyph_len; 7264 s = font->width(font->userdata, font->height, text, len); 7265 for (i = 0; i < sep_count; ++i) { 7266 if (unicode != sep_list[i]) continue; 7267 sep_width = last_width = width; 7268 sep_g = g+1; 7269 sep_len = len; 7270 break; 7271 } 7272 if (i == sep_count){ 7273 last_width = sep_width = width; 7274 sep_g = g+1; 7275 } 7276 width = s; 7277 glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len); 7278 g++; 7279 } 7280 if (len >= text_len) { 7281 *glyphs = g; 7282 *text_width = last_width; 7283 return len; 7284 } else { 7285 *glyphs = sep_g; 7286 *text_width = sep_width; 7287 return (!sep_len) ? len: sep_len; 7288 } 7289 } 7290 NK_LIB struct nk_vec2 7291 nk_text_calculate_text_bounds(const struct nk_user_font *font, 7292 const char *begin, int byte_len, float row_height, const char **remaining, 7293 struct nk_vec2 *out_offset, int *glyphs, int op) 7294 { 7295 float line_height = row_height; 7296 struct nk_vec2 text_size = nk_vec2(0,0); 7297 float line_width = 0.0f; 7298 7299 float glyph_width; 7300 int glyph_len = 0; 7301 nk_rune unicode = 0; 7302 int text_len = 0; 7303 if (!begin || byte_len <= 0 || !font) 7304 return nk_vec2(0,row_height); 7305 7306 glyph_len = nk_utf_decode(begin, &unicode, byte_len); 7307 if (!glyph_len) return text_size; 7308 glyph_width = font->width(font->userdata, font->height, begin, glyph_len); 7309 7310 *glyphs = 0; 7311 while ((text_len < byte_len) && glyph_len) { 7312 if (unicode == '\n') { 7313 text_size.x = NK_MAX(text_size.x, line_width); 7314 text_size.y += line_height; 7315 line_width = 0; 7316 *glyphs+=1; 7317 if (op == NK_STOP_ON_NEW_LINE) 7318 break; 7319 7320 text_len++; 7321 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7322 continue; 7323 } 7324 7325 if (unicode == '\r') { 7326 text_len++; 7327 *glyphs+=1; 7328 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7329 continue; 7330 } 7331 7332 *glyphs = *glyphs + 1; 7333 text_len += glyph_len; 7334 line_width += (float)glyph_width; 7335 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7336 glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len); 7337 continue; 7338 } 7339 7340 if (text_size.x < line_width) 7341 text_size.x = line_width; 7342 if (out_offset) 7343 *out_offset = nk_vec2(line_width, text_size.y + line_height); 7344 if (line_width > 0 || text_size.y == 0.0f) 7345 text_size.y += line_height; 7346 if (remaining) 7347 *remaining = begin+text_len; 7348 return text_size; 7349 } 7350 7351 7352 7353 7354 7355 /* ============================================================== 7356 * 7357 * COLOR 7358 * 7359 * ===============================================================*/ 7360 NK_INTERN int 7361 nk_parse_hex(const char *p, int length) 7362 { 7363 int i = 0; 7364 int len = 0; 7365 while (len < length) { 7366 i <<= 4; 7367 if (p[len] >= 'a' && p[len] <= 'f') 7368 i += ((p[len] - 'a') + 10); 7369 else if (p[len] >= 'A' && p[len] <= 'F') 7370 i += ((p[len] - 'A') + 10); 7371 else i += (p[len] - '0'); 7372 len++; 7373 } 7374 return i; 7375 } 7376 NK_API struct nk_color 7377 nk_rgba(int r, int g, int b, int a) 7378 { 7379 struct nk_color ret; 7380 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7381 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7382 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7383 ret.a = (nk_byte)NK_CLAMP(0, a, 255); 7384 return ret; 7385 } 7386 NK_API struct nk_color 7387 nk_rgb_hex(const char *rgb) 7388 { 7389 struct nk_color col; 7390 const char *c = rgb; 7391 if (*c == '#') c++; 7392 col.r = (nk_byte)nk_parse_hex(c, 2); 7393 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7394 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7395 col.a = 255; 7396 return col; 7397 } 7398 NK_API struct nk_color 7399 nk_rgba_hex(const char *rgb) 7400 { 7401 struct nk_color col; 7402 const char *c = rgb; 7403 if (*c == '#') c++; 7404 col.r = (nk_byte)nk_parse_hex(c, 2); 7405 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7406 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7407 col.a = (nk_byte)nk_parse_hex(c+6, 2); 7408 return col; 7409 } 7410 NK_API void 7411 nk_color_hex_rgba(char *output, struct nk_color col) 7412 { 7413 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7414 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7415 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7416 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7417 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7418 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7419 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7420 output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4); 7421 output[7] = (char)NK_TO_HEX((col.a & 0x0F)); 7422 output[8] = '\0'; 7423 #undef NK_TO_HEX 7424 } 7425 NK_API void 7426 nk_color_hex_rgb(char *output, struct nk_color col) 7427 { 7428 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7429 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7430 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7431 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7432 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7433 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7434 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7435 output[6] = '\0'; 7436 #undef NK_TO_HEX 7437 } 7438 NK_API struct nk_color 7439 nk_rgba_iv(const int *c) 7440 { 7441 return nk_rgba(c[0], c[1], c[2], c[3]); 7442 } 7443 NK_API struct nk_color 7444 nk_rgba_bv(const nk_byte *c) 7445 { 7446 return nk_rgba(c[0], c[1], c[2], c[3]); 7447 } 7448 NK_API struct nk_color 7449 nk_rgb(int r, int g, int b) 7450 { 7451 struct nk_color ret; 7452 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7453 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7454 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7455 ret.a = (nk_byte)255; 7456 return ret; 7457 } 7458 NK_API struct nk_color 7459 nk_rgb_iv(const int *c) 7460 { 7461 return nk_rgb(c[0], c[1], c[2]); 7462 } 7463 NK_API struct nk_color 7464 nk_rgb_bv(const nk_byte* c) 7465 { 7466 return nk_rgb(c[0], c[1], c[2]); 7467 } 7468 NK_API struct nk_color 7469 nk_rgba_u32(nk_uint in) 7470 { 7471 struct nk_color ret; 7472 ret.r = (in & 0xFF); 7473 ret.g = ((in >> 8) & 0xFF); 7474 ret.b = ((in >> 16) & 0xFF); 7475 ret.a = (nk_byte)((in >> 24) & 0xFF); 7476 return ret; 7477 } 7478 NK_API struct nk_color 7479 nk_rgba_f(float r, float g, float b, float a) 7480 { 7481 struct nk_color ret; 7482 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7483 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7484 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7485 ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f); 7486 return ret; 7487 } 7488 NK_API struct nk_color 7489 nk_rgba_fv(const float *c) 7490 { 7491 return nk_rgba_f(c[0], c[1], c[2], c[3]); 7492 } 7493 NK_API struct nk_color 7494 nk_rgba_cf(struct nk_colorf c) 7495 { 7496 return nk_rgba_f(c.r, c.g, c.b, c.a); 7497 } 7498 NK_API struct nk_color 7499 nk_rgb_f(float r, float g, float b) 7500 { 7501 struct nk_color ret; 7502 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7503 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7504 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7505 ret.a = 255; 7506 return ret; 7507 } 7508 NK_API struct nk_color 7509 nk_rgb_fv(const float *c) 7510 { 7511 return nk_rgb_f(c[0], c[1], c[2]); 7512 } 7513 NK_API struct nk_color 7514 nk_rgb_cf(struct nk_colorf c) 7515 { 7516 return nk_rgb_f(c.r, c.g, c.b); 7517 } 7518 NK_API struct nk_color 7519 nk_hsv(int h, int s, int v) 7520 { 7521 return nk_hsva(h, s, v, 255); 7522 } 7523 NK_API struct nk_color 7524 nk_hsv_iv(const int *c) 7525 { 7526 return nk_hsv(c[0], c[1], c[2]); 7527 } 7528 NK_API struct nk_color 7529 nk_hsv_bv(const nk_byte *c) 7530 { 7531 return nk_hsv(c[0], c[1], c[2]); 7532 } 7533 NK_API struct nk_color 7534 nk_hsv_f(float h, float s, float v) 7535 { 7536 return nk_hsva_f(h, s, v, 1.0f); 7537 } 7538 NK_API struct nk_color 7539 nk_hsv_fv(const float *c) 7540 { 7541 return nk_hsv_f(c[0], c[1], c[2]); 7542 } 7543 NK_API struct nk_color 7544 nk_hsva(int h, int s, int v, int a) 7545 { 7546 float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f; 7547 float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f; 7548 float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f; 7549 float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f; 7550 return nk_hsva_f(hf, sf, vf, af); 7551 } 7552 NK_API struct nk_color 7553 nk_hsva_iv(const int *c) 7554 { 7555 return nk_hsva(c[0], c[1], c[2], c[3]); 7556 } 7557 NK_API struct nk_color 7558 nk_hsva_bv(const nk_byte *c) 7559 { 7560 return nk_hsva(c[0], c[1], c[2], c[3]); 7561 } 7562 NK_API struct nk_colorf 7563 nk_hsva_colorf(float h, float s, float v, float a) 7564 { 7565 int i; 7566 float p, q, t, f; 7567 struct nk_colorf out = {0,0,0,0}; 7568 if (s <= 0.0f) { 7569 out.r = v; out.g = v; out.b = v; out.a = a; 7570 return out; 7571 } 7572 h = h / (60.0f/360.0f); 7573 i = (int)h; 7574 f = h - (float)i; 7575 p = v * (1.0f - s); 7576 q = v * (1.0f - (s * f)); 7577 t = v * (1.0f - s * (1.0f - f)); 7578 7579 switch (i) { 7580 case 0: default: out.r = v; out.g = t; out.b = p; break; 7581 case 1: out.r = q; out.g = v; out.b = p; break; 7582 case 2: out.r = p; out.g = v; out.b = t; break; 7583 case 3: out.r = p; out.g = q; out.b = v; break; 7584 case 4: out.r = t; out.g = p; out.b = v; break; 7585 case 5: out.r = v; out.g = p; out.b = q; break;} 7586 out.a = a; 7587 return out; 7588 } 7589 NK_API struct nk_colorf 7590 nk_hsva_colorfv(float *c) 7591 { 7592 return nk_hsva_colorf(c[0], c[1], c[2], c[3]); 7593 } 7594 NK_API struct nk_color 7595 nk_hsva_f(float h, float s, float v, float a) 7596 { 7597 struct nk_colorf c = nk_hsva_colorf(h, s, v, a); 7598 return nk_rgba_f(c.r, c.g, c.b, c.a); 7599 } 7600 NK_API struct nk_color 7601 nk_hsva_fv(const float *c) 7602 { 7603 return nk_hsva_f(c[0], c[1], c[2], c[3]); 7604 } 7605 NK_API nk_uint 7606 nk_color_u32(struct nk_color in) 7607 { 7608 nk_uint out = (nk_uint)in.r; 7609 out |= ((nk_uint)in.g << 8); 7610 out |= ((nk_uint)in.b << 16); 7611 out |= ((nk_uint)in.a << 24); 7612 return out; 7613 } 7614 NK_API void 7615 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in) 7616 { 7617 NK_STORAGE const float s = 1.0f/255.0f; 7618 *r = (float)in.r * s; 7619 *g = (float)in.g * s; 7620 *b = (float)in.b * s; 7621 *a = (float)in.a * s; 7622 } 7623 NK_API void 7624 nk_color_fv(float *c, struct nk_color in) 7625 { 7626 nk_color_f(&c[0], &c[1], &c[2], &c[3], in); 7627 } 7628 NK_API struct nk_colorf 7629 nk_color_cf(struct nk_color in) 7630 { 7631 struct nk_colorf o; 7632 nk_color_f(&o.r, &o.g, &o.b, &o.a, in); 7633 return o; 7634 } 7635 NK_API void 7636 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in) 7637 { 7638 NK_STORAGE const double s = 1.0/255.0; 7639 *r = (double)in.r * s; 7640 *g = (double)in.g * s; 7641 *b = (double)in.b * s; 7642 *a = (double)in.a * s; 7643 } 7644 NK_API void 7645 nk_color_dv(double *c, struct nk_color in) 7646 { 7647 nk_color_d(&c[0], &c[1], &c[2], &c[3], in); 7648 } 7649 NK_API void 7650 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in) 7651 { 7652 float a; 7653 nk_color_hsva_f(out_h, out_s, out_v, &a, in); 7654 } 7655 NK_API void 7656 nk_color_hsv_fv(float *out, struct nk_color in) 7657 { 7658 float a; 7659 nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in); 7660 } 7661 NK_API void 7662 nk_colorf_hsva_f(float *out_h, float *out_s, 7663 float *out_v, float *out_a, struct nk_colorf in) 7664 { 7665 float chroma; 7666 float K = 0.0f; 7667 if (in.g < in.b) { 7668 const float t = in.g; in.g = in.b; in.b = t; 7669 K = -1.f; 7670 } 7671 if (in.r < in.g) { 7672 const float t = in.r; in.r = in.g; in.g = t; 7673 K = -2.f/6.0f - K; 7674 } 7675 chroma = in.r - ((in.g < in.b) ? in.g: in.b); 7676 *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f)); 7677 *out_s = chroma / (in.r + 1e-20f); 7678 *out_v = in.r; 7679 *out_a = in.a; 7680 7681 } 7682 NK_API void 7683 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in) 7684 { 7685 nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in); 7686 } 7687 NK_API void 7688 nk_color_hsva_f(float *out_h, float *out_s, 7689 float *out_v, float *out_a, struct nk_color in) 7690 { 7691 struct nk_colorf col; 7692 nk_color_f(&col.r,&col.g,&col.b,&col.a, in); 7693 nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col); 7694 } 7695 NK_API void 7696 nk_color_hsva_fv(float *out, struct nk_color in) 7697 { 7698 nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in); 7699 } 7700 NK_API void 7701 nk_color_hsva_i(int *out_h, int *out_s, int *out_v, 7702 int *out_a, struct nk_color in) 7703 { 7704 float h,s,v,a; 7705 nk_color_hsva_f(&h, &s, &v, &a, in); 7706 *out_h = (nk_byte)(h * 255.0f); 7707 *out_s = (nk_byte)(s * 255.0f); 7708 *out_v = (nk_byte)(v * 255.0f); 7709 *out_a = (nk_byte)(a * 255.0f); 7710 } 7711 NK_API void 7712 nk_color_hsva_iv(int *out, struct nk_color in) 7713 { 7714 nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in); 7715 } 7716 NK_API void 7717 nk_color_hsva_bv(nk_byte *out, struct nk_color in) 7718 { 7719 int tmp[4]; 7720 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7721 out[0] = (nk_byte)tmp[0]; 7722 out[1] = (nk_byte)tmp[1]; 7723 out[2] = (nk_byte)tmp[2]; 7724 out[3] = (nk_byte)tmp[3]; 7725 } 7726 NK_API void 7727 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in) 7728 { 7729 int tmp[4]; 7730 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7731 *h = (nk_byte)tmp[0]; 7732 *s = (nk_byte)tmp[1]; 7733 *v = (nk_byte)tmp[2]; 7734 *a = (nk_byte)tmp[3]; 7735 } 7736 NK_API void 7737 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in) 7738 { 7739 int a; 7740 nk_color_hsva_i(out_h, out_s, out_v, &a, in); 7741 } 7742 NK_API void 7743 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in) 7744 { 7745 int tmp[4]; 7746 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7747 *out_h = (nk_byte)tmp[0]; 7748 *out_s = (nk_byte)tmp[1]; 7749 *out_v = (nk_byte)tmp[2]; 7750 } 7751 NK_API void 7752 nk_color_hsv_iv(int *out, struct nk_color in) 7753 { 7754 nk_color_hsv_i(&out[0], &out[1], &out[2], in); 7755 } 7756 NK_API void 7757 nk_color_hsv_bv(nk_byte *out, struct nk_color in) 7758 { 7759 int tmp[4]; 7760 nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in); 7761 out[0] = (nk_byte)tmp[0]; 7762 out[1] = (nk_byte)tmp[1]; 7763 out[2] = (nk_byte)tmp[2]; 7764 } 7765 7766 7767 7768 7769 7770 /* =============================================================== 7771 * 7772 * UTF-8 7773 * 7774 * ===============================================================*/ 7775 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 7776 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 7777 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000}; 7778 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 7779 7780 NK_INTERN int 7781 nk_utf_validate(nk_rune *u, int i) 7782 { 7783 NK_ASSERT(u); 7784 if (!u) return 0; 7785 if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) || 7786 NK_BETWEEN(*u, 0xD800, 0xDFFF)) 7787 *u = NK_UTF_INVALID; 7788 for (i = 1; *u > nk_utfmax[i]; ++i); 7789 return i; 7790 } 7791 NK_INTERN nk_rune 7792 nk_utf_decode_byte(char c, int *i) 7793 { 7794 NK_ASSERT(i); 7795 if (!i) return 0; 7796 for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) { 7797 if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i]) 7798 return (nk_byte)(c & ~nk_utfmask[*i]); 7799 } 7800 return 0; 7801 } 7802 NK_API int 7803 nk_utf_decode(const char *c, nk_rune *u, int clen) 7804 { 7805 int i, j, len, type=0; 7806 nk_rune udecoded; 7807 7808 NK_ASSERT(c); 7809 NK_ASSERT(u); 7810 7811 if (!c || !u) return 0; 7812 if (!clen) return 0; 7813 *u = NK_UTF_INVALID; 7814 7815 udecoded = nk_utf_decode_byte(c[0], &len); 7816 if (!NK_BETWEEN(len, 1, NK_UTF_SIZE)) 7817 return 1; 7818 7819 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 7820 udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type); 7821 if (type != 0) 7822 return j; 7823 } 7824 if (j < len) 7825 return 0; 7826 *u = udecoded; 7827 nk_utf_validate(u, len); 7828 return len; 7829 } 7830 NK_INTERN char 7831 nk_utf_encode_byte(nk_rune u, int i) 7832 { 7833 return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i])); 7834 } 7835 NK_API int 7836 nk_utf_encode(nk_rune u, char *c, int clen) 7837 { 7838 int len, i; 7839 len = nk_utf_validate(&u, 0); 7840 if (clen < len || !len || len > NK_UTF_SIZE) 7841 return 0; 7842 7843 for (i = len - 1; i != 0; --i) { 7844 c[i] = nk_utf_encode_byte(u, 0); 7845 u >>= 6; 7846 } 7847 c[0] = nk_utf_encode_byte(u, len); 7848 return len; 7849 } 7850 NK_API int 7851 nk_utf_len(const char *str, int len) 7852 { 7853 const char *text; 7854 int glyphs = 0; 7855 int text_len; 7856 int glyph_len; 7857 int src_len = 0; 7858 nk_rune unicode; 7859 7860 NK_ASSERT(str); 7861 if (!str || !len) return 0; 7862 7863 text = str; 7864 text_len = len; 7865 glyph_len = nk_utf_decode(text, &unicode, text_len); 7866 while (glyph_len && src_len < len) { 7867 glyphs++; 7868 src_len = src_len + glyph_len; 7869 glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len); 7870 } 7871 return glyphs; 7872 } 7873 NK_API const char* 7874 nk_utf_at(const char *buffer, int length, int index, 7875 nk_rune *unicode, int *len) 7876 { 7877 int i = 0; 7878 int src_len = 0; 7879 int glyph_len = 0; 7880 const char *text; 7881 int text_len; 7882 7883 NK_ASSERT(buffer); 7884 NK_ASSERT(unicode); 7885 NK_ASSERT(len); 7886 7887 if (!buffer || !unicode || !len) return 0; 7888 if (index < 0) { 7889 *unicode = NK_UTF_INVALID; 7890 *len = 0; 7891 return 0; 7892 } 7893 7894 text = buffer; 7895 text_len = length; 7896 glyph_len = nk_utf_decode(text, unicode, text_len); 7897 while (glyph_len) { 7898 if (i == index) { 7899 *len = glyph_len; 7900 break; 7901 } 7902 7903 i++; 7904 src_len = src_len + glyph_len; 7905 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 7906 } 7907 if (i != index) return 0; 7908 return buffer + src_len; 7909 } 7910 7911 7912 7913 7914 7915 /* ============================================================== 7916 * 7917 * BUFFER 7918 * 7919 * ===============================================================*/ 7920 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 7921 NK_LIB void* 7922 nk_malloc(nk_handle unused, void *old,nk_size size) 7923 { 7924 NK_UNUSED(unused); 7925 NK_UNUSED(old); 7926 return malloc(size); 7927 } 7928 NK_LIB void 7929 nk_mfree(nk_handle unused, void *ptr) 7930 { 7931 NK_UNUSED(unused); 7932 free(ptr); 7933 } 7934 NK_API void 7935 nk_buffer_init_default(struct nk_buffer *buffer) 7936 { 7937 struct nk_allocator alloc; 7938 alloc.userdata.ptr = 0; 7939 alloc.alloc = nk_malloc; 7940 alloc.free = nk_mfree; 7941 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE); 7942 } 7943 #endif 7944 7945 NK_API void 7946 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a, 7947 nk_size initial_size) 7948 { 7949 NK_ASSERT(b); 7950 NK_ASSERT(a); 7951 NK_ASSERT(initial_size); 7952 if (!b || !a || !initial_size) return; 7953 7954 nk_zero(b, sizeof(*b)); 7955 b->type = NK_BUFFER_DYNAMIC; 7956 b->memory.ptr = a->alloc(a->userdata,0, initial_size); 7957 b->memory.size = initial_size; 7958 b->size = initial_size; 7959 b->grow_factor = 2.0f; 7960 b->pool = *a; 7961 } 7962 NK_API void 7963 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size) 7964 { 7965 NK_ASSERT(b); 7966 NK_ASSERT(m); 7967 NK_ASSERT(size); 7968 if (!b || !m || !size) return; 7969 7970 nk_zero(b, sizeof(*b)); 7971 b->type = NK_BUFFER_FIXED; 7972 b->memory.ptr = m; 7973 b->memory.size = size; 7974 b->size = size; 7975 } 7976 NK_LIB void* 7977 nk_buffer_align(void *unaligned, 7978 nk_size align, nk_size *alignment, 7979 enum nk_buffer_allocation_type type) 7980 { 7981 void *memory = 0; 7982 switch (type) { 7983 default: 7984 case NK_BUFFER_MAX: 7985 case NK_BUFFER_FRONT: 7986 if (align) { 7987 memory = NK_ALIGN_PTR(unaligned, align); 7988 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 7989 } else { 7990 memory = unaligned; 7991 *alignment = 0; 7992 } 7993 break; 7994 case NK_BUFFER_BACK: 7995 if (align) { 7996 memory = NK_ALIGN_PTR_BACK(unaligned, align); 7997 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory); 7998 } else { 7999 memory = unaligned; 8000 *alignment = 0; 8001 } 8002 break; 8003 } 8004 return memory; 8005 } 8006 NK_LIB void* 8007 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size) 8008 { 8009 void *temp; 8010 nk_size buffer_size; 8011 8012 NK_ASSERT(b); 8013 NK_ASSERT(size); 8014 if (!b || !size || !b->pool.alloc || !b->pool.free) 8015 return 0; 8016 8017 buffer_size = b->memory.size; 8018 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity); 8019 NK_ASSERT(temp); 8020 if (!temp) return 0; 8021 8022 *size = capacity; 8023 if (temp != b->memory.ptr) { 8024 NK_MEMCPY(temp, b->memory.ptr, buffer_size); 8025 b->pool.free(b->pool.userdata, b->memory.ptr); 8026 } 8027 8028 if (b->size == buffer_size) { 8029 /* no back buffer so just set correct size */ 8030 b->size = capacity; 8031 return temp; 8032 } else { 8033 /* copy back buffer to the end of the new buffer */ 8034 void *dst, *src; 8035 nk_size back_size; 8036 back_size = buffer_size - b->size; 8037 dst = nk_ptr_add(void, temp, capacity - back_size); 8038 src = nk_ptr_add(void, temp, b->size); 8039 NK_MEMCPY(dst, src, back_size); 8040 b->size = capacity - back_size; 8041 } 8042 return temp; 8043 } 8044 NK_LIB void* 8045 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8046 nk_size size, nk_size align) 8047 { 8048 int full; 8049 nk_size alignment; 8050 void *unaligned; 8051 void *memory; 8052 8053 NK_ASSERT(b); 8054 NK_ASSERT(size); 8055 if (!b || !size) return 0; 8056 b->needed += size; 8057 8058 /* calculate total size with needed alignment + size */ 8059 if (type == NK_BUFFER_FRONT) 8060 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8061 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8062 memory = nk_buffer_align(unaligned, align, &alignment, type); 8063 8064 /* check if buffer has enough memory*/ 8065 if (type == NK_BUFFER_FRONT) 8066 full = ((b->allocated + size + alignment) > b->size); 8067 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated); 8068 8069 if (full) { 8070 nk_size capacity; 8071 if (b->type != NK_BUFFER_DYNAMIC) 8072 return 0; 8073 NK_ASSERT(b->pool.alloc && b->pool.free); 8074 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free) 8075 return 0; 8076 8077 /* buffer is full so allocate bigger buffer if dynamic */ 8078 capacity = (nk_size)((float)b->memory.size * b->grow_factor); 8079 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size))); 8080 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size); 8081 if (!b->memory.ptr) return 0; 8082 8083 /* align newly allocated pointer */ 8084 if (type == NK_BUFFER_FRONT) 8085 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8086 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8087 memory = nk_buffer_align(unaligned, align, &alignment, type); 8088 } 8089 if (type == NK_BUFFER_FRONT) 8090 b->allocated += size + alignment; 8091 else b->size -= (size + alignment); 8092 b->needed += alignment; 8093 b->calls++; 8094 return memory; 8095 } 8096 NK_API void 8097 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8098 const void *memory, nk_size size, nk_size align) 8099 { 8100 void *mem = nk_buffer_alloc(b, type, size, align); 8101 if (!mem) return; 8102 NK_MEMCPY(mem, memory, size); 8103 } 8104 NK_API void 8105 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8106 { 8107 NK_ASSERT(buffer); 8108 if (!buffer) return; 8109 buffer->marker[type].active = nk_true; 8110 if (type == NK_BUFFER_BACK) 8111 buffer->marker[type].offset = buffer->size; 8112 else buffer->marker[type].offset = buffer->allocated; 8113 } 8114 NK_API void 8115 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8116 { 8117 NK_ASSERT(buffer); 8118 if (!buffer) return; 8119 if (type == NK_BUFFER_BACK) { 8120 /* reset back buffer either back to marker or empty */ 8121 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset); 8122 if (buffer->marker[type].active) 8123 buffer->size = buffer->marker[type].offset; 8124 else buffer->size = buffer->memory.size; 8125 buffer->marker[type].active = nk_false; 8126 } else { 8127 /* reset front buffer either back to back marker or empty */ 8128 buffer->needed -= (buffer->allocated - buffer->marker[type].offset); 8129 if (buffer->marker[type].active) 8130 buffer->allocated = buffer->marker[type].offset; 8131 else buffer->allocated = 0; 8132 buffer->marker[type].active = nk_false; 8133 } 8134 } 8135 NK_API void 8136 nk_buffer_clear(struct nk_buffer *b) 8137 { 8138 NK_ASSERT(b); 8139 if (!b) return; 8140 b->allocated = 0; 8141 b->size = b->memory.size; 8142 b->calls = 0; 8143 b->needed = 0; 8144 } 8145 NK_API void 8146 nk_buffer_free(struct nk_buffer *b) 8147 { 8148 NK_ASSERT(b); 8149 if (!b || !b->memory.ptr) return; 8150 if (b->type == NK_BUFFER_FIXED) return; 8151 if (!b->pool.free) return; 8152 NK_ASSERT(b->pool.free); 8153 b->pool.free(b->pool.userdata, b->memory.ptr); 8154 } 8155 NK_API void 8156 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b) 8157 { 8158 NK_ASSERT(b); 8159 NK_ASSERT(s); 8160 if (!s || !b) return; 8161 s->allocated = b->allocated; 8162 s->size = b->memory.size; 8163 s->needed = b->needed; 8164 s->memory = b->memory.ptr; 8165 s->calls = b->calls; 8166 } 8167 NK_API void* 8168 nk_buffer_memory(struct nk_buffer *buffer) 8169 { 8170 NK_ASSERT(buffer); 8171 if (!buffer) return 0; 8172 return buffer->memory.ptr; 8173 } 8174 NK_API const void* 8175 nk_buffer_memory_const(const struct nk_buffer *buffer) 8176 { 8177 NK_ASSERT(buffer); 8178 if (!buffer) return 0; 8179 return buffer->memory.ptr; 8180 } 8181 NK_API nk_size 8182 nk_buffer_total(struct nk_buffer *buffer) 8183 { 8184 NK_ASSERT(buffer); 8185 if (!buffer) return 0; 8186 return buffer->memory.size; 8187 } 8188 8189 8190 8191 8192 8193 /* =============================================================== 8194 * 8195 * STRING 8196 * 8197 * ===============================================================*/ 8198 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8199 NK_API void 8200 nk_str_init_default(struct nk_str *str) 8201 { 8202 struct nk_allocator alloc; 8203 alloc.userdata.ptr = 0; 8204 alloc.alloc = nk_malloc; 8205 alloc.free = nk_mfree; 8206 nk_buffer_init(&str->buffer, &alloc, 32); 8207 str->len = 0; 8208 } 8209 #endif 8210 8211 NK_API void 8212 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size) 8213 { 8214 nk_buffer_init(&str->buffer, alloc, size); 8215 str->len = 0; 8216 } 8217 NK_API void 8218 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size) 8219 { 8220 nk_buffer_init_fixed(&str->buffer, memory, size); 8221 str->len = 0; 8222 } 8223 NK_API int 8224 nk_str_append_text_char(struct nk_str *s, const char *str, int len) 8225 { 8226 char *mem; 8227 NK_ASSERT(s); 8228 NK_ASSERT(str); 8229 if (!s || !str || !len) return 0; 8230 mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8231 if (!mem) return 0; 8232 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8233 s->len += nk_utf_len(str, len); 8234 return len; 8235 } 8236 NK_API int 8237 nk_str_append_str_char(struct nk_str *s, const char *str) 8238 { 8239 return nk_str_append_text_char(s, str, nk_strlen(str)); 8240 } 8241 NK_API int 8242 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len) 8243 { 8244 int i = 0; 8245 int byte_len = 0; 8246 nk_rune unicode; 8247 if (!str || !text || !len) return 0; 8248 for (i = 0; i < len; ++i) 8249 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8250 nk_str_append_text_char(str, text, byte_len); 8251 return len; 8252 } 8253 NK_API int 8254 nk_str_append_str_utf8(struct nk_str *str, const char *text) 8255 { 8256 int runes = 0; 8257 int byte_len = 0; 8258 int num_runes = 0; 8259 int glyph_len = 0; 8260 nk_rune unicode; 8261 if (!str || !text) return 0; 8262 8263 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8264 while (unicode != '\0' && glyph_len) { 8265 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8266 byte_len += glyph_len; 8267 num_runes++; 8268 } 8269 nk_str_append_text_char(str, text, byte_len); 8270 return runes; 8271 } 8272 NK_API int 8273 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) 8274 { 8275 int i = 0; 8276 int byte_len = 0; 8277 nk_glyph glyph; 8278 8279 NK_ASSERT(str); 8280 if (!str || !text || !len) return 0; 8281 for (i = 0; i < len; ++i) { 8282 byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE); 8283 if (!byte_len) break; 8284 nk_str_append_text_char(str, glyph, byte_len); 8285 } 8286 return len; 8287 } 8288 NK_API int 8289 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes) 8290 { 8291 int i = 0; 8292 nk_glyph glyph; 8293 int byte_len; 8294 NK_ASSERT(str); 8295 if (!str || !runes) return 0; 8296 while (runes[i] != '\0') { 8297 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8298 nk_str_append_text_char(str, glyph, byte_len); 8299 i++; 8300 } 8301 return i; 8302 } 8303 NK_API int 8304 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len) 8305 { 8306 int i; 8307 void *mem; 8308 char *src; 8309 char *dst; 8310 8311 int copylen; 8312 NK_ASSERT(s); 8313 NK_ASSERT(str); 8314 NK_ASSERT(len >= 0); 8315 if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0; 8316 if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) && 8317 (s->buffer.type == NK_BUFFER_FIXED)) return 0; 8318 8319 copylen = (int)s->buffer.allocated - pos; 8320 if (!copylen) { 8321 nk_str_append_text_char(s, str, len); 8322 return 1; 8323 } 8324 mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8325 if (!mem) return 0; 8326 8327 /* memmove */ 8328 NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0); 8329 NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0); 8330 dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1)); 8331 src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1)); 8332 for (i = 0; i < copylen; ++i) *dst-- = *src--; 8333 mem = nk_ptr_add(void, s->buffer.memory.ptr, pos); 8334 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8335 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8336 return 1; 8337 } 8338 NK_API int 8339 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len) 8340 { 8341 int glyph_len; 8342 nk_rune unicode; 8343 const char *begin; 8344 const char *buffer; 8345 8346 NK_ASSERT(str); 8347 NK_ASSERT(cstr); 8348 NK_ASSERT(len); 8349 if (!str || !cstr || !len) return 0; 8350 begin = nk_str_at_rune(str, pos, &unicode, &glyph_len); 8351 if (!str->len) 8352 return nk_str_append_text_char(str, cstr, len); 8353 buffer = nk_str_get_const(str); 8354 if (!begin) return 0; 8355 return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len); 8356 } 8357 NK_API int 8358 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len) 8359 { 8360 return nk_str_insert_text_utf8(str, pos, text, len); 8361 } 8362 NK_API int 8363 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text) 8364 { 8365 return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text)); 8366 } 8367 NK_API int 8368 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len) 8369 { 8370 int i = 0; 8371 int byte_len = 0; 8372 nk_rune unicode; 8373 8374 NK_ASSERT(str); 8375 NK_ASSERT(text); 8376 if (!str || !text || !len) return 0; 8377 for (i = 0; i < len; ++i) 8378 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8379 nk_str_insert_at_rune(str, pos, text, byte_len); 8380 return len; 8381 } 8382 NK_API int 8383 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) 8384 { 8385 int runes = 0; 8386 int byte_len = 0; 8387 int num_runes = 0; 8388 int glyph_len = 0; 8389 nk_rune unicode; 8390 if (!str || !text) return 0; 8391 8392 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8393 while (unicode != '\0' && glyph_len) { 8394 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8395 byte_len += glyph_len; 8396 num_runes++; 8397 } 8398 nk_str_insert_at_rune(str, pos, text, byte_len); 8399 return runes; 8400 } 8401 NK_API int 8402 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) 8403 { 8404 int i = 0; 8405 int byte_len = 0; 8406 nk_glyph glyph; 8407 8408 NK_ASSERT(str); 8409 if (!str || !runes || !len) return 0; 8410 for (i = 0; i < len; ++i) { 8411 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8412 if (!byte_len) break; 8413 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8414 } 8415 return len; 8416 } 8417 NK_API int 8418 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes) 8419 { 8420 int i = 0; 8421 nk_glyph glyph; 8422 int byte_len; 8423 NK_ASSERT(str); 8424 if (!str || !runes) return 0; 8425 while (runes[i] != '\0') { 8426 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8427 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8428 i++; 8429 } 8430 return i; 8431 } 8432 NK_API void 8433 nk_str_remove_chars(struct nk_str *s, int len) 8434 { 8435 NK_ASSERT(s); 8436 NK_ASSERT(len >= 0); 8437 if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return; 8438 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8439 s->buffer.allocated -= (nk_size)len; 8440 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8441 } 8442 NK_API void 8443 nk_str_remove_runes(struct nk_str *str, int len) 8444 { 8445 int index; 8446 const char *begin; 8447 const char *end; 8448 nk_rune unicode; 8449 8450 NK_ASSERT(str); 8451 NK_ASSERT(len >= 0); 8452 if (!str || len < 0) return; 8453 if (len >= str->len) { 8454 str->len = 0; 8455 return; 8456 } 8457 8458 index = str->len - len; 8459 begin = nk_str_at_rune(str, index, &unicode, &len); 8460 end = (const char*)str->buffer.memory.ptr + str->buffer.allocated; 8461 nk_str_remove_chars(str, (int)(end-begin)+1); 8462 } 8463 NK_API void 8464 nk_str_delete_chars(struct nk_str *s, int pos, int len) 8465 { 8466 NK_ASSERT(s); 8467 if (!s || !len || (nk_size)pos > s->buffer.allocated || 8468 (nk_size)(pos + len) > s->buffer.allocated) return; 8469 8470 if ((nk_size)(pos + len) < s->buffer.allocated) { 8471 /* memmove */ 8472 char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos); 8473 char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len); 8474 NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len)); 8475 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8476 s->buffer.allocated -= (nk_size)len; 8477 } else nk_str_remove_chars(s, len); 8478 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8479 } 8480 NK_API void 8481 nk_str_delete_runes(struct nk_str *s, int pos, int len) 8482 { 8483 char *temp; 8484 nk_rune unicode; 8485 char *begin; 8486 char *end; 8487 int unused; 8488 8489 NK_ASSERT(s); 8490 NK_ASSERT(s->len >= pos + len); 8491 if (s->len < pos + len) 8492 len = NK_CLAMP(0, (s->len - pos), s->len); 8493 if (!len) return; 8494 8495 temp = (char *)s->buffer.memory.ptr; 8496 begin = nk_str_at_rune(s, pos, &unicode, &unused); 8497 if (!begin) return; 8498 s->buffer.memory.ptr = begin; 8499 end = nk_str_at_rune(s, len, &unicode, &unused); 8500 s->buffer.memory.ptr = temp; 8501 if (!end) return; 8502 nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin)); 8503 } 8504 NK_API char* 8505 nk_str_at_char(struct nk_str *s, int pos) 8506 { 8507 NK_ASSERT(s); 8508 if (!s || pos > (int)s->buffer.allocated) return 0; 8509 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8510 } 8511 NK_API char* 8512 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len) 8513 { 8514 int i = 0; 8515 int src_len = 0; 8516 int glyph_len = 0; 8517 char *text; 8518 int text_len; 8519 8520 NK_ASSERT(str); 8521 NK_ASSERT(unicode); 8522 NK_ASSERT(len); 8523 8524 if (!str || !unicode || !len) return 0; 8525 if (pos < 0) { 8526 *unicode = 0; 8527 *len = 0; 8528 return 0; 8529 } 8530 8531 text = (char*)str->buffer.memory.ptr; 8532 text_len = (int)str->buffer.allocated; 8533 glyph_len = nk_utf_decode(text, unicode, text_len); 8534 while (glyph_len) { 8535 if (i == pos) { 8536 *len = glyph_len; 8537 break; 8538 } 8539 8540 i++; 8541 src_len = src_len + glyph_len; 8542 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8543 } 8544 if (i != pos) return 0; 8545 return text + src_len; 8546 } 8547 NK_API const char* 8548 nk_str_at_char_const(const struct nk_str *s, int pos) 8549 { 8550 NK_ASSERT(s); 8551 if (!s || pos > (int)s->buffer.allocated) return 0; 8552 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8553 } 8554 NK_API const char* 8555 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len) 8556 { 8557 int i = 0; 8558 int src_len = 0; 8559 int glyph_len = 0; 8560 char *text; 8561 int text_len; 8562 8563 NK_ASSERT(str); 8564 NK_ASSERT(unicode); 8565 NK_ASSERT(len); 8566 8567 if (!str || !unicode || !len) return 0; 8568 if (pos < 0) { 8569 *unicode = 0; 8570 *len = 0; 8571 return 0; 8572 } 8573 8574 text = (char*)str->buffer.memory.ptr; 8575 text_len = (int)str->buffer.allocated; 8576 glyph_len = nk_utf_decode(text, unicode, text_len); 8577 while (glyph_len) { 8578 if (i == pos) { 8579 *len = glyph_len; 8580 break; 8581 } 8582 8583 i++; 8584 src_len = src_len + glyph_len; 8585 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8586 } 8587 if (i != pos) return 0; 8588 return text + src_len; 8589 } 8590 NK_API nk_rune 8591 nk_str_rune_at(const struct nk_str *str, int pos) 8592 { 8593 int len; 8594 nk_rune unicode = 0; 8595 nk_str_at_const(str, pos, &unicode, &len); 8596 return unicode; 8597 } 8598 NK_API char* 8599 nk_str_get(struct nk_str *s) 8600 { 8601 NK_ASSERT(s); 8602 if (!s || !s->len || !s->buffer.allocated) return 0; 8603 return (char*)s->buffer.memory.ptr; 8604 } 8605 NK_API const char* 8606 nk_str_get_const(const struct nk_str *s) 8607 { 8608 NK_ASSERT(s); 8609 if (!s || !s->len || !s->buffer.allocated) return 0; 8610 return (const char*)s->buffer.memory.ptr; 8611 } 8612 NK_API int 8613 nk_str_len(struct nk_str *s) 8614 { 8615 NK_ASSERT(s); 8616 if (!s || !s->len || !s->buffer.allocated) return 0; 8617 return s->len; 8618 } 8619 NK_API int 8620 nk_str_len_char(struct nk_str *s) 8621 { 8622 NK_ASSERT(s); 8623 if (!s || !s->len || !s->buffer.allocated) return 0; 8624 return (int)s->buffer.allocated; 8625 } 8626 NK_API void 8627 nk_str_clear(struct nk_str *str) 8628 { 8629 NK_ASSERT(str); 8630 nk_buffer_clear(&str->buffer); 8631 str->len = 0; 8632 } 8633 NK_API void 8634 nk_str_free(struct nk_str *str) 8635 { 8636 NK_ASSERT(str); 8637 nk_buffer_free(&str->buffer); 8638 str->len = 0; 8639 } 8640 8641 8642 8643 8644 8645 /* ============================================================== 8646 * 8647 * DRAW 8648 * 8649 * ===============================================================*/ 8650 NK_LIB void 8651 nk_command_buffer_init(struct nk_command_buffer *cb, 8652 struct nk_buffer *b, enum nk_command_clipping clip) 8653 { 8654 NK_ASSERT(cb); 8655 NK_ASSERT(b); 8656 if (!cb || !b) return; 8657 cb->base = b; 8658 cb->use_clipping = (int)clip; 8659 cb->begin = b->allocated; 8660 cb->end = b->allocated; 8661 cb->last = b->allocated; 8662 } 8663 NK_LIB void 8664 nk_command_buffer_reset(struct nk_command_buffer *b) 8665 { 8666 NK_ASSERT(b); 8667 if (!b) return; 8668 b->begin = 0; 8669 b->end = 0; 8670 b->last = 0; 8671 b->clip = nk_null_rect; 8672 #ifdef NK_INCLUDE_COMMAND_USERDATA 8673 b->userdata.ptr = 0; 8674 #endif 8675 } 8676 NK_LIB void* 8677 nk_command_buffer_push(struct nk_command_buffer* b, 8678 enum nk_command_type t, nk_size size) 8679 { 8680 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command); 8681 struct nk_command *cmd; 8682 nk_size alignment; 8683 void *unaligned; 8684 void *memory; 8685 8686 NK_ASSERT(b); 8687 NK_ASSERT(b->base); 8688 if (!b) return 0; 8689 cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align); 8690 if (!cmd) return 0; 8691 8692 /* make sure the offset to the next command is aligned */ 8693 b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr); 8694 unaligned = (nk_byte*)cmd + size; 8695 memory = NK_ALIGN_PTR(unaligned, align); 8696 alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8697 #ifdef NK_ZERO_COMMAND_MEMORY 8698 NK_MEMSET(cmd, 0, size + alignment); 8699 #endif 8700 8701 cmd->type = t; 8702 cmd->next = b->base->allocated + alignment; 8703 #ifdef NK_INCLUDE_COMMAND_USERDATA 8704 cmd->userdata = b->userdata; 8705 #endif 8706 b->end = cmd->next; 8707 return cmd; 8708 } 8709 NK_API void 8710 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r) 8711 { 8712 struct nk_command_scissor *cmd; 8713 NK_ASSERT(b); 8714 if (!b) return; 8715 8716 b->clip.x = r.x; 8717 b->clip.y = r.y; 8718 b->clip.w = r.w; 8719 b->clip.h = r.h; 8720 cmd = (struct nk_command_scissor*) 8721 nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd)); 8722 8723 if (!cmd) return; 8724 cmd->x = (short)r.x; 8725 cmd->y = (short)r.y; 8726 cmd->w = (unsigned short)NK_MAX(0, r.w); 8727 cmd->h = (unsigned short)NK_MAX(0, r.h); 8728 } 8729 NK_API void 8730 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, 8731 float x1, float y1, float line_thickness, struct nk_color c) 8732 { 8733 struct nk_command_line *cmd; 8734 NK_ASSERT(b); 8735 if (!b || line_thickness <= 0) return; 8736 cmd = (struct nk_command_line*) 8737 nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd)); 8738 if (!cmd) return; 8739 cmd->line_thickness = (unsigned short)line_thickness; 8740 cmd->begin.x = (short)x0; 8741 cmd->begin.y = (short)y0; 8742 cmd->end.x = (short)x1; 8743 cmd->end.y = (short)y1; 8744 cmd->color = c; 8745 } 8746 NK_API void 8747 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay, 8748 float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, 8749 float bx, float by, float line_thickness, struct nk_color col) 8750 { 8751 struct nk_command_curve *cmd; 8752 NK_ASSERT(b); 8753 if (!b || col.a == 0 || line_thickness <= 0) return; 8754 8755 cmd = (struct nk_command_curve*) 8756 nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd)); 8757 if (!cmd) return; 8758 cmd->line_thickness = (unsigned short)line_thickness; 8759 cmd->begin.x = (short)ax; 8760 cmd->begin.y = (short)ay; 8761 cmd->ctrl[0].x = (short)ctrl0x; 8762 cmd->ctrl[0].y = (short)ctrl0y; 8763 cmd->ctrl[1].x = (short)ctrl1x; 8764 cmd->ctrl[1].y = (short)ctrl1y; 8765 cmd->end.x = (short)bx; 8766 cmd->end.y = (short)by; 8767 cmd->color = col; 8768 } 8769 NK_API void 8770 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect, 8771 float rounding, float line_thickness, struct nk_color c) 8772 { 8773 struct nk_command_rect *cmd; 8774 NK_ASSERT(b); 8775 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return; 8776 if (b->use_clipping) { 8777 const struct nk_rect *clip = &b->clip; 8778 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8779 clip->x, clip->y, clip->w, clip->h)) return; 8780 } 8781 cmd = (struct nk_command_rect*) 8782 nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd)); 8783 if (!cmd) return; 8784 cmd->rounding = (unsigned short)rounding; 8785 cmd->line_thickness = (unsigned short)line_thickness; 8786 cmd->x = (short)rect.x; 8787 cmd->y = (short)rect.y; 8788 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8789 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8790 cmd->color = c; 8791 } 8792 NK_API void 8793 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect, 8794 float rounding, struct nk_color c) 8795 { 8796 struct nk_command_rect_filled *cmd; 8797 NK_ASSERT(b); 8798 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; 8799 if (b->use_clipping) { 8800 const struct nk_rect *clip = &b->clip; 8801 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8802 clip->x, clip->y, clip->w, clip->h)) return; 8803 } 8804 8805 cmd = (struct nk_command_rect_filled*) 8806 nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd)); 8807 if (!cmd) return; 8808 cmd->rounding = (unsigned short)rounding; 8809 cmd->x = (short)rect.x; 8810 cmd->y = (short)rect.y; 8811 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8812 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8813 cmd->color = c; 8814 } 8815 NK_API void 8816 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect, 8817 struct nk_color left, struct nk_color top, struct nk_color right, 8818 struct nk_color bottom) 8819 { 8820 struct nk_command_rect_multi_color *cmd; 8821 NK_ASSERT(b); 8822 if (!b || rect.w == 0 || rect.h == 0) return; 8823 if (b->use_clipping) { 8824 const struct nk_rect *clip = &b->clip; 8825 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8826 clip->x, clip->y, clip->w, clip->h)) return; 8827 } 8828 8829 cmd = (struct nk_command_rect_multi_color*) 8830 nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd)); 8831 if (!cmd) return; 8832 cmd->x = (short)rect.x; 8833 cmd->y = (short)rect.y; 8834 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8835 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8836 cmd->left = left; 8837 cmd->top = top; 8838 cmd->right = right; 8839 cmd->bottom = bottom; 8840 } 8841 NK_API void 8842 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r, 8843 float line_thickness, struct nk_color c) 8844 { 8845 struct nk_command_circle *cmd; 8846 if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return; 8847 if (b->use_clipping) { 8848 const struct nk_rect *clip = &b->clip; 8849 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 8850 return; 8851 } 8852 8853 cmd = (struct nk_command_circle*) 8854 nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd)); 8855 if (!cmd) return; 8856 cmd->line_thickness = (unsigned short)line_thickness; 8857 cmd->x = (short)r.x; 8858 cmd->y = (short)r.y; 8859 cmd->w = (unsigned short)NK_MAX(r.w, 0); 8860 cmd->h = (unsigned short)NK_MAX(r.h, 0); 8861 cmd->color = c; 8862 } 8863 NK_API void 8864 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c) 8865 { 8866 struct nk_command_circle_filled *cmd; 8867 NK_ASSERT(b); 8868 if (!b || c.a == 0 || r.w == 0 || r.h == 0) return; 8869 if (b->use_clipping) { 8870 const struct nk_rect *clip = &b->clip; 8871 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 8872 return; 8873 } 8874 8875 cmd = (struct nk_command_circle_filled*) 8876 nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); 8877 if (!cmd) return; 8878 cmd->x = (short)r.x; 8879 cmd->y = (short)r.y; 8880 cmd->w = (unsigned short)NK_MAX(r.w, 0); 8881 cmd->h = (unsigned short)NK_MAX(r.h, 0); 8882 cmd->color = c; 8883 } 8884 NK_API void 8885 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 8886 float a_min, float a_max, float line_thickness, struct nk_color c) 8887 { 8888 struct nk_command_arc *cmd; 8889 if (!b || c.a == 0 || line_thickness <= 0) return; 8890 cmd = (struct nk_command_arc*) 8891 nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd)); 8892 if (!cmd) return; 8893 cmd->line_thickness = (unsigned short)line_thickness; 8894 cmd->cx = (short)cx; 8895 cmd->cy = (short)cy; 8896 cmd->r = (unsigned short)radius; 8897 cmd->a[0] = a_min; 8898 cmd->a[1] = a_max; 8899 cmd->color = c; 8900 } 8901 NK_API void 8902 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 8903 float a_min, float a_max, struct nk_color c) 8904 { 8905 struct nk_command_arc_filled *cmd; 8906 NK_ASSERT(b); 8907 if (!b || c.a == 0) return; 8908 cmd = (struct nk_command_arc_filled*) 8909 nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd)); 8910 if (!cmd) return; 8911 cmd->cx = (short)cx; 8912 cmd->cy = (short)cy; 8913 cmd->r = (unsigned short)radius; 8914 cmd->a[0] = a_min; 8915 cmd->a[1] = a_max; 8916 cmd->color = c; 8917 } 8918 NK_API void 8919 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 8920 float y1, float x2, float y2, float line_thickness, struct nk_color c) 8921 { 8922 struct nk_command_triangle *cmd; 8923 NK_ASSERT(b); 8924 if (!b || c.a == 0 || line_thickness <= 0) return; 8925 if (b->use_clipping) { 8926 const struct nk_rect *clip = &b->clip; 8927 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 8928 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 8929 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 8930 return; 8931 } 8932 8933 cmd = (struct nk_command_triangle*) 8934 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd)); 8935 if (!cmd) return; 8936 cmd->line_thickness = (unsigned short)line_thickness; 8937 cmd->a.x = (short)x0; 8938 cmd->a.y = (short)y0; 8939 cmd->b.x = (short)x1; 8940 cmd->b.y = (short)y1; 8941 cmd->c.x = (short)x2; 8942 cmd->c.y = (short)y2; 8943 cmd->color = c; 8944 } 8945 NK_API void 8946 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 8947 float y1, float x2, float y2, struct nk_color c) 8948 { 8949 struct nk_command_triangle_filled *cmd; 8950 NK_ASSERT(b); 8951 if (!b || c.a == 0) return; 8952 if (!b) return; 8953 if (b->use_clipping) { 8954 const struct nk_rect *clip = &b->clip; 8955 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 8956 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 8957 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 8958 return; 8959 } 8960 8961 cmd = (struct nk_command_triangle_filled*) 8962 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); 8963 if (!cmd) return; 8964 cmd->a.x = (short)x0; 8965 cmd->a.y = (short)y0; 8966 cmd->b.x = (short)x1; 8967 cmd->b.y = (short)y1; 8968 cmd->c.x = (short)x2; 8969 cmd->c.y = (short)y2; 8970 cmd->color = c; 8971 } 8972 NK_API void 8973 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count, 8974 float line_thickness, struct nk_color col) 8975 { 8976 int i; 8977 nk_size size = 0; 8978 struct nk_command_polygon *cmd; 8979 8980 NK_ASSERT(b); 8981 if (!b || col.a == 0 || line_thickness <= 0) return; 8982 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 8983 cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size); 8984 if (!cmd) return; 8985 cmd->color = col; 8986 cmd->line_thickness = (unsigned short)line_thickness; 8987 cmd->point_count = (unsigned short)point_count; 8988 for (i = 0; i < point_count; ++i) { 8989 cmd->points[i].x = (short)points[i*2]; 8990 cmd->points[i].y = (short)points[i*2+1]; 8991 } 8992 } 8993 NK_API void 8994 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count, 8995 struct nk_color col) 8996 { 8997 int i; 8998 nk_size size = 0; 8999 struct nk_command_polygon_filled *cmd; 9000 9001 NK_ASSERT(b); 9002 if (!b || col.a == 0) return; 9003 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9004 cmd = (struct nk_command_polygon_filled*) 9005 nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size); 9006 if (!cmd) return; 9007 cmd->color = col; 9008 cmd->point_count = (unsigned short)point_count; 9009 for (i = 0; i < point_count; ++i) { 9010 cmd->points[i].x = (short)points[i*2+0]; 9011 cmd->points[i].y = (short)points[i*2+1]; 9012 } 9013 } 9014 NK_API void 9015 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count, 9016 float line_thickness, struct nk_color col) 9017 { 9018 int i; 9019 nk_size size = 0; 9020 struct nk_command_polyline *cmd; 9021 9022 NK_ASSERT(b); 9023 if (!b || col.a == 0 || line_thickness <= 0) return; 9024 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9025 cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size); 9026 if (!cmd) return; 9027 cmd->color = col; 9028 cmd->point_count = (unsigned short)point_count; 9029 cmd->line_thickness = (unsigned short)line_thickness; 9030 for (i = 0; i < point_count; ++i) { 9031 cmd->points[i].x = (short)points[i*2]; 9032 cmd->points[i].y = (short)points[i*2+1]; 9033 } 9034 } 9035 NK_API void 9036 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r, 9037 const struct nk_image *img, struct nk_color col) 9038 { 9039 struct nk_command_image *cmd; 9040 NK_ASSERT(b); 9041 if (!b) return; 9042 if (b->use_clipping) { 9043 const struct nk_rect *c = &b->clip; 9044 if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h)) 9045 return; 9046 } 9047 9048 cmd = (struct nk_command_image*) 9049 nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd)); 9050 if (!cmd) return; 9051 cmd->x = (short)r.x; 9052 cmd->y = (short)r.y; 9053 cmd->w = (unsigned short)NK_MAX(0, r.w); 9054 cmd->h = (unsigned short)NK_MAX(0, r.h); 9055 cmd->img = *img; 9056 cmd->col = col; 9057 } 9058 NK_API void 9059 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r, 9060 nk_command_custom_callback cb, nk_handle usr) 9061 { 9062 struct nk_command_custom *cmd; 9063 NK_ASSERT(b); 9064 if (!b) return; 9065 if (b->use_clipping) { 9066 const struct nk_rect *c = &b->clip; 9067 if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h)) 9068 return; 9069 } 9070 9071 cmd = (struct nk_command_custom*) 9072 nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd)); 9073 if (!cmd) return; 9074 cmd->x = (short)r.x; 9075 cmd->y = (short)r.y; 9076 cmd->w = (unsigned short)NK_MAX(0, r.w); 9077 cmd->h = (unsigned short)NK_MAX(0, r.h); 9078 cmd->callback_data = usr; 9079 cmd->callback = cb; 9080 } 9081 NK_API void 9082 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r, 9083 const char *string, int length, const struct nk_user_font *font, 9084 struct nk_color bg, struct nk_color fg) 9085 { 9086 float text_width = 0; 9087 struct nk_command_text *cmd; 9088 9089 NK_ASSERT(b); 9090 NK_ASSERT(font); 9091 if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; 9092 if (b->use_clipping) { 9093 const struct nk_rect *c = &b->clip; 9094 if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h)) 9095 return; 9096 } 9097 9098 /* make sure text fits inside bounds */ 9099 text_width = font->width(font->userdata, font->height, string, length); 9100 if (text_width > r.w){ 9101 int glyphs = 0; 9102 float txt_width = (float)text_width; 9103 length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0); 9104 } 9105 9106 if (!length) return; 9107 cmd = (struct nk_command_text*) 9108 nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1)); 9109 if (!cmd) return; 9110 cmd->x = (short)r.x; 9111 cmd->y = (short)r.y; 9112 cmd->w = (unsigned short)r.w; 9113 cmd->h = (unsigned short)r.h; 9114 cmd->background = bg; 9115 cmd->foreground = fg; 9116 cmd->font = font; 9117 cmd->length = length; 9118 cmd->height = font->height; 9119 NK_MEMCPY(cmd->string, string, (nk_size)length); 9120 cmd->string[length] = '\0'; 9121 } 9122 9123 9124 9125 9126 9127 /* =============================================================== 9128 * 9129 * VERTEX 9130 * 9131 * ===============================================================*/ 9132 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 9133 NK_API void 9134 nk_draw_list_init(struct nk_draw_list *list) 9135 { 9136 nk_size i = 0; 9137 NK_ASSERT(list); 9138 if (!list) return; 9139 nk_zero(list, sizeof(*list)); 9140 for (i = 0; i < NK_LEN(list->circle_vtx); ++i) { 9141 const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI; 9142 list->circle_vtx[i].x = (float)NK_COS(a); 9143 list->circle_vtx[i].y = (float)NK_SIN(a); 9144 } 9145 } 9146 NK_API void 9147 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config, 9148 struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, 9149 enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa) 9150 { 9151 NK_ASSERT(canvas); 9152 NK_ASSERT(config); 9153 NK_ASSERT(cmds); 9154 NK_ASSERT(vertices); 9155 NK_ASSERT(elements); 9156 if (!canvas || !config || !cmds || !vertices || !elements) 9157 return; 9158 9159 canvas->buffer = cmds; 9160 canvas->config = *config; 9161 canvas->elements = elements; 9162 canvas->vertices = vertices; 9163 canvas->line_AA = line_aa; 9164 canvas->shape_AA = shape_aa; 9165 canvas->clip_rect = nk_null_rect; 9166 9167 canvas->cmd_offset = 0; 9168 canvas->element_count = 0; 9169 canvas->vertex_count = 0; 9170 canvas->cmd_offset = 0; 9171 canvas->cmd_count = 0; 9172 canvas->path_count = 0; 9173 } 9174 NK_API const struct nk_draw_command* 9175 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9176 { 9177 nk_byte *memory; 9178 nk_size offset; 9179 const struct nk_draw_command *cmd; 9180 9181 NK_ASSERT(buffer); 9182 if (!buffer || !buffer->size || !canvas->cmd_count) 9183 return 0; 9184 9185 memory = (nk_byte*)buffer->memory.ptr; 9186 offset = buffer->memory.size - canvas->cmd_offset; 9187 cmd = nk_ptr_add(const struct nk_draw_command, memory, offset); 9188 return cmd; 9189 } 9190 NK_API const struct nk_draw_command* 9191 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9192 { 9193 nk_size size; 9194 nk_size offset; 9195 nk_byte *memory; 9196 const struct nk_draw_command *end; 9197 9198 NK_ASSERT(buffer); 9199 NK_ASSERT(canvas); 9200 if (!buffer || !canvas) 9201 return 0; 9202 9203 memory = (nk_byte*)buffer->memory.ptr; 9204 size = buffer->memory.size; 9205 offset = size - canvas->cmd_offset; 9206 end = nk_ptr_add(const struct nk_draw_command, memory, offset); 9207 end -= (canvas->cmd_count-1); 9208 return end; 9209 } 9210 NK_API const struct nk_draw_command* 9211 nk__draw_list_next(const struct nk_draw_command *cmd, 9212 const struct nk_buffer *buffer, const struct nk_draw_list *canvas) 9213 { 9214 const struct nk_draw_command *end; 9215 NK_ASSERT(buffer); 9216 NK_ASSERT(canvas); 9217 if (!cmd || !buffer || !canvas) 9218 return 0; 9219 9220 end = nk__draw_list_end(canvas, buffer); 9221 if (cmd <= end) return 0; 9222 return (cmd-1); 9223 } 9224 NK_INTERN struct nk_vec2* 9225 nk_draw_list_alloc_path(struct nk_draw_list *list, int count) 9226 { 9227 struct nk_vec2 *points; 9228 NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2); 9229 NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2); 9230 points = (struct nk_vec2*) 9231 nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT, 9232 point_size * (nk_size)count, point_align); 9233 9234 if (!points) return 0; 9235 if (!list->path_offset) { 9236 void *memory = nk_buffer_memory(list->buffer); 9237 list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory); 9238 } 9239 list->path_count += (unsigned int)count; 9240 return points; 9241 } 9242 NK_INTERN struct nk_vec2 9243 nk_draw_list_path_last(struct nk_draw_list *list) 9244 { 9245 void *memory; 9246 struct nk_vec2 *point; 9247 NK_ASSERT(list->path_count); 9248 memory = nk_buffer_memory(list->buffer); 9249 point = nk_ptr_add(struct nk_vec2, memory, list->path_offset); 9250 point += (list->path_count-1); 9251 return *point; 9252 } 9253 NK_INTERN struct nk_draw_command* 9254 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip, 9255 nk_handle texture) 9256 { 9257 NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command); 9258 NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command); 9259 struct nk_draw_command *cmd; 9260 9261 NK_ASSERT(list); 9262 cmd = (struct nk_draw_command*) 9263 nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align); 9264 9265 if (!cmd) return 0; 9266 if (!list->cmd_count) { 9267 nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer); 9268 nk_size total = nk_buffer_total(list->buffer); 9269 memory = nk_ptr_add(nk_byte, memory, total); 9270 list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd); 9271 } 9272 9273 cmd->elem_count = 0; 9274 cmd->clip_rect = clip; 9275 cmd->texture = texture; 9276 #ifdef NK_INCLUDE_COMMAND_USERDATA 9277 cmd->userdata = list->userdata; 9278 #endif 9279 9280 list->cmd_count++; 9281 list->clip_rect = clip; 9282 return cmd; 9283 } 9284 NK_INTERN struct nk_draw_command* 9285 nk_draw_list_command_last(struct nk_draw_list *list) 9286 { 9287 void *memory; 9288 nk_size size; 9289 struct nk_draw_command *cmd; 9290 NK_ASSERT(list->cmd_count); 9291 9292 memory = nk_buffer_memory(list->buffer); 9293 size = nk_buffer_total(list->buffer); 9294 cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset); 9295 return (cmd - (list->cmd_count-1)); 9296 } 9297 NK_INTERN void 9298 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect) 9299 { 9300 NK_ASSERT(list); 9301 if (!list) return; 9302 if (!list->cmd_count) { 9303 nk_draw_list_push_command(list, rect, list->config.null.texture); 9304 } else { 9305 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9306 if (prev->elem_count == 0) 9307 prev->clip_rect = rect; 9308 nk_draw_list_push_command(list, rect, prev->texture); 9309 } 9310 } 9311 NK_INTERN void 9312 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture) 9313 { 9314 NK_ASSERT(list); 9315 if (!list) return; 9316 if (!list->cmd_count) { 9317 nk_draw_list_push_command(list, nk_null_rect, texture); 9318 } else { 9319 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9320 if (prev->elem_count == 0) { 9321 prev->texture = texture; 9322 #ifdef NK_INCLUDE_COMMAND_USERDATA 9323 prev->userdata = list->userdata; 9324 #endif 9325 } else if (prev->texture.id != texture.id 9326 #ifdef NK_INCLUDE_COMMAND_USERDATA 9327 || prev->userdata.id != list->userdata.id 9328 #endif 9329 ) nk_draw_list_push_command(list, prev->clip_rect, texture); 9330 } 9331 } 9332 #ifdef NK_INCLUDE_COMMAND_USERDATA 9333 NK_API void 9334 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata) 9335 { 9336 list->userdata = userdata; 9337 } 9338 #endif 9339 NK_INTERN void* 9340 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) 9341 { 9342 void *vtx; 9343 NK_ASSERT(list); 9344 if (!list) return 0; 9345 vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, 9346 list->config.vertex_size*count, list->config.vertex_alignment); 9347 if (!vtx) return 0; 9348 list->vertex_count += (unsigned int)count; 9349 9350 /* This assert triggers because your are drawing a lot of stuff and nuklear 9351 * defined `nk_draw_index` as `nk_ushort` to safe space be default. 9352 * 9353 * So you reached the maximum number of indicies or rather vertexes. 9354 * To solve this issue please change typdef `nk_draw_index` to `nk_uint` 9355 * and don't forget to specify the new element size in your drawing 9356 * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements` 9357 * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`. 9358 * Sorry for the inconvenience. */ 9359 NK_ASSERT((sizeof(nk_draw_index) == 2 && list->vertex_count < NK_USHORT_MAX && 9360 "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem")); 9361 return vtx; 9362 } 9363 NK_INTERN nk_draw_index* 9364 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count) 9365 { 9366 nk_draw_index *ids; 9367 struct nk_draw_command *cmd; 9368 NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index); 9369 NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index); 9370 NK_ASSERT(list); 9371 if (!list) return 0; 9372 9373 ids = (nk_draw_index*) 9374 nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align); 9375 if (!ids) return 0; 9376 cmd = nk_draw_list_command_last(list); 9377 list->element_count += (unsigned int)count; 9378 cmd->elem_count += (unsigned int)count; 9379 return ids; 9380 } 9381 NK_INTERN int 9382 nk_draw_vertex_layout_element_is_end_of_layout( 9383 const struct nk_draw_vertex_layout_element *element) 9384 { 9385 return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT || 9386 element->format == NK_FORMAT_COUNT); 9387 } 9388 NK_INTERN void 9389 nk_draw_vertex_color(void *attr, const float *vals, 9390 enum nk_draw_vertex_layout_format format) 9391 { 9392 /* if this triggers you tried to provide a value format for a color */ 9393 float val[4]; 9394 NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN); 9395 NK_ASSERT(format <= NK_FORMAT_COLOR_END); 9396 if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return; 9397 9398 val[0] = NK_SATURATE(vals[0]); 9399 val[1] = NK_SATURATE(vals[1]); 9400 val[2] = NK_SATURATE(vals[2]); 9401 val[3] = NK_SATURATE(vals[3]); 9402 9403 switch (format) { 9404 default: NK_ASSERT(0 && "Invalid vertex layout color format"); break; 9405 case NK_FORMAT_R8G8B8A8: 9406 case NK_FORMAT_R8G8B8: { 9407 struct nk_color col = nk_rgba_fv(val); 9408 NK_MEMCPY(attr, &col.r, sizeof(col)); 9409 } break; 9410 case NK_FORMAT_B8G8R8A8: { 9411 struct nk_color col = nk_rgba_fv(val); 9412 struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a); 9413 NK_MEMCPY(attr, &bgra, sizeof(bgra)); 9414 } break; 9415 case NK_FORMAT_R16G15B16: { 9416 nk_ushort col[3]; 9417 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9418 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9419 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9420 NK_MEMCPY(attr, col, sizeof(col)); 9421 } break; 9422 case NK_FORMAT_R16G15B16A16: { 9423 nk_ushort col[4]; 9424 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9425 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9426 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9427 col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX); 9428 NK_MEMCPY(attr, col, sizeof(col)); 9429 } break; 9430 case NK_FORMAT_R32G32B32: { 9431 nk_uint col[3]; 9432 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9433 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9434 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9435 NK_MEMCPY(attr, col, sizeof(col)); 9436 } break; 9437 case NK_FORMAT_R32G32B32A32: { 9438 nk_uint col[4]; 9439 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9440 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9441 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9442 col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX); 9443 NK_MEMCPY(attr, col, sizeof(col)); 9444 } break; 9445 case NK_FORMAT_R32G32B32A32_FLOAT: 9446 NK_MEMCPY(attr, val, sizeof(float)*4); 9447 break; 9448 case NK_FORMAT_R32G32B32A32_DOUBLE: { 9449 double col[4]; 9450 col[0] = (double)val[0]; 9451 col[1] = (double)val[1]; 9452 col[2] = (double)val[2]; 9453 col[3] = (double)val[3]; 9454 NK_MEMCPY(attr, col, sizeof(col)); 9455 } break; 9456 case NK_FORMAT_RGB32: 9457 case NK_FORMAT_RGBA32: { 9458 struct nk_color col = nk_rgba_fv(val); 9459 nk_uint color = nk_color_u32(col); 9460 NK_MEMCPY(attr, &color, sizeof(color)); 9461 } break; } 9462 } 9463 NK_INTERN void 9464 nk_draw_vertex_element(void *dst, const float *values, int value_count, 9465 enum nk_draw_vertex_layout_format format) 9466 { 9467 int value_index; 9468 void *attribute = dst; 9469 /* if this triggers you tried to provide a color format for a value */ 9470 NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN); 9471 if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return; 9472 for (value_index = 0; value_index < value_count; ++value_index) { 9473 switch (format) { 9474 default: NK_ASSERT(0 && "invalid vertex layout format"); break; 9475 case NK_FORMAT_SCHAR: { 9476 char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX); 9477 NK_MEMCPY(attribute, &value, sizeof(value)); 9478 attribute = (void*)((char*)attribute + sizeof(char)); 9479 } break; 9480 case NK_FORMAT_SSHORT: { 9481 nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX); 9482 NK_MEMCPY(attribute, &value, sizeof(value)); 9483 attribute = (void*)((char*)attribute + sizeof(value)); 9484 } break; 9485 case NK_FORMAT_SINT: { 9486 nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX); 9487 NK_MEMCPY(attribute, &value, sizeof(value)); 9488 attribute = (void*)((char*)attribute + sizeof(nk_int)); 9489 } break; 9490 case NK_FORMAT_UCHAR: { 9491 unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX); 9492 NK_MEMCPY(attribute, &value, sizeof(value)); 9493 attribute = (void*)((char*)attribute + sizeof(unsigned char)); 9494 } break; 9495 case NK_FORMAT_USHORT: { 9496 nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX); 9497 NK_MEMCPY(attribute, &value, sizeof(value)); 9498 attribute = (void*)((char*)attribute + sizeof(value)); 9499 } break; 9500 case NK_FORMAT_UINT: { 9501 nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX); 9502 NK_MEMCPY(attribute, &value, sizeof(value)); 9503 attribute = (void*)((char*)attribute + sizeof(nk_uint)); 9504 } break; 9505 case NK_FORMAT_FLOAT: 9506 NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index])); 9507 attribute = (void*)((char*)attribute + sizeof(float)); 9508 break; 9509 case NK_FORMAT_DOUBLE: { 9510 double value = (double)values[value_index]; 9511 NK_MEMCPY(attribute, &value, sizeof(value)); 9512 attribute = (void*)((char*)attribute + sizeof(double)); 9513 } break; 9514 } 9515 } 9516 } 9517 NK_INTERN void* 9518 nk_draw_vertex(void *dst, const struct nk_convert_config *config, 9519 struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color) 9520 { 9521 void *result = (void*)((char*)dst + config->vertex_size); 9522 const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout; 9523 while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) { 9524 void *address = (void*)((char*)dst + elem_iter->offset); 9525 switch (elem_iter->attribute) { 9526 case NK_VERTEX_ATTRIBUTE_COUNT: 9527 default: NK_ASSERT(0 && "wrong element attribute"); break; 9528 case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break; 9529 case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break; 9530 case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break; 9531 } 9532 elem_iter++; 9533 } 9534 return result; 9535 } 9536 NK_API void 9537 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points, 9538 const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed, 9539 float thickness, enum nk_anti_aliasing aliasing) 9540 { 9541 nk_size count; 9542 int thick_line; 9543 struct nk_colorf col; 9544 struct nk_colorf col_trans; 9545 NK_ASSERT(list); 9546 if (!list || points_count < 2) return; 9547 9548 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9549 count = points_count; 9550 if (!closed) count = points_count-1; 9551 thick_line = thickness > 1.0f; 9552 9553 #ifdef NK_INCLUDE_COMMAND_USERDATA 9554 nk_draw_list_push_userdata(list, list->userdata); 9555 #endif 9556 9557 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9558 nk_color_fv(&col.r, color); 9559 col_trans = col; 9560 col_trans.a = 0; 9561 9562 if (aliasing == NK_ANTI_ALIASING_ON) { 9563 /* ANTI-ALIASED STROKE */ 9564 const float AA_SIZE = 1.0f; 9565 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9566 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9567 9568 /* allocate vertices and elements */ 9569 nk_size i1 = 0; 9570 nk_size vertex_offset; 9571 nk_size index = list->vertex_count; 9572 9573 const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12); 9574 const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3); 9575 9576 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9577 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9578 9579 nk_size size; 9580 struct nk_vec2 *normals, *temp; 9581 if (!vtx || !ids) return; 9582 9583 /* temporary allocate normals + points */ 9584 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9585 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9586 size = pnt_size * ((thick_line) ? 5 : 3) * points_count; 9587 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9588 if (!normals) return; 9589 temp = normals + points_count; 9590 9591 /* make sure vertex pointer is still correct */ 9592 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9593 9594 /* calculate normals */ 9595 for (i1 = 0; i1 < count; ++i1) { 9596 const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9597 struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]); 9598 float len; 9599 9600 /* vec2 inverted length */ 9601 len = nk_vec2_len_sqr(diff); 9602 if (len != 0.0f) 9603 len = nk_inv_sqrt(len); 9604 else len = 1.0f; 9605 9606 diff = nk_vec2_muls(diff, len); 9607 normals[i1].x = diff.y; 9608 normals[i1].y = -diff.x; 9609 } 9610 9611 if (!closed) 9612 normals[points_count-1] = normals[points_count-2]; 9613 9614 if (!thick_line) { 9615 nk_size idx1, i; 9616 if (!closed) { 9617 struct nk_vec2 d; 9618 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9619 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9620 d = nk_vec2_muls(normals[points_count-1], AA_SIZE); 9621 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d); 9622 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d); 9623 } 9624 9625 /* fill elements */ 9626 idx1 = index; 9627 for (i1 = 0; i1 < count; i1++) { 9628 struct nk_vec2 dm; 9629 float dmr2; 9630 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9631 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3); 9632 9633 /* average normals */ 9634 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9635 dmr2 = dm.x * dm.x + dm.y* dm.y; 9636 if (dmr2 > 0.000001f) { 9637 float scale = 1.0f/dmr2; 9638 scale = NK_MIN(100.0f, scale); 9639 dm = nk_vec2_muls(dm, scale); 9640 } 9641 9642 dm = nk_vec2_muls(dm, AA_SIZE); 9643 temp[i2*2+0] = nk_vec2_add(points[i2], dm); 9644 temp[i2*2+1] = nk_vec2_sub(points[i2], dm); 9645 9646 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0); 9647 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9648 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0); 9649 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9650 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9651 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1); 9652 ids += 12; 9653 idx1 = idx2; 9654 } 9655 9656 /* fill vertices */ 9657 for (i = 0; i < points_count; ++i) { 9658 const struct nk_vec2 uv = list->config.null.uv; 9659 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); 9660 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); 9661 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); 9662 } 9663 } else { 9664 nk_size idx1, i; 9665 const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; 9666 if (!closed) { 9667 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE); 9668 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness); 9669 9670 temp[0] = nk_vec2_add(points[0], d1); 9671 temp[1] = nk_vec2_add(points[0], d2); 9672 temp[2] = nk_vec2_sub(points[0], d2); 9673 temp[3] = nk_vec2_sub(points[0], d1); 9674 9675 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE); 9676 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness); 9677 9678 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1); 9679 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2); 9680 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2); 9681 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1); 9682 } 9683 9684 /* add all elements */ 9685 idx1 = index; 9686 for (i1 = 0; i1 < count; ++i1) { 9687 struct nk_vec2 dm_out, dm_in; 9688 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1); 9689 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4); 9690 9691 /* average normals */ 9692 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9693 float dmr2 = dm.x * dm.x + dm.y* dm.y; 9694 if (dmr2 > 0.000001f) { 9695 float scale = 1.0f/dmr2; 9696 scale = NK_MIN(100.0f, scale); 9697 dm = nk_vec2_muls(dm, scale); 9698 } 9699 9700 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE)); 9701 dm_in = nk_vec2_muls(dm, half_inner_thickness); 9702 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out); 9703 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in); 9704 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in); 9705 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out); 9706 9707 /* add indexes */ 9708 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1); 9709 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9710 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1); 9711 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9712 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9713 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1); 9714 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2); 9715 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3); 9716 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2); 9717 ids += 18; 9718 idx1 = idx2; 9719 } 9720 9721 /* add vertices */ 9722 for (i = 0; i < points_count; ++i) { 9723 const struct nk_vec2 uv = list->config.null.uv; 9724 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); 9725 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); 9726 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); 9727 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans); 9728 } 9729 } 9730 /* free temporary normals + points */ 9731 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 9732 } else { 9733 /* NON ANTI-ALIASED STROKE */ 9734 nk_size i1 = 0; 9735 nk_size idx = list->vertex_count; 9736 const nk_size idx_count = count * 6; 9737 const nk_size vtx_count = count * 4; 9738 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9739 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9740 if (!vtx || !ids) return; 9741 9742 for (i1 = 0; i1 < count; ++i1) { 9743 float dx, dy; 9744 const struct nk_vec2 uv = list->config.null.uv; 9745 const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; 9746 const struct nk_vec2 p1 = points[i1]; 9747 const struct nk_vec2 p2 = points[i2]; 9748 struct nk_vec2 diff = nk_vec2_sub(p2, p1); 9749 float len; 9750 9751 /* vec2 inverted length */ 9752 len = nk_vec2_len_sqr(diff); 9753 if (len != 0.0f) 9754 len = nk_inv_sqrt(len); 9755 else len = 1.0f; 9756 diff = nk_vec2_muls(diff, len); 9757 9758 /* add vertices */ 9759 dx = diff.x * (thickness * 0.5f); 9760 dy = diff.y * (thickness * 0.5f); 9761 9762 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col); 9763 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col); 9764 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col); 9765 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col); 9766 9767 ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1); 9768 ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0); 9769 ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3); 9770 9771 ids += 6; 9772 idx += 4; 9773 } 9774 } 9775 } 9776 NK_API void 9777 nk_draw_list_fill_poly_convex(struct nk_draw_list *list, 9778 const struct nk_vec2 *points, const unsigned int points_count, 9779 struct nk_color color, enum nk_anti_aliasing aliasing) 9780 { 9781 struct nk_colorf col; 9782 struct nk_colorf col_trans; 9783 9784 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9785 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9786 NK_ASSERT(list); 9787 if (!list || points_count < 3) return; 9788 9789 #ifdef NK_INCLUDE_COMMAND_USERDATA 9790 nk_draw_list_push_userdata(list, list->userdata); 9791 #endif 9792 9793 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9794 nk_color_fv(&col.r, color); 9795 col_trans = col; 9796 col_trans.a = 0; 9797 9798 if (aliasing == NK_ANTI_ALIASING_ON) { 9799 nk_size i = 0; 9800 nk_size i0 = 0; 9801 nk_size i1 = 0; 9802 9803 const float AA_SIZE = 1.0f; 9804 nk_size vertex_offset = 0; 9805 nk_size index = list->vertex_count; 9806 9807 const nk_size idx_count = (points_count-2)*3 + points_count*6; 9808 const nk_size vtx_count = (points_count*2); 9809 9810 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9811 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9812 9813 nk_size size = 0; 9814 struct nk_vec2 *normals = 0; 9815 unsigned int vtx_inner_idx = (unsigned int)(index + 0); 9816 unsigned int vtx_outer_idx = (unsigned int)(index + 1); 9817 if (!vtx || !ids) return; 9818 9819 /* temporary allocate normals */ 9820 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9821 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9822 size = pnt_size * points_count; 9823 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9824 if (!normals) return; 9825 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9826 9827 /* add elements */ 9828 for (i = 2; i < points_count; i++) { 9829 ids[0] = (nk_draw_index)(vtx_inner_idx); 9830 ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1)); 9831 ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1)); 9832 ids += 3; 9833 } 9834 9835 /* compute normals */ 9836 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 9837 struct nk_vec2 p0 = points[i0]; 9838 struct nk_vec2 p1 = points[i1]; 9839 struct nk_vec2 diff = nk_vec2_sub(p1, p0); 9840 9841 /* vec2 inverted length */ 9842 float len = nk_vec2_len_sqr(diff); 9843 if (len != 0.0f) 9844 len = nk_inv_sqrt(len); 9845 else len = 1.0f; 9846 diff = nk_vec2_muls(diff, len); 9847 9848 normals[i0].x = diff.y; 9849 normals[i0].y = -diff.x; 9850 } 9851 9852 /* add vertices + indexes */ 9853 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 9854 const struct nk_vec2 uv = list->config.null.uv; 9855 struct nk_vec2 n0 = normals[i0]; 9856 struct nk_vec2 n1 = normals[i1]; 9857 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); 9858 float dmr2 = dm.x*dm.x + dm.y*dm.y; 9859 if (dmr2 > 0.000001f) { 9860 float scale = 1.0f / dmr2; 9861 scale = NK_MIN(scale, 100.0f); 9862 dm = nk_vec2_muls(dm, scale); 9863 } 9864 dm = nk_vec2_muls(dm, AA_SIZE * 0.5f); 9865 9866 /* add vertices */ 9867 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col); 9868 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans); 9869 9870 /* add indexes */ 9871 ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 9872 ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1)); 9873 ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 9874 ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 9875 ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1)); 9876 ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 9877 ids += 6; 9878 } 9879 /* free temporary normals + points */ 9880 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 9881 } else { 9882 nk_size i = 0; 9883 nk_size index = list->vertex_count; 9884 const nk_size idx_count = (points_count-2)*3; 9885 const nk_size vtx_count = points_count; 9886 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9887 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9888 9889 if (!vtx || !ids) return; 9890 for (i = 0; i < vtx_count; ++i) 9891 vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col); 9892 for (i = 2; i < points_count; ++i) { 9893 ids[0] = (nk_draw_index)index; 9894 ids[1] = (nk_draw_index)(index+ i - 1); 9895 ids[2] = (nk_draw_index)(index+i); 9896 ids += 3; 9897 } 9898 } 9899 } 9900 NK_API void 9901 nk_draw_list_path_clear(struct nk_draw_list *list) 9902 { 9903 NK_ASSERT(list); 9904 if (!list) return; 9905 nk_buffer_reset(list->buffer, NK_BUFFER_FRONT); 9906 list->path_count = 0; 9907 list->path_offset = 0; 9908 } 9909 NK_API void 9910 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos) 9911 { 9912 struct nk_vec2 *points = 0; 9913 struct nk_draw_command *cmd = 0; 9914 NK_ASSERT(list); 9915 if (!list) return; 9916 if (!list->cmd_count) 9917 nk_draw_list_add_clip(list, nk_null_rect); 9918 9919 cmd = nk_draw_list_command_last(list); 9920 if (cmd && cmd->texture.ptr != list->config.null.texture.ptr) 9921 nk_draw_list_push_image(list, list->config.null.texture); 9922 9923 points = nk_draw_list_alloc_path(list, 1); 9924 if (!points) return; 9925 points[0] = pos; 9926 } 9927 NK_API void 9928 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center, 9929 float radius, int a_min, int a_max) 9930 { 9931 int a = 0; 9932 NK_ASSERT(list); 9933 if (!list) return; 9934 if (a_min <= a_max) { 9935 for (a = a_min; a <= a_max; a++) { 9936 const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)]; 9937 const float x = center.x + c.x * radius; 9938 const float y = center.y + c.y * radius; 9939 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 9940 } 9941 } 9942 } 9943 NK_API void 9944 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center, 9945 float radius, float a_min, float a_max, unsigned int segments) 9946 { 9947 unsigned int i = 0; 9948 NK_ASSERT(list); 9949 if (!list) return; 9950 if (radius == 0.0f) return; 9951 9952 /* This algorithm for arc drawing relies on these two trigonometric identities[1]: 9953 sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) 9954 cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) 9955 9956 Two coordinates (x, y) of a point on a circle centered on 9957 the origin can be written in polar form as: 9958 x = r * cos(a) 9959 y = r * sin(a) 9960 where r is the radius of the circle, 9961 a is the angle between (x, y) and the origin. 9962 9963 This allows us to rotate the coordinates around the 9964 origin by an angle b using the following transformation: 9965 x' = r * cos(a + b) = x * cos(b) - y * sin(b) 9966 y' = r * sin(a + b) = y * cos(b) + x * sin(b) 9967 9968 [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities 9969 */ 9970 {const float d_angle = (a_max - a_min) / (float)segments; 9971 const float sin_d = (float)NK_SIN(d_angle); 9972 const float cos_d = (float)NK_COS(d_angle); 9973 9974 float cx = (float)NK_COS(a_min) * radius; 9975 float cy = (float)NK_SIN(a_min) * radius; 9976 for(i = 0; i <= segments; ++i) { 9977 float new_cx, new_cy; 9978 const float x = center.x + cx; 9979 const float y = center.y + cy; 9980 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 9981 9982 new_cx = cx * cos_d - cy * sin_d; 9983 new_cy = cy * cos_d + cx * sin_d; 9984 cx = new_cx; 9985 cy = new_cy; 9986 }} 9987 } 9988 NK_API void 9989 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a, 9990 struct nk_vec2 b, float rounding) 9991 { 9992 float r; 9993 NK_ASSERT(list); 9994 if (!list) return; 9995 r = rounding; 9996 r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x)); 9997 r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y)); 9998 9999 if (r == 0.0f) { 10000 nk_draw_list_path_line_to(list, a); 10001 nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y)); 10002 nk_draw_list_path_line_to(list, b); 10003 nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y)); 10004 } else { 10005 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9); 10006 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12); 10007 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3); 10008 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6); 10009 } 10010 } 10011 NK_API void 10012 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2, 10013 struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments) 10014 { 10015 float t_step; 10016 unsigned int i_step; 10017 struct nk_vec2 p1; 10018 10019 NK_ASSERT(list); 10020 NK_ASSERT(list->path_count); 10021 if (!list || !list->path_count) return; 10022 num_segments = NK_MAX(num_segments, 1); 10023 10024 p1 = nk_draw_list_path_last(list); 10025 t_step = 1.0f/(float)num_segments; 10026 for (i_step = 1; i_step <= num_segments; ++i_step) { 10027 float t = t_step * (float)i_step; 10028 float u = 1.0f - t; 10029 float w1 = u*u*u; 10030 float w2 = 3*u*u*t; 10031 float w3 = 3*u*t*t; 10032 float w4 = t * t *t; 10033 float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; 10034 float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; 10035 nk_draw_list_path_line_to(list, nk_vec2(x,y)); 10036 } 10037 } 10038 NK_API void 10039 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color) 10040 { 10041 struct nk_vec2 *points; 10042 NK_ASSERT(list); 10043 if (!list) return; 10044 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10045 nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA); 10046 nk_draw_list_path_clear(list); 10047 } 10048 NK_API void 10049 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color, 10050 enum nk_draw_list_stroke closed, float thickness) 10051 { 10052 struct nk_vec2 *points; 10053 NK_ASSERT(list); 10054 if (!list) return; 10055 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10056 nk_draw_list_stroke_poly_line(list, points, list->path_count, color, 10057 closed, thickness, list->config.line_AA); 10058 nk_draw_list_path_clear(list); 10059 } 10060 NK_API void 10061 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a, 10062 struct nk_vec2 b, struct nk_color col, float thickness) 10063 { 10064 NK_ASSERT(list); 10065 if (!list || !col.a) return; 10066 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10067 nk_draw_list_path_line_to(list, a); 10068 nk_draw_list_path_line_to(list, b); 10069 } else { 10070 nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f))); 10071 nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f))); 10072 } 10073 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10074 } 10075 NK_API void 10076 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect, 10077 struct nk_color col, float rounding) 10078 { 10079 NK_ASSERT(list); 10080 if (!list || !col.a) return; 10081 10082 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10083 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10084 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10085 } else { 10086 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10087 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10088 } nk_draw_list_path_fill(list, col); 10089 } 10090 NK_API void 10091 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect, 10092 struct nk_color col, float rounding, float thickness) 10093 { 10094 NK_ASSERT(list); 10095 if (!list || !col.a) return; 10096 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10097 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10098 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10099 } else { 10100 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10101 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10102 } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10103 } 10104 NK_API void 10105 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect, 10106 struct nk_color left, struct nk_color top, struct nk_color right, 10107 struct nk_color bottom) 10108 { 10109 void *vtx; 10110 struct nk_colorf col_left, col_top; 10111 struct nk_colorf col_right, col_bottom; 10112 nk_draw_index *idx; 10113 nk_draw_index index; 10114 10115 nk_color_fv(&col_left.r, left); 10116 nk_color_fv(&col_right.r, right); 10117 nk_color_fv(&col_top.r, top); 10118 nk_color_fv(&col_bottom.r, bottom); 10119 10120 NK_ASSERT(list); 10121 if (!list) return; 10122 10123 nk_draw_list_push_image(list, list->config.null.texture); 10124 index = (nk_draw_index)list->vertex_count; 10125 vtx = nk_draw_list_alloc_vertices(list, 4); 10126 idx = nk_draw_list_alloc_elements(list, 6); 10127 if (!vtx || !idx) return; 10128 10129 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10130 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10131 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10132 10133 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left); 10134 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top); 10135 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right); 10136 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom); 10137 } 10138 NK_API void 10139 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10140 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col) 10141 { 10142 NK_ASSERT(list); 10143 if (!list || !col.a) return; 10144 nk_draw_list_path_line_to(list, a); 10145 nk_draw_list_path_line_to(list, b); 10146 nk_draw_list_path_line_to(list, c); 10147 nk_draw_list_path_fill(list, col); 10148 } 10149 NK_API void 10150 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10151 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness) 10152 { 10153 NK_ASSERT(list); 10154 if (!list || !col.a) return; 10155 nk_draw_list_path_line_to(list, a); 10156 nk_draw_list_path_line_to(list, b); 10157 nk_draw_list_path_line_to(list, c); 10158 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10159 } 10160 NK_API void 10161 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center, 10162 float radius, struct nk_color col, unsigned int segs) 10163 { 10164 float a_max; 10165 NK_ASSERT(list); 10166 if (!list || !col.a) return; 10167 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10168 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10169 nk_draw_list_path_fill(list, col); 10170 } 10171 NK_API void 10172 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center, 10173 float radius, struct nk_color col, unsigned int segs, float thickness) 10174 { 10175 float a_max; 10176 NK_ASSERT(list); 10177 if (!list || !col.a) return; 10178 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10179 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10180 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10181 } 10182 NK_API void 10183 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0, 10184 struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, 10185 struct nk_color col, unsigned int segments, float thickness) 10186 { 10187 NK_ASSERT(list); 10188 if (!list || !col.a) return; 10189 nk_draw_list_path_line_to(list, p0); 10190 nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments); 10191 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10192 } 10193 NK_INTERN void 10194 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a, 10195 struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc, 10196 struct nk_color color) 10197 { 10198 void *vtx; 10199 struct nk_vec2 uvb; 10200 struct nk_vec2 uvd; 10201 struct nk_vec2 b; 10202 struct nk_vec2 d; 10203 10204 struct nk_colorf col; 10205 nk_draw_index *idx; 10206 nk_draw_index index; 10207 NK_ASSERT(list); 10208 if (!list) return; 10209 10210 nk_color_fv(&col.r, color); 10211 uvb = nk_vec2(uvc.x, uva.y); 10212 uvd = nk_vec2(uva.x, uvc.y); 10213 b = nk_vec2(c.x, a.y); 10214 d = nk_vec2(a.x, c.y); 10215 10216 index = (nk_draw_index)list->vertex_count; 10217 vtx = nk_draw_list_alloc_vertices(list, 4); 10218 idx = nk_draw_list_alloc_elements(list, 6); 10219 if (!vtx || !idx) return; 10220 10221 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10222 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10223 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10224 10225 vtx = nk_draw_vertex(vtx, &list->config, a, uva, col); 10226 vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col); 10227 vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col); 10228 vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col); 10229 } 10230 NK_API void 10231 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture, 10232 struct nk_rect rect, struct nk_color color) 10233 { 10234 NK_ASSERT(list); 10235 if (!list) return; 10236 /* push new command with given texture */ 10237 nk_draw_list_push_image(list, texture.handle); 10238 if (nk_image_is_subimage(&texture)) { 10239 /* add region inside of the texture */ 10240 struct nk_vec2 uv[2]; 10241 uv[0].x = (float)texture.region[0]/(float)texture.w; 10242 uv[0].y = (float)texture.region[1]/(float)texture.h; 10243 uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w; 10244 uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h; 10245 nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10246 nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color); 10247 } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10248 nk_vec2(rect.x + rect.w, rect.y + rect.h), 10249 nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color); 10250 } 10251 NK_API void 10252 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font, 10253 struct nk_rect rect, const char *text, int len, float font_height, 10254 struct nk_color fg) 10255 { 10256 float x = 0; 10257 int text_len = 0; 10258 nk_rune unicode = 0; 10259 nk_rune next = 0; 10260 int glyph_len = 0; 10261 int next_glyph_len = 0; 10262 struct nk_user_font_glyph g; 10263 10264 NK_ASSERT(list); 10265 if (!list || !len || !text) return; 10266 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 10267 list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return; 10268 10269 nk_draw_list_push_image(list, font->texture); 10270 x = rect.x; 10271 glyph_len = nk_utf_decode(text, &unicode, len); 10272 if (!glyph_len) return; 10273 10274 /* draw every glyph image */ 10275 fg.a = (nk_byte)((float)fg.a * list->config.global_alpha); 10276 while (text_len < len && glyph_len) { 10277 float gx, gy, gh, gw; 10278 float char_width = 0; 10279 if (unicode == NK_UTF_INVALID) break; 10280 10281 /* query currently drawn glyph information */ 10282 next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); 10283 font->query(font->userdata, font_height, &g, unicode, 10284 (next == NK_UTF_INVALID) ? '\0' : next); 10285 10286 /* calculate and draw glyph drawing rectangle and image */ 10287 gx = x + g.offset.x; 10288 gy = rect.y + g.offset.y; 10289 gw = g.width; gh = g.height; 10290 char_width = g.xadvance; 10291 nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh), 10292 g.uv[0], g.uv[1], fg); 10293 10294 /* offset next glyph */ 10295 text_len += glyph_len; 10296 x += char_width; 10297 glyph_len = next_glyph_len; 10298 unicode = next; 10299 } 10300 } 10301 NK_API nk_flags 10302 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 10303 struct nk_buffer *vertices, struct nk_buffer *elements, 10304 const struct nk_convert_config *config) 10305 { 10306 nk_flags res = NK_CONVERT_SUCCESS; 10307 const struct nk_command *cmd; 10308 NK_ASSERT(ctx); 10309 NK_ASSERT(cmds); 10310 NK_ASSERT(vertices); 10311 NK_ASSERT(elements); 10312 NK_ASSERT(config); 10313 NK_ASSERT(config->vertex_layout); 10314 NK_ASSERT(config->vertex_size); 10315 if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout) 10316 return NK_CONVERT_INVALID_PARAM; 10317 10318 nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements, 10319 config->line_AA, config->shape_AA); 10320 nk_foreach(cmd, ctx) 10321 { 10322 #ifdef NK_INCLUDE_COMMAND_USERDATA 10323 ctx->draw_list.userdata = cmd->userdata; 10324 #endif 10325 switch (cmd->type) { 10326 case NK_COMMAND_NOP: break; 10327 case NK_COMMAND_SCISSOR: { 10328 const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd; 10329 nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h)); 10330 } break; 10331 case NK_COMMAND_LINE: { 10332 const struct nk_command_line *l = (const struct nk_command_line*)cmd; 10333 nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y), 10334 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness); 10335 } break; 10336 case NK_COMMAND_CURVE: { 10337 const struct nk_command_curve *q = (const struct nk_command_curve*)cmd; 10338 nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y), 10339 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x, 10340 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color, 10341 config->curve_segment_count, q->line_thickness); 10342 } break; 10343 case NK_COMMAND_RECT: { 10344 const struct nk_command_rect *r = (const struct nk_command_rect*)cmd; 10345 nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10346 r->color, (float)r->rounding, r->line_thickness); 10347 } break; 10348 case NK_COMMAND_RECT_FILLED: { 10349 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd; 10350 nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10351 r->color, (float)r->rounding); 10352 } break; 10353 case NK_COMMAND_RECT_MULTI_COLOR: { 10354 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd; 10355 nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10356 r->left, r->top, r->right, r->bottom); 10357 } break; 10358 case NK_COMMAND_CIRCLE: { 10359 const struct nk_command_circle *c = (const struct nk_command_circle*)cmd; 10360 nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10361 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10362 config->circle_segment_count, c->line_thickness); 10363 } break; 10364 case NK_COMMAND_CIRCLE_FILLED: { 10365 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; 10366 nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10367 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10368 config->circle_segment_count); 10369 } break; 10370 case NK_COMMAND_ARC: { 10371 const struct nk_command_arc *c = (const struct nk_command_arc*)cmd; 10372 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10373 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10374 c->a[0], c->a[1], config->arc_segment_count); 10375 nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness); 10376 } break; 10377 case NK_COMMAND_ARC_FILLED: { 10378 const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd; 10379 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10380 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10381 c->a[0], c->a[1], config->arc_segment_count); 10382 nk_draw_list_path_fill(&ctx->draw_list, c->color); 10383 } break; 10384 case NK_COMMAND_TRIANGLE: { 10385 const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; 10386 nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10387 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color, 10388 t->line_thickness); 10389 } break; 10390 case NK_COMMAND_TRIANGLE_FILLED: { 10391 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; 10392 nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10393 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color); 10394 } break; 10395 case NK_COMMAND_POLYGON: { 10396 int i; 10397 const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd; 10398 for (i = 0; i < p->point_count; ++i) { 10399 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10400 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10401 } 10402 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness); 10403 } break; 10404 case NK_COMMAND_POLYGON_FILLED: { 10405 int i; 10406 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; 10407 for (i = 0; i < p->point_count; ++i) { 10408 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10409 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10410 } 10411 nk_draw_list_path_fill(&ctx->draw_list, p->color); 10412 } break; 10413 case NK_COMMAND_POLYLINE: { 10414 int i; 10415 const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd; 10416 for (i = 0; i < p->point_count; ++i) { 10417 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10418 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10419 } 10420 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness); 10421 } break; 10422 case NK_COMMAND_TEXT: { 10423 const struct nk_command_text *t = (const struct nk_command_text*)cmd; 10424 nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h), 10425 t->string, t->length, t->height, t->foreground); 10426 } break; 10427 case NK_COMMAND_IMAGE: { 10428 const struct nk_command_image *i = (const struct nk_command_image*)cmd; 10429 nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col); 10430 } break; 10431 case NK_COMMAND_CUSTOM: { 10432 const struct nk_command_custom *c = (const struct nk_command_custom*)cmd; 10433 c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data); 10434 } break; 10435 default: break; 10436 } 10437 } 10438 res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0; 10439 res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0; 10440 res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0; 10441 return res; 10442 } 10443 NK_API const struct nk_draw_command* 10444 nk__draw_begin(const struct nk_context *ctx, 10445 const struct nk_buffer *buffer) 10446 { 10447 return nk__draw_list_begin(&ctx->draw_list, buffer); 10448 } 10449 NK_API const struct nk_draw_command* 10450 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer) 10451 { 10452 return nk__draw_list_end(&ctx->draw_list, buffer); 10453 } 10454 NK_API const struct nk_draw_command* 10455 nk__draw_next(const struct nk_draw_command *cmd, 10456 const struct nk_buffer *buffer, const struct nk_context *ctx) 10457 { 10458 return nk__draw_list_next(cmd, buffer, &ctx->draw_list); 10459 } 10460 #endif 10461 10462 10463 10464 10465 10466 #ifdef NK_INCLUDE_FONT_BAKING 10467 /* ------------------------------------------------------------- 10468 * 10469 * RECT PACK 10470 * 10471 * --------------------------------------------------------------*/ 10472 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */ 10473 /* Sean Barrett 2014 */ 10474 #define NK_RP__MAXVAL 0xffff 10475 typedef unsigned short nk_rp_coord; 10476 10477 struct nk_rp_rect { 10478 /* reserved for your use: */ 10479 int id; 10480 /* input: */ 10481 nk_rp_coord w, h; 10482 /* output: */ 10483 nk_rp_coord x, y; 10484 int was_packed; 10485 /* non-zero if valid packing */ 10486 }; /* 16 bytes, nominally */ 10487 10488 struct nk_rp_node { 10489 nk_rp_coord x,y; 10490 struct nk_rp_node *next; 10491 }; 10492 10493 struct nk_rp_context { 10494 int width; 10495 int height; 10496 int align; 10497 int init_mode; 10498 int heuristic; 10499 int num_nodes; 10500 struct nk_rp_node *active_head; 10501 struct nk_rp_node *free_head; 10502 struct nk_rp_node extra[2]; 10503 /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */ 10504 }; 10505 10506 struct nk_rp__findresult { 10507 int x,y; 10508 struct nk_rp_node **prev_link; 10509 }; 10510 10511 enum NK_RP_HEURISTIC { 10512 NK_RP_HEURISTIC_Skyline_default=0, 10513 NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default, 10514 NK_RP_HEURISTIC_Skyline_BF_sortHeight 10515 }; 10516 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1}; 10517 10518 NK_INTERN void 10519 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem) 10520 { 10521 if (allow_out_of_mem) 10522 /* if it's ok to run out of memory, then don't bother aligning them; */ 10523 /* this gives better packing, but may fail due to OOM (even though */ 10524 /* the rectangles easily fit). @TODO a smarter approach would be to only */ 10525 /* quantize once we've hit OOM, then we could get rid of this parameter. */ 10526 context->align = 1; 10527 else { 10528 /* if it's not ok to run out of memory, then quantize the widths */ 10529 /* so that num_nodes is always enough nodes. */ 10530 /* */ 10531 /* I.e. num_nodes * align >= width */ 10532 /* align >= width / num_nodes */ 10533 /* align = ceil(width/num_nodes) */ 10534 context->align = (context->width + context->num_nodes-1) / context->num_nodes; 10535 } 10536 } 10537 NK_INTERN void 10538 nk_rp_init_target(struct nk_rp_context *context, int width, int height, 10539 struct nk_rp_node *nodes, int num_nodes) 10540 { 10541 int i; 10542 #ifndef STBRP_LARGE_RECTS 10543 NK_ASSERT(width <= 0xffff && height <= 0xffff); 10544 #endif 10545 10546 for (i=0; i < num_nodes-1; ++i) 10547 nodes[i].next = &nodes[i+1]; 10548 nodes[i].next = 0; 10549 context->init_mode = NK_RP__INIT_skyline; 10550 context->heuristic = NK_RP_HEURISTIC_Skyline_default; 10551 context->free_head = &nodes[0]; 10552 context->active_head = &context->extra[0]; 10553 context->width = width; 10554 context->height = height; 10555 context->num_nodes = num_nodes; 10556 nk_rp_setup_allow_out_of_mem(context, 0); 10557 10558 /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */ 10559 context->extra[0].x = 0; 10560 context->extra[0].y = 0; 10561 context->extra[0].next = &context->extra[1]; 10562 context->extra[1].x = (nk_rp_coord) width; 10563 context->extra[1].y = 65535; 10564 context->extra[1].next = 0; 10565 } 10566 /* find minimum y position if it starts at x1 */ 10567 NK_INTERN int 10568 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first, 10569 int x0, int width, int *pwaste) 10570 { 10571 struct nk_rp_node *node = first; 10572 int x1 = x0 + width; 10573 int min_y, visited_width, waste_area; 10574 NK_ASSERT(first->x <= x0); 10575 NK_UNUSED(c); 10576 10577 NK_ASSERT(node->next->x > x0); 10578 /* we ended up handling this in the caller for efficiency */ 10579 NK_ASSERT(node->x <= x0); 10580 10581 min_y = 0; 10582 waste_area = 0; 10583 visited_width = 0; 10584 while (node->x < x1) 10585 { 10586 if (node->y > min_y) { 10587 /* raise min_y higher. */ 10588 /* we've accounted for all waste up to min_y, */ 10589 /* but we'll now add more waste for everything we've visited */ 10590 waste_area += visited_width * (node->y - min_y); 10591 min_y = node->y; 10592 /* the first time through, visited_width might be reduced */ 10593 if (node->x < x0) 10594 visited_width += node->next->x - x0; 10595 else 10596 visited_width += node->next->x - node->x; 10597 } else { 10598 /* add waste area */ 10599 int under_width = node->next->x - node->x; 10600 if (under_width + visited_width > width) 10601 under_width = width - visited_width; 10602 waste_area += under_width * (min_y - node->y); 10603 visited_width += under_width; 10604 } 10605 node = node->next; 10606 } 10607 *pwaste = waste_area; 10608 return min_y; 10609 } 10610 NK_INTERN struct nk_rp__findresult 10611 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height) 10612 { 10613 int best_waste = (1<<30), best_x, best_y = (1 << 30); 10614 struct nk_rp__findresult fr; 10615 struct nk_rp_node **prev, *node, *tail, **best = 0; 10616 10617 /* align to multiple of c->align */ 10618 width = (width + c->align - 1); 10619 width -= width % c->align; 10620 NK_ASSERT(width % c->align == 0); 10621 10622 node = c->active_head; 10623 prev = &c->active_head; 10624 while (node->x + width <= c->width) { 10625 int y,waste; 10626 y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste); 10627 /* actually just want to test BL */ 10628 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) { 10629 /* bottom left */ 10630 if (y < best_y) { 10631 best_y = y; 10632 best = prev; 10633 } 10634 } else { 10635 /* best-fit */ 10636 if (y + height <= c->height) { 10637 /* can only use it if it first vertically */ 10638 if (y < best_y || (y == best_y && waste < best_waste)) { 10639 best_y = y; 10640 best_waste = waste; 10641 best = prev; 10642 } 10643 } 10644 } 10645 prev = &node->next; 10646 node = node->next; 10647 } 10648 best_x = (best == 0) ? 0 : (*best)->x; 10649 10650 /* if doing best-fit (BF), we also have to try aligning right edge to each node position */ 10651 /* */ 10652 /* e.g, if fitting */ 10653 /* */ 10654 /* ____________________ */ 10655 /* |____________________| */ 10656 /* */ 10657 /* into */ 10658 /* */ 10659 /* | | */ 10660 /* | ____________| */ 10661 /* |____________| */ 10662 /* */ 10663 /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */ 10664 /* */ 10665 /* This makes BF take about 2x the time */ 10666 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight) 10667 { 10668 tail = c->active_head; 10669 node = c->active_head; 10670 prev = &c->active_head; 10671 /* find first node that's admissible */ 10672 while (tail->x < width) 10673 tail = tail->next; 10674 while (tail) 10675 { 10676 int xpos = tail->x - width; 10677 int y,waste; 10678 NK_ASSERT(xpos >= 0); 10679 /* find the left position that matches this */ 10680 while (node->next->x <= xpos) { 10681 prev = &node->next; 10682 node = node->next; 10683 } 10684 NK_ASSERT(node->next->x > xpos && node->x <= xpos); 10685 y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste); 10686 if (y + height < c->height) { 10687 if (y <= best_y) { 10688 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 10689 best_x = xpos; 10690 NK_ASSERT(y <= best_y); 10691 best_y = y; 10692 best_waste = waste; 10693 best = prev; 10694 } 10695 } 10696 } 10697 tail = tail->next; 10698 } 10699 } 10700 fr.prev_link = best; 10701 fr.x = best_x; 10702 fr.y = best_y; 10703 return fr; 10704 } 10705 NK_INTERN struct nk_rp__findresult 10706 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height) 10707 { 10708 /* find best position according to heuristic */ 10709 struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height); 10710 struct nk_rp_node *node, *cur; 10711 10712 /* bail if: */ 10713 /* 1. it failed */ 10714 /* 2. the best node doesn't fit (we don't always check this) */ 10715 /* 3. we're out of memory */ 10716 if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) { 10717 res.prev_link = 0; 10718 return res; 10719 } 10720 10721 /* on success, create new node */ 10722 node = context->free_head; 10723 node->x = (nk_rp_coord) res.x; 10724 node->y = (nk_rp_coord) (res.y + height); 10725 10726 context->free_head = node->next; 10727 10728 /* insert the new node into the right starting point, and */ 10729 /* let 'cur' point to the remaining nodes needing to be */ 10730 /* stitched back in */ 10731 cur = *res.prev_link; 10732 if (cur->x < res.x) { 10733 /* preserve the existing one, so start testing with the next one */ 10734 struct nk_rp_node *next = cur->next; 10735 cur->next = node; 10736 cur = next; 10737 } else { 10738 *res.prev_link = node; 10739 } 10740 10741 /* from here, traverse cur and free the nodes, until we get to one */ 10742 /* that shouldn't be freed */ 10743 while (cur->next && cur->next->x <= res.x + width) { 10744 struct nk_rp_node *next = cur->next; 10745 /* move the current node to the free list */ 10746 cur->next = context->free_head; 10747 context->free_head = cur; 10748 cur = next; 10749 } 10750 /* stitch the list back in */ 10751 node->next = cur; 10752 10753 if (cur->x < res.x + width) 10754 cur->x = (nk_rp_coord) (res.x + width); 10755 return res; 10756 } 10757 NK_INTERN int 10758 nk_rect_height_compare(const void *a, const void *b) 10759 { 10760 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; 10761 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; 10762 if (p->h > q->h) 10763 return -1; 10764 if (p->h < q->h) 10765 return 1; 10766 return (p->w > q->w) ? -1 : (p->w < q->w); 10767 } 10768 NK_INTERN int 10769 nk_rect_original_order(const void *a, const void *b) 10770 { 10771 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; 10772 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; 10773 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 10774 } 10775 NK_INTERN void 10776 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*)) 10777 { 10778 /* iterative quick sort */ 10779 #define NK_MAX_SORT_STACK 64 10780 unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0; 10781 unsigned seed = len/2 * 69069+1; 10782 for (;;) { 10783 for (; left+1 < len; len++) { 10784 struct nk_rp_rect pivot, tmp; 10785 if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0]; 10786 pivot = array[left+seed%(len-left)]; 10787 seed = seed * 69069 + 1; 10788 stack[pos++] = len; 10789 for (right = left-1;;) { 10790 while (cmp(&array[++right], &pivot) < 0); 10791 while (cmp(&pivot, &array[--len]) < 0); 10792 if (right >= len) break; 10793 tmp = array[right]; 10794 array[right] = array[len]; 10795 array[len] = tmp; 10796 } 10797 } 10798 if (pos == 0) break; 10799 left = len; 10800 len = stack[--pos]; 10801 } 10802 #undef NK_MAX_SORT_STACK 10803 } 10804 NK_INTERN void 10805 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects) 10806 { 10807 int i; 10808 /* we use the 'was_packed' field internally to allow sorting/unsorting */ 10809 for (i=0; i < num_rects; ++i) { 10810 rects[i].was_packed = i; 10811 } 10812 10813 /* sort according to heuristic */ 10814 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare); 10815 10816 for (i=0; i < num_rects; ++i) { 10817 struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 10818 if (fr.prev_link) { 10819 rects[i].x = (nk_rp_coord) fr.x; 10820 rects[i].y = (nk_rp_coord) fr.y; 10821 } else { 10822 rects[i].x = rects[i].y = NK_RP__MAXVAL; 10823 } 10824 } 10825 10826 /* unsort */ 10827 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order); 10828 10829 /* set was_packed flags */ 10830 for (i=0; i < num_rects; ++i) 10831 rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL); 10832 } 10833 10834 /* 10835 * ============================================================== 10836 * 10837 * TRUETYPE 10838 * 10839 * =============================================================== 10840 */ 10841 /* stb_truetype.h - v1.07 - public domain */ 10842 #define NK_TT_MAX_OVERSAMPLE 8 10843 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1) 10844 10845 struct nk_tt_bakedchar { 10846 unsigned short x0,y0,x1,y1; 10847 /* coordinates of bbox in bitmap */ 10848 float xoff,yoff,xadvance; 10849 }; 10850 10851 struct nk_tt_aligned_quad{ 10852 float x0,y0,s0,t0; /* top-left */ 10853 float x1,y1,s1,t1; /* bottom-right */ 10854 }; 10855 10856 struct nk_tt_packedchar { 10857 unsigned short x0,y0,x1,y1; 10858 /* coordinates of bbox in bitmap */ 10859 float xoff,yoff,xadvance; 10860 float xoff2,yoff2; 10861 }; 10862 10863 struct nk_tt_pack_range { 10864 float font_size; 10865 int first_unicode_codepoint_in_range; 10866 /* if non-zero, then the chars are continuous, and this is the first codepoint */ 10867 int *array_of_unicode_codepoints; 10868 /* if non-zero, then this is an array of unicode codepoints */ 10869 int num_chars; 10870 struct nk_tt_packedchar *chardata_for_range; /* output */ 10871 unsigned char h_oversample, v_oversample; 10872 /* don't set these, they're used internally */ 10873 }; 10874 10875 struct nk_tt_pack_context { 10876 void *pack_info; 10877 int width; 10878 int height; 10879 int stride_in_bytes; 10880 int padding; 10881 unsigned int h_oversample, v_oversample; 10882 unsigned char *pixels; 10883 void *nodes; 10884 }; 10885 10886 struct nk_tt_fontinfo { 10887 const unsigned char* data; /* pointer to .ttf file */ 10888 int fontstart;/* offset of start of font */ 10889 int numGlyphs;/* number of glyphs, needed for range checking */ 10890 int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */ 10891 int index_map; /* a cmap mapping for our chosen character encoding */ 10892 int indexToLocFormat; /* format needed to map from glyph index to glyph */ 10893 }; 10894 10895 enum { 10896 NK_TT_vmove=1, 10897 NK_TT_vline, 10898 NK_TT_vcurve 10899 }; 10900 10901 struct nk_tt_vertex { 10902 short x,y,cx,cy; 10903 unsigned char type,padding; 10904 }; 10905 10906 struct nk_tt__bitmap{ 10907 int w,h,stride; 10908 unsigned char *pixels; 10909 }; 10910 10911 struct nk_tt__hheap_chunk { 10912 struct nk_tt__hheap_chunk *next; 10913 }; 10914 struct nk_tt__hheap { 10915 struct nk_allocator alloc; 10916 struct nk_tt__hheap_chunk *head; 10917 void *first_free; 10918 int num_remaining_in_head_chunk; 10919 }; 10920 10921 struct nk_tt__edge { 10922 float x0,y0, x1,y1; 10923 int invert; 10924 }; 10925 10926 struct nk_tt__active_edge { 10927 struct nk_tt__active_edge *next; 10928 float fx,fdx,fdy; 10929 float direction; 10930 float sy; 10931 float ey; 10932 }; 10933 struct nk_tt__point {float x,y;}; 10934 10935 #define NK_TT_MACSTYLE_DONTCARE 0 10936 #define NK_TT_MACSTYLE_BOLD 1 10937 #define NK_TT_MACSTYLE_ITALIC 2 10938 #define NK_TT_MACSTYLE_UNDERSCORE 4 10939 #define NK_TT_MACSTYLE_NONE 8 10940 /* <= not same as 0, this makes us check the bitfield is 0 */ 10941 10942 enum { /* platformID */ 10943 NK_TT_PLATFORM_ID_UNICODE =0, 10944 NK_TT_PLATFORM_ID_MAC =1, 10945 NK_TT_PLATFORM_ID_ISO =2, 10946 NK_TT_PLATFORM_ID_MICROSOFT =3 10947 }; 10948 10949 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */ 10950 NK_TT_UNICODE_EID_UNICODE_1_0 =0, 10951 NK_TT_UNICODE_EID_UNICODE_1_1 =1, 10952 NK_TT_UNICODE_EID_ISO_10646 =2, 10953 NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3, 10954 NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4 10955 }; 10956 10957 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */ 10958 NK_TT_MS_EID_SYMBOL =0, 10959 NK_TT_MS_EID_UNICODE_BMP =1, 10960 NK_TT_MS_EID_SHIFTJIS =2, 10961 NK_TT_MS_EID_UNICODE_FULL =10 10962 }; 10963 10964 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */ 10965 NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4, 10966 NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5, 10967 NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6, 10968 NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7 10969 }; 10970 10971 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */ 10972 /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */ 10973 NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410, 10974 NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411, 10975 NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412, 10976 NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419, 10977 NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409, 10978 NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D 10979 }; 10980 10981 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */ 10982 NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11, 10983 NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23, 10984 NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32, 10985 NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 , 10986 NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 , 10987 NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33, 10988 NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19 10989 }; 10990 10991 #define nk_ttBYTE(p) (* (const nk_byte *) (p)) 10992 #define nk_ttCHAR(p) (* (const char *) (p)) 10993 10994 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE) 10995 #define nk_ttUSHORT(p) (* (nk_ushort *) (p)) 10996 #define nk_ttSHORT(p) (* (nk_short *) (p)) 10997 #define nk_ttULONG(p) (* (nk_uint *) (p)) 10998 #define nk_ttLONG(p) (* (nk_int *) (p)) 10999 #else 11000 static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); } 11001 static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); } 11002 static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); } 11003 #endif 11004 11005 #define nk_tt_tag4(p,c0,c1,c2,c3)\ 11006 ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) 11007 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3]) 11008 11009 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, 11010 int glyph_index, struct nk_tt_vertex **pvertices); 11011 11012 NK_INTERN nk_uint 11013 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag) 11014 { 11015 /* @OPTIMIZE: binary search */ 11016 nk_int num_tables = nk_ttUSHORT(data+fontstart+4); 11017 nk_uint tabledir = fontstart + 12; 11018 nk_int i; 11019 for (i = 0; i < num_tables; ++i) { 11020 nk_uint loc = tabledir + (nk_uint)(16*i); 11021 if (nk_tt_tag(data+loc+0, tag)) 11022 return nk_ttULONG(data+loc+8); 11023 } 11024 return 0; 11025 } 11026 NK_INTERN int 11027 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart) 11028 { 11029 nk_uint cmap, t; 11030 nk_int i,numTables; 11031 const nk_byte *data = (const nk_byte *) data2; 11032 11033 info->data = data; 11034 info->fontstart = fontstart; 11035 11036 cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */ 11037 info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */ 11038 info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */ 11039 info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */ 11040 info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */ 11041 info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */ 11042 info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */ 11043 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) 11044 return 0; 11045 11046 t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp"); 11047 if (t) info->numGlyphs = nk_ttUSHORT(data+t+4); 11048 else info->numGlyphs = 0xffff; 11049 11050 /* find a cmap encoding table we understand *now* to avoid searching */ 11051 /* later. (todo: could make this installable) */ 11052 /* the same regardless of glyph. */ 11053 numTables = nk_ttUSHORT(data + cmap + 2); 11054 info->index_map = 0; 11055 for (i=0; i < numTables; ++i) 11056 { 11057 nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i; 11058 /* find an encoding we understand: */ 11059 switch(nk_ttUSHORT(data+encoding_record)) { 11060 case NK_TT_PLATFORM_ID_MICROSOFT: 11061 switch (nk_ttUSHORT(data+encoding_record+2)) { 11062 case NK_TT_MS_EID_UNICODE_BMP: 11063 case NK_TT_MS_EID_UNICODE_FULL: 11064 /* MS/Unicode */ 11065 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); 11066 break; 11067 default: break; 11068 } break; 11069 case NK_TT_PLATFORM_ID_UNICODE: 11070 /* Mac/iOS has these */ 11071 /* all the encodingIDs are unicode, so we don't bother to check it */ 11072 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); 11073 break; 11074 default: break; 11075 } 11076 } 11077 if (info->index_map == 0) 11078 return 0; 11079 info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50); 11080 return 1; 11081 } 11082 NK_INTERN int 11083 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint) 11084 { 11085 const nk_byte *data = info->data; 11086 nk_uint index_map = (nk_uint)info->index_map; 11087 11088 nk_ushort format = nk_ttUSHORT(data + index_map + 0); 11089 if (format == 0) { /* apple byte encoding */ 11090 nk_int bytes = nk_ttUSHORT(data + index_map + 2); 11091 if (unicode_codepoint < bytes-6) 11092 return nk_ttBYTE(data + index_map + 6 + unicode_codepoint); 11093 return 0; 11094 } else if (format == 6) { 11095 nk_uint first = nk_ttUSHORT(data + index_map + 6); 11096 nk_uint count = nk_ttUSHORT(data + index_map + 8); 11097 if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count) 11098 return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2); 11099 return 0; 11100 } else if (format == 2) { 11101 NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */ 11102 return 0; 11103 } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */ 11104 nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1; 11105 nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1; 11106 nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10); 11107 nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1; 11108 11109 /* do a binary search of the segments */ 11110 nk_uint endCount = index_map + 14; 11111 nk_uint search = endCount; 11112 11113 if (unicode_codepoint > 0xffff) 11114 return 0; 11115 11116 /* they lie from endCount .. endCount + segCount */ 11117 /* but searchRange is the nearest power of two, so... */ 11118 if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2)) 11119 search += (nk_uint)(rangeShift*2); 11120 11121 /* now decrement to bias correctly to find smallest */ 11122 search -= 2; 11123 while (entrySelector) { 11124 nk_ushort end; 11125 searchRange >>= 1; 11126 end = nk_ttUSHORT(data + search + searchRange*2); 11127 if (unicode_codepoint > end) 11128 search += (nk_uint)(searchRange*2); 11129 --entrySelector; 11130 } 11131 search += 2; 11132 11133 { 11134 nk_ushort offset, start; 11135 nk_ushort item = (nk_ushort) ((search - endCount) >> 1); 11136 11137 NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item)); 11138 start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); 11139 if (unicode_codepoint < start) 11140 return 0; 11141 11142 offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); 11143 if (offset == 0) 11144 return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); 11145 11146 return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); 11147 } 11148 } else if (format == 12 || format == 13) { 11149 nk_uint ngroups = nk_ttULONG(data+index_map+12); 11150 nk_int low,high; 11151 low = 0; high = (nk_int)ngroups; 11152 /* Binary search the right group. */ 11153 while (low < high) { 11154 nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */ 11155 nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12); 11156 nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4); 11157 if ((nk_uint) unicode_codepoint < start_char) 11158 high = mid; 11159 else if ((nk_uint) unicode_codepoint > end_char) 11160 low = mid+1; 11161 else { 11162 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8); 11163 if (format == 12) 11164 return (int)start_glyph + (int)unicode_codepoint - (int)start_char; 11165 else /* format == 13 */ 11166 return (int)start_glyph; 11167 } 11168 } 11169 return 0; /* not found */ 11170 } 11171 /* @TODO */ 11172 NK_ASSERT(0); 11173 return 0; 11174 } 11175 NK_INTERN void 11176 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy) 11177 { 11178 v->type = type; 11179 v->x = (nk_short) x; 11180 v->y = (nk_short) y; 11181 v->cx = (nk_short) cx; 11182 v->cy = (nk_short) cy; 11183 } 11184 NK_INTERN int 11185 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index) 11186 { 11187 int g1,g2; 11188 if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */ 11189 if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */ 11190 11191 if (info->indexToLocFormat == 0) { 11192 g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; 11193 g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; 11194 } else { 11195 g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4); 11196 g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4); 11197 } 11198 return g1==g2 ? -1 : g1; /* if length is 0, return -1 */ 11199 } 11200 NK_INTERN int 11201 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index, 11202 int *x0, int *y0, int *x1, int *y1) 11203 { 11204 int g = nk_tt__GetGlyfOffset(info, glyph_index); 11205 if (g < 0) return 0; 11206 11207 if (x0) *x0 = nk_ttSHORT(info->data + g + 2); 11208 if (y0) *y0 = nk_ttSHORT(info->data + g + 4); 11209 if (x1) *x1 = nk_ttSHORT(info->data + g + 6); 11210 if (y1) *y1 = nk_ttSHORT(info->data + g + 8); 11211 return 1; 11212 } 11213 NK_INTERN int 11214 nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off, 11215 int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy) 11216 { 11217 if (start_off) { 11218 if (was_off) 11219 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); 11220 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy); 11221 } else { 11222 if (was_off) 11223 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy); 11224 else 11225 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0); 11226 } 11227 return num_vertices; 11228 } 11229 NK_INTERN int 11230 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, 11231 int glyph_index, struct nk_tt_vertex **pvertices) 11232 { 11233 nk_short numberOfContours; 11234 const nk_byte *endPtsOfContours; 11235 const nk_byte *data = info->data; 11236 struct nk_tt_vertex *vertices=0; 11237 int num_vertices=0; 11238 int g = nk_tt__GetGlyfOffset(info, glyph_index); 11239 *pvertices = 0; 11240 11241 if (g < 0) return 0; 11242 numberOfContours = nk_ttSHORT(data + g); 11243 if (numberOfContours > 0) { 11244 nk_byte flags=0,flagcount; 11245 nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; 11246 nk_int x,y,cx,cy,sx,sy, scx,scy; 11247 const nk_byte *points; 11248 endPtsOfContours = (data + g + 10); 11249 ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2); 11250 points = data + g + 10 + numberOfContours * 2 + 2 + ins; 11251 11252 n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2); 11253 m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */ 11254 vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0])); 11255 if (vertices == 0) 11256 return 0; 11257 11258 next_move = 0; 11259 flagcount=0; 11260 11261 /* in first pass, we load uninterpreted data into the allocated array */ 11262 /* above, shifted to the end of the array so we won't overwrite it when */ 11263 /* we create our final data starting from the front */ 11264 off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */ 11265 11266 /* first load flags */ 11267 for (i=0; i < n; ++i) { 11268 if (flagcount == 0) { 11269 flags = *points++; 11270 if (flags & 8) 11271 flagcount = *points++; 11272 } else --flagcount; 11273 vertices[off+i].type = flags; 11274 } 11275 11276 /* now load x coordinates */ 11277 x=0; 11278 for (i=0; i < n; ++i) { 11279 flags = vertices[off+i].type; 11280 if (flags & 2) { 11281 nk_short dx = *points++; 11282 x += (flags & 16) ? dx : -dx; /* ??? */ 11283 } else { 11284 if (!(flags & 16)) { 11285 x = x + (nk_short) (points[0]*256 + points[1]); 11286 points += 2; 11287 } 11288 } 11289 vertices[off+i].x = (nk_short) x; 11290 } 11291 11292 /* now load y coordinates */ 11293 y=0; 11294 for (i=0; i < n; ++i) { 11295 flags = vertices[off+i].type; 11296 if (flags & 4) { 11297 nk_short dy = *points++; 11298 y += (flags & 32) ? dy : -dy; /* ??? */ 11299 } else { 11300 if (!(flags & 32)) { 11301 y = y + (nk_short) (points[0]*256 + points[1]); 11302 points += 2; 11303 } 11304 } 11305 vertices[off+i].y = (nk_short) y; 11306 } 11307 11308 /* now convert them to our format */ 11309 num_vertices=0; 11310 sx = sy = cx = cy = scx = scy = 0; 11311 for (i=0; i < n; ++i) 11312 { 11313 flags = vertices[off+i].type; 11314 x = (nk_short) vertices[off+i].x; 11315 y = (nk_short) vertices[off+i].y; 11316 11317 if (next_move == i) { 11318 if (i != 0) 11319 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 11320 11321 /* now start the new one */ 11322 start_off = !(flags & 1); 11323 if (start_off) { 11324 /* if we start off with an off-curve point, then when we need to find a point on the curve */ 11325 /* where we can start, and we need to save some state for when we wraparound. */ 11326 scx = x; 11327 scy = y; 11328 if (!(vertices[off+i+1].type & 1)) { 11329 /* next point is also a curve point, so interpolate an on-point curve */ 11330 sx = (x + (nk_int) vertices[off+i+1].x) >> 1; 11331 sy = (y + (nk_int) vertices[off+i+1].y) >> 1; 11332 } else { 11333 /* otherwise just use the next point as our start point */ 11334 sx = (nk_int) vertices[off+i+1].x; 11335 sy = (nk_int) vertices[off+i+1].y; 11336 ++i; /* we're using point i+1 as the starting point, so skip it */ 11337 } 11338 } else { 11339 sx = x; 11340 sy = y; 11341 } 11342 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0); 11343 was_off = 0; 11344 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2); 11345 ++j; 11346 } else { 11347 if (!(flags & 1)) 11348 { /* if it's a curve */ 11349 if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */ 11350 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); 11351 cx = x; 11352 cy = y; 11353 was_off = 1; 11354 } else { 11355 if (was_off) 11356 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy); 11357 else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0); 11358 was_off = 0; 11359 } 11360 } 11361 } 11362 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 11363 } else if (numberOfContours == -1) { 11364 /* Compound shapes. */ 11365 int more = 1; 11366 const nk_byte *comp = data + g + 10; 11367 num_vertices = 0; 11368 vertices = 0; 11369 11370 while (more) 11371 { 11372 nk_ushort flags, gidx; 11373 int comp_num_verts = 0, i; 11374 struct nk_tt_vertex *comp_verts = 0, *tmp = 0; 11375 float mtx[6] = {1,0,0,1,0,0}, m, n; 11376 11377 flags = (nk_ushort)nk_ttSHORT(comp); comp+=2; 11378 gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2; 11379 11380 if (flags & 2) { /* XY values */ 11381 if (flags & 1) { /* shorts */ 11382 mtx[4] = nk_ttSHORT(comp); comp+=2; 11383 mtx[5] = nk_ttSHORT(comp); comp+=2; 11384 } else { 11385 mtx[4] = nk_ttCHAR(comp); comp+=1; 11386 mtx[5] = nk_ttCHAR(comp); comp+=1; 11387 } 11388 } else { 11389 /* @TODO handle matching point */ 11390 NK_ASSERT(0); 11391 } 11392 if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */ 11393 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11394 mtx[1] = mtx[2] = 0; 11395 } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */ 11396 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11397 mtx[1] = mtx[2] = 0; 11398 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11399 } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */ 11400 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11401 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11402 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11403 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11404 } 11405 11406 /* Find transformation scales. */ 11407 m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]); 11408 n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]); 11409 11410 /* Get indexed glyph. */ 11411 comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts); 11412 if (comp_num_verts > 0) 11413 { 11414 /* Transform vertices. */ 11415 for (i = 0; i < comp_num_verts; ++i) { 11416 struct nk_tt_vertex* v = &comp_verts[i]; 11417 short x,y; 11418 x=v->x; y=v->y; 11419 v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 11420 v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 11421 x=v->cx; y=v->cy; 11422 v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 11423 v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 11424 } 11425 /* Append vertices. */ 11426 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0, 11427 (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex)); 11428 if (!tmp) { 11429 if (vertices) alloc->free(alloc->userdata, vertices); 11430 if (comp_verts) alloc->free(alloc->userdata, comp_verts); 11431 return 0; 11432 } 11433 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex)); 11434 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex)); 11435 if (vertices) alloc->free(alloc->userdata,vertices); 11436 vertices = tmp; 11437 alloc->free(alloc->userdata,comp_verts); 11438 num_vertices += comp_num_verts; 11439 } 11440 /* More components ? */ 11441 more = flags & (1<<5); 11442 } 11443 } else if (numberOfContours < 0) { 11444 /* @TODO other compound variations? */ 11445 NK_ASSERT(0); 11446 } else { 11447 /* numberOfCounters == 0, do nothing */ 11448 } 11449 *pvertices = vertices; 11450 return num_vertices; 11451 } 11452 NK_INTERN void 11453 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index, 11454 int *advanceWidth, int *leftSideBearing) 11455 { 11456 nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34); 11457 if (glyph_index < numOfLongHorMetrics) { 11458 if (advanceWidth) 11459 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index); 11460 if (leftSideBearing) 11461 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); 11462 } else { 11463 if (advanceWidth) 11464 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); 11465 if (leftSideBearing) 11466 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); 11467 } 11468 } 11469 NK_INTERN void 11470 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info, 11471 int *ascent, int *descent, int *lineGap) 11472 { 11473 if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4); 11474 if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6); 11475 if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8); 11476 } 11477 NK_INTERN float 11478 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height) 11479 { 11480 int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6); 11481 return (float) height / (float)fheight; 11482 } 11483 NK_INTERN float 11484 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels) 11485 { 11486 int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18); 11487 return pixels / (float)unitsPerEm; 11488 } 11489 11490 /*------------------------------------------------------------- 11491 * antialiasing software rasterizer 11492 * --------------------------------------------------------------*/ 11493 NK_INTERN void 11494 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font, 11495 int glyph, float scale_x, float scale_y,float shift_x, float shift_y, 11496 int *ix0, int *iy0, int *ix1, int *iy1) 11497 { 11498 int x0,y0,x1,y1; 11499 if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { 11500 /* e.g. space character */ 11501 if (ix0) *ix0 = 0; 11502 if (iy0) *iy0 = 0; 11503 if (ix1) *ix1 = 0; 11504 if (iy1) *iy1 = 0; 11505 } else { 11506 /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */ 11507 if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x); 11508 if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y); 11509 if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x); 11510 if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y); 11511 } 11512 } 11513 NK_INTERN void 11514 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph, 11515 float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) 11516 { 11517 nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); 11518 } 11519 11520 /*------------------------------------------------------------- 11521 * Rasterizer 11522 * --------------------------------------------------------------*/ 11523 NK_INTERN void* 11524 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size) 11525 { 11526 if (hh->first_free) { 11527 void *p = hh->first_free; 11528 hh->first_free = * (void **) p; 11529 return p; 11530 } else { 11531 if (hh->num_remaining_in_head_chunk == 0) { 11532 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); 11533 struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *) 11534 hh->alloc.alloc(hh->alloc.userdata, 0, 11535 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count); 11536 if (c == 0) return 0; 11537 c->next = hh->head; 11538 hh->head = c; 11539 hh->num_remaining_in_head_chunk = count; 11540 } 11541 --hh->num_remaining_in_head_chunk; 11542 return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk; 11543 } 11544 } 11545 NK_INTERN void 11546 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p) 11547 { 11548 *(void **) p = hh->first_free; 11549 hh->first_free = p; 11550 } 11551 NK_INTERN void 11552 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh) 11553 { 11554 struct nk_tt__hheap_chunk *c = hh->head; 11555 while (c) { 11556 struct nk_tt__hheap_chunk *n = c->next; 11557 hh->alloc.free(hh->alloc.userdata, c); 11558 c = n; 11559 } 11560 } 11561 NK_INTERN struct nk_tt__active_edge* 11562 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e, 11563 int off_x, float start_point) 11564 { 11565 struct nk_tt__active_edge *z = (struct nk_tt__active_edge *) 11566 nk_tt__hheap_alloc(hh, sizeof(*z)); 11567 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 11568 /*STBTT_assert(e->y0 <= start_point); */ 11569 if (!z) return z; 11570 z->fdx = dxdy; 11571 z->fdy = (dxdy != 0) ? (1/dxdy): 0; 11572 z->fx = e->x0 + dxdy * (start_point - e->y0); 11573 z->fx -= (float)off_x; 11574 z->direction = e->invert ? 1.0f : -1.0f; 11575 z->sy = e->y0; 11576 z->ey = e->y1; 11577 z->next = 0; 11578 return z; 11579 } 11580 NK_INTERN void 11581 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e, 11582 float x0, float y0, float x1, float y1) 11583 { 11584 if (y0 == y1) return; 11585 NK_ASSERT(y0 < y1); 11586 NK_ASSERT(e->sy <= e->ey); 11587 if (y0 > e->ey) return; 11588 if (y1 < e->sy) return; 11589 if (y0 < e->sy) { 11590 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); 11591 y0 = e->sy; 11592 } 11593 if (y1 > e->ey) { 11594 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); 11595 y1 = e->ey; 11596 } 11597 11598 if (x0 == x) NK_ASSERT(x1 <= x+1); 11599 else if (x0 == x+1) NK_ASSERT(x1 >= x); 11600 else if (x0 <= x) NK_ASSERT(x1 <= x); 11601 else if (x0 >= x+1) NK_ASSERT(x1 >= x+1); 11602 else NK_ASSERT(x1 >= x && x1 <= x+1); 11603 11604 if (x0 <= x && x1 <= x) 11605 scanline[x] += e->direction * (y1-y0); 11606 else if (x0 >= x+1 && x1 >= x+1); 11607 else { 11608 NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); 11609 /* coverage = 1 - average x position */ 11610 scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f); 11611 } 11612 } 11613 NK_INTERN void 11614 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, 11615 struct nk_tt__active_edge *e, float y_top) 11616 { 11617 float y_bottom = y_top+1; 11618 while (e) 11619 { 11620 /* brute force every pixel */ 11621 /* compute intersection points with top & bottom */ 11622 NK_ASSERT(e->ey >= y_top); 11623 if (e->fdx == 0) { 11624 float x0 = e->fx; 11625 if (x0 < len) { 11626 if (x0 >= 0) { 11627 nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); 11628 nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); 11629 } else { 11630 nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); 11631 } 11632 } 11633 } else { 11634 float x0 = e->fx; 11635 float dx = e->fdx; 11636 float xb = x0 + dx; 11637 float x_top, x_bottom; 11638 float y0,y1; 11639 float dy = e->fdy; 11640 NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top); 11641 11642 /* compute endpoints of line segment clipped to this scanline (if the */ 11643 /* line segment starts on this scanline. x0 is the intersection of the */ 11644 /* line with y_top, but that may be off the line segment. */ 11645 if (e->sy > y_top) { 11646 x_top = x0 + dx * (e->sy - y_top); 11647 y0 = e->sy; 11648 } else { 11649 x_top = x0; 11650 y0 = y_top; 11651 } 11652 11653 if (e->ey < y_bottom) { 11654 x_bottom = x0 + dx * (e->ey - y_top); 11655 y1 = e->ey; 11656 } else { 11657 x_bottom = xb; 11658 y1 = y_bottom; 11659 } 11660 11661 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) 11662 { 11663 /* from here on, we don't have to range check x values */ 11664 if ((int) x_top == (int) x_bottom) { 11665 float height; 11666 /* simple case, only spans one pixel */ 11667 int x = (int) x_top; 11668 height = y1 - y0; 11669 NK_ASSERT(x >= 0 && x < len); 11670 scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height; 11671 scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */ 11672 } else { 11673 int x,x1,x2; 11674 float y_crossing, step, sign, area; 11675 /* covers 2+ pixels */ 11676 if (x_top > x_bottom) 11677 { 11678 /* flip scanline vertically; signed area is the same */ 11679 float t; 11680 y0 = y_bottom - (y0 - y_top); 11681 y1 = y_bottom - (y1 - y_top); 11682 t = y0; y0 = y1; y1 = t; 11683 t = x_bottom; x_bottom = x_top; x_top = t; 11684 dx = -dx; 11685 dy = -dy; 11686 t = x0; x0 = xb; xb = t; 11687 } 11688 11689 x1 = (int) x_top; 11690 x2 = (int) x_bottom; 11691 /* compute intersection with y axis at x1+1 */ 11692 y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top; 11693 11694 sign = e->direction; 11695 /* area of the rectangle covered from y0..y_crossing */ 11696 area = sign * (y_crossing-y0); 11697 /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */ 11698 scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f); 11699 11700 step = sign * dy; 11701 for (x = x1+1; x < x2; ++x) { 11702 scanline[x] += area + step/2; 11703 area += step; 11704 } 11705 y_crossing += (float)dy * (float)(x2 - (x1+1)); 11706 11707 scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing); 11708 scanline_fill[x2] += sign * (y1-y0); 11709 } 11710 } 11711 else 11712 { 11713 /* if edge goes outside of box we're drawing, we require */ 11714 /* clipping logic. since this does not match the intended use */ 11715 /* of this library, we use a different, very slow brute */ 11716 /* force implementation */ 11717 int x; 11718 for (x=0; x < len; ++x) 11719 { 11720 /* cases: */ 11721 /* */ 11722 /* there can be up to two intersections with the pixel. any intersection */ 11723 /* with left or right edges can be handled by splitting into two (or three) */ 11724 /* regions. intersections with top & bottom do not necessitate case-wise logic. */ 11725 /* */ 11726 /* the old way of doing this found the intersections with the left & right edges, */ 11727 /* then used some simple logic to produce up to three segments in sorted order */ 11728 /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */ 11729 /* across the x border, then the corresponding y position might not be distinct */ 11730 /* from the other y segment, and it might ignored as an empty segment. to avoid */ 11731 /* that, we need to explicitly produce segments based on x positions. */ 11732 11733 /* rename variables to clear pairs */ 11734 float ya = y_top; 11735 float x1 = (float) (x); 11736 float x2 = (float) (x+1); 11737 float x3 = xb; 11738 float y3 = y_bottom; 11739 float yb,y2; 11740 11741 yb = ((float)x - x0) / dx + y_top; 11742 y2 = ((float)x+1 - x0) / dx + y_top; 11743 11744 if (x0 < x1 && x3 > x2) { /* three segments descending down-right */ 11745 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11746 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2); 11747 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11748 } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */ 11749 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11750 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb); 11751 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11752 } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */ 11753 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11754 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11755 } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */ 11756 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11757 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11758 } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */ 11759 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11760 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11761 } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */ 11762 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11763 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11764 } else { /* one segment */ 11765 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3); 11766 } 11767 } 11768 } 11769 } 11770 e = e->next; 11771 } 11772 } 11773 NK_INTERN void 11774 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e, 11775 int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc) 11776 { 11777 /* directly AA rasterize edges w/o supersampling */ 11778 struct nk_tt__hheap hh; 11779 struct nk_tt__active_edge *active = 0; 11780 int y,j=0, i; 11781 float scanline_data[129], *scanline, *scanline2; 11782 11783 NK_UNUSED(vsubsample); 11784 nk_zero_struct(hh); 11785 hh.alloc = *alloc; 11786 11787 if (result->w > 64) 11788 scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float)); 11789 else scanline = scanline_data; 11790 11791 scanline2 = scanline + result->w; 11792 y = off_y; 11793 e[n].y0 = (float) (off_y + result->h) + 1; 11794 11795 while (j < result->h) 11796 { 11797 /* find center of pixel for this scanline */ 11798 float scan_y_top = (float)y + 0.0f; 11799 float scan_y_bottom = (float)y + 1.0f; 11800 struct nk_tt__active_edge **step = &active; 11801 11802 NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0])); 11803 NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0])); 11804 11805 /* update all active edges; */ 11806 /* remove all active edges that terminate before the top of this scanline */ 11807 while (*step) { 11808 struct nk_tt__active_edge * z = *step; 11809 if (z->ey <= scan_y_top) { 11810 *step = z->next; /* delete from list */ 11811 NK_ASSERT(z->direction); 11812 z->direction = 0; 11813 nk_tt__hheap_free(&hh, z); 11814 } else { 11815 step = &((*step)->next); /* advance through list */ 11816 } 11817 } 11818 11819 /* insert all edges that start before the bottom of this scanline */ 11820 while (e->y0 <= scan_y_bottom) { 11821 if (e->y0 != e->y1) { 11822 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top); 11823 if (z != 0) { 11824 NK_ASSERT(z->ey >= scan_y_top); 11825 /* insert at front */ 11826 z->next = active; 11827 active = z; 11828 } 11829 } 11830 ++e; 11831 } 11832 11833 /* now process all active edges */ 11834 if (active) 11835 nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); 11836 11837 { 11838 float sum = 0; 11839 for (i=0; i < result->w; ++i) { 11840 float k; 11841 int m; 11842 sum += scanline2[i]; 11843 k = scanline[i] + sum; 11844 k = (float) NK_ABS(k) * 255.0f + 0.5f; 11845 m = (int) k; 11846 if (m > 255) m = 255; 11847 result->pixels[j*result->stride + i] = (unsigned char) m; 11848 } 11849 } 11850 /* advance all the edges */ 11851 step = &active; 11852 while (*step) { 11853 struct nk_tt__active_edge *z = *step; 11854 z->fx += z->fdx; /* advance to position for current scanline */ 11855 step = &((*step)->next); /* advance through list */ 11856 } 11857 ++y; 11858 ++j; 11859 } 11860 nk_tt__hheap_cleanup(&hh); 11861 if (scanline != scanline_data) 11862 alloc->free(alloc->userdata, scanline); 11863 } 11864 NK_INTERN void 11865 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n) 11866 { 11867 int i,j; 11868 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0) 11869 for (i=1; i < n; ++i) { 11870 struct nk_tt__edge t = p[i], *a = &t; 11871 j = i; 11872 while (j > 0) { 11873 struct nk_tt__edge *b = &p[j-1]; 11874 int c = NK_TT__COMPARE(a,b); 11875 if (!c) break; 11876 p[j] = p[j-1]; 11877 --j; 11878 } 11879 if (i != j) 11880 p[j] = t; 11881 } 11882 } 11883 NK_INTERN void 11884 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n) 11885 { 11886 /* threshold for transitioning to insertion sort */ 11887 while (n > 12) { 11888 struct nk_tt__edge t; 11889 int c01,c12,c,m,i,j; 11890 11891 /* compute median of three */ 11892 m = n >> 1; 11893 c01 = NK_TT__COMPARE(&p[0],&p[m]); 11894 c12 = NK_TT__COMPARE(&p[m],&p[n-1]); 11895 11896 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ 11897 if (c01 != c12) { 11898 /* otherwise, we'll need to swap something else to middle */ 11899 int z; 11900 c = NK_TT__COMPARE(&p[0],&p[n-1]); 11901 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ 11902 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ 11903 z = (c == c12) ? 0 : n-1; 11904 t = p[z]; 11905 p[z] = p[m]; 11906 p[m] = t; 11907 } 11908 11909 /* now p[m] is the median-of-three */ 11910 /* swap it to the beginning so it won't move around */ 11911 t = p[0]; 11912 p[0] = p[m]; 11913 p[m] = t; 11914 11915 /* partition loop */ 11916 i=1; 11917 j=n-1; 11918 for(;;) { 11919 /* handling of equality is crucial here */ 11920 /* for sentinels & efficiency with duplicates */ 11921 for (;;++i) { 11922 if (!NK_TT__COMPARE(&p[i], &p[0])) break; 11923 } 11924 for (;;--j) { 11925 if (!NK_TT__COMPARE(&p[0], &p[j])) break; 11926 } 11927 11928 /* make sure we haven't crossed */ 11929 if (i >= j) break; 11930 t = p[i]; 11931 p[i] = p[j]; 11932 p[j] = t; 11933 11934 ++i; 11935 --j; 11936 11937 } 11938 11939 /* recurse on smaller side, iterate on larger */ 11940 if (j < (n-i)) { 11941 nk_tt__sort_edges_quicksort(p,j); 11942 p = p+i; 11943 n = n-i; 11944 } else { 11945 nk_tt__sort_edges_quicksort(p+i, n-i); 11946 n = j; 11947 } 11948 } 11949 } 11950 NK_INTERN void 11951 nk_tt__sort_edges(struct nk_tt__edge *p, int n) 11952 { 11953 nk_tt__sort_edges_quicksort(p, n); 11954 nk_tt__sort_edges_ins_sort(p, n); 11955 } 11956 NK_INTERN void 11957 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts, 11958 int *wcount, int windings, float scale_x, float scale_y, 11959 float shift_x, float shift_y, int off_x, int off_y, int invert, 11960 struct nk_allocator *alloc) 11961 { 11962 float y_scale_inv = invert ? -scale_y : scale_y; 11963 struct nk_tt__edge *e; 11964 int n,i,j,k,m; 11965 int vsubsample = 1; 11966 /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */ 11967 11968 /* now we have to blow out the windings into explicit edge lists */ 11969 n = 0; 11970 for (i=0; i < windings; ++i) 11971 n += wcount[i]; 11972 11973 e = (struct nk_tt__edge*) 11974 alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1))); 11975 if (e == 0) return; 11976 n = 0; 11977 11978 m=0; 11979 for (i=0; i < windings; ++i) 11980 { 11981 struct nk_tt__point *p = pts + m; 11982 m += wcount[i]; 11983 j = wcount[i]-1; 11984 for (k=0; k < wcount[i]; j=k++) { 11985 int a=k,b=j; 11986 /* skip the edge if horizontal */ 11987 if (p[j].y == p[k].y) 11988 continue; 11989 11990 /* add edge from j to k to the list */ 11991 e[n].invert = 0; 11992 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { 11993 e[n].invert = 1; 11994 a=j,b=k; 11995 } 11996 e[n].x0 = p[a].x * scale_x + shift_x; 11997 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample; 11998 e[n].x1 = p[b].x * scale_x + shift_x; 11999 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample; 12000 ++n; 12001 } 12002 } 12003 12004 /* now sort the edges by their highest point (should snap to integer, and then by x) */ 12005 /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */ 12006 nk_tt__sort_edges(e, n); 12007 /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */ 12008 nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc); 12009 alloc->free(alloc->userdata, e); 12010 } 12011 NK_INTERN void 12012 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y) 12013 { 12014 if (!points) return; /* during first pass, it's unallocated */ 12015 points[n].x = x; 12016 points[n].y = y; 12017 } 12018 NK_INTERN int 12019 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points, 12020 float x0, float y0, float x1, float y1, float x2, float y2, 12021 float objspace_flatness_squared, int n) 12022 { 12023 /* tesselate until threshold p is happy... 12024 * @TODO warped to compensate for non-linear stretching */ 12025 /* midpoint */ 12026 float mx = (x0 + 2*x1 + x2)/4; 12027 float my = (y0 + 2*y1 + y2)/4; 12028 /* versus directly drawn line */ 12029 float dx = (x0+x2)/2 - mx; 12030 float dy = (y0+y2)/2 - my; 12031 if (n > 16) /* 65536 segments on one curve better be enough! */ 12032 return 1; 12033 12034 /* half-pixel error allowed... need to be smaller if AA */ 12035 if (dx*dx+dy*dy > objspace_flatness_squared) { 12036 nk_tt__tesselate_curve(points, num_points, x0,y0, 12037 (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); 12038 nk_tt__tesselate_curve(points, num_points, mx,my, 12039 (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); 12040 } else { 12041 nk_tt__add_point(points, *num_points,x2,y2); 12042 *num_points = *num_points+1; 12043 } 12044 return 1; 12045 } 12046 NK_INTERN struct nk_tt__point* 12047 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts, 12048 float objspace_flatness, int **contour_lengths, int *num_contours, 12049 struct nk_allocator *alloc) 12050 { 12051 /* returns number of contours */ 12052 struct nk_tt__point *points=0; 12053 int num_points=0; 12054 float objspace_flatness_squared = objspace_flatness * objspace_flatness; 12055 int i; 12056 int n=0; 12057 int start=0; 12058 int pass; 12059 12060 /* count how many "moves" there are to get the contour count */ 12061 for (i=0; i < num_verts; ++i) 12062 if (vertices[i].type == NK_TT_vmove) ++n; 12063 12064 *num_contours = n; 12065 if (n == 0) return 0; 12066 12067 *contour_lengths = (int *) 12068 alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n)); 12069 if (*contour_lengths == 0) { 12070 *num_contours = 0; 12071 return 0; 12072 } 12073 12074 /* make two passes through the points so we don't need to realloc */ 12075 for (pass=0; pass < 2; ++pass) 12076 { 12077 float x=0,y=0; 12078 if (pass == 1) { 12079 points = (struct nk_tt__point *) 12080 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0])); 12081 if (points == 0) goto error; 12082 } 12083 num_points = 0; 12084 n= -1; 12085 12086 for (i=0; i < num_verts; ++i) 12087 { 12088 switch (vertices[i].type) { 12089 case NK_TT_vmove: 12090 /* start the next contour */ 12091 if (n >= 0) 12092 (*contour_lengths)[n] = num_points - start; 12093 ++n; 12094 start = num_points; 12095 12096 x = vertices[i].x, y = vertices[i].y; 12097 nk_tt__add_point(points, num_points++, x,y); 12098 break; 12099 case NK_TT_vline: 12100 x = vertices[i].x, y = vertices[i].y; 12101 nk_tt__add_point(points, num_points++, x, y); 12102 break; 12103 case NK_TT_vcurve: 12104 nk_tt__tesselate_curve(points, &num_points, x,y, 12105 vertices[i].cx, vertices[i].cy, 12106 vertices[i].x, vertices[i].y, 12107 objspace_flatness_squared, 0); 12108 x = vertices[i].x, y = vertices[i].y; 12109 break; 12110 default: break; 12111 } 12112 } 12113 (*contour_lengths)[n] = num_points - start; 12114 } 12115 return points; 12116 12117 error: 12118 alloc->free(alloc->userdata, points); 12119 alloc->free(alloc->userdata, *contour_lengths); 12120 *contour_lengths = 0; 12121 *num_contours = 0; 12122 return 0; 12123 } 12124 NK_INTERN void 12125 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels, 12126 struct nk_tt_vertex *vertices, int num_verts, 12127 float scale_x, float scale_y, float shift_x, float shift_y, 12128 int x_off, int y_off, int invert, struct nk_allocator *alloc) 12129 { 12130 float scale = scale_x > scale_y ? scale_y : scale_x; 12131 int winding_count, *winding_lengths; 12132 struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts, 12133 flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc); 12134 12135 NK_ASSERT(alloc); 12136 if (windings) { 12137 nk_tt__rasterize(result, windings, winding_lengths, winding_count, 12138 scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc); 12139 alloc->free(alloc->userdata, winding_lengths); 12140 alloc->free(alloc->userdata, windings); 12141 } 12142 } 12143 NK_INTERN void 12144 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output, 12145 int out_w, int out_h, int out_stride, float scale_x, float scale_y, 12146 float shift_x, float shift_y, int glyph, struct nk_allocator *alloc) 12147 { 12148 int ix0,iy0; 12149 struct nk_tt_vertex *vertices; 12150 int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices); 12151 struct nk_tt__bitmap gbm; 12152 12153 nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, 12154 shift_y, &ix0,&iy0,0,0); 12155 gbm.pixels = output; 12156 gbm.w = out_w; 12157 gbm.h = out_h; 12158 gbm.stride = out_stride; 12159 12160 if (gbm.w && gbm.h) 12161 nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, 12162 shift_x, shift_y, ix0,iy0, 1, alloc); 12163 alloc->free(alloc->userdata, vertices); 12164 } 12165 12166 /*------------------------------------------------------------- 12167 * Bitmap baking 12168 * --------------------------------------------------------------*/ 12169 NK_INTERN int 12170 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels, 12171 int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc) 12172 { 12173 int num_nodes = pw - padding; 12174 struct nk_rp_context *context = (struct nk_rp_context *) 12175 alloc->alloc(alloc->userdata,0, sizeof(*context)); 12176 struct nk_rp_node *nodes = (struct nk_rp_node*) 12177 alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes)); 12178 12179 if (context == 0 || nodes == 0) { 12180 if (context != 0) alloc->free(alloc->userdata, context); 12181 if (nodes != 0) alloc->free(alloc->userdata, nodes); 12182 return 0; 12183 } 12184 12185 spc->width = pw; 12186 spc->height = ph; 12187 spc->pixels = pixels; 12188 spc->pack_info = context; 12189 spc->nodes = nodes; 12190 spc->padding = padding; 12191 spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw; 12192 spc->h_oversample = 1; 12193 spc->v_oversample = 1; 12194 12195 nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); 12196 if (pixels) 12197 NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */ 12198 return 1; 12199 } 12200 NK_INTERN void 12201 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc) 12202 { 12203 alloc->free(alloc->userdata, spc->nodes); 12204 alloc->free(alloc->userdata, spc->pack_info); 12205 } 12206 NK_INTERN void 12207 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc, 12208 unsigned int h_oversample, unsigned int v_oversample) 12209 { 12210 NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE); 12211 NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE); 12212 if (h_oversample <= NK_TT_MAX_OVERSAMPLE) 12213 spc->h_oversample = h_oversample; 12214 if (v_oversample <= NK_TT_MAX_OVERSAMPLE) 12215 spc->v_oversample = v_oversample; 12216 } 12217 NK_INTERN void 12218 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, 12219 int kernel_width) 12220 { 12221 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; 12222 int safe_w = w - kernel_width; 12223 int j; 12224 12225 for (j=0; j < h; ++j) 12226 { 12227 int i; 12228 unsigned int total; 12229 NK_MEMSET(buffer, 0, (nk_size)kernel_width); 12230 12231 total = 0; 12232 12233 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 12234 switch (kernel_width) { 12235 case 2: 12236 for (i=0; i <= safe_w; ++i) { 12237 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12238 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12239 pixels[i] = (unsigned char) (total / 2); 12240 } 12241 break; 12242 case 3: 12243 for (i=0; i <= safe_w; ++i) { 12244 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12245 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12246 pixels[i] = (unsigned char) (total / 3); 12247 } 12248 break; 12249 case 4: 12250 for (i=0; i <= safe_w; ++i) { 12251 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK]; 12252 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12253 pixels[i] = (unsigned char) (total / 4); 12254 } 12255 break; 12256 case 5: 12257 for (i=0; i <= safe_w; ++i) { 12258 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12259 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12260 pixels[i] = (unsigned char) (total / 5); 12261 } 12262 break; 12263 default: 12264 for (i=0; i <= safe_w; ++i) { 12265 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12266 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12267 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); 12268 } 12269 break; 12270 } 12271 12272 for (; i < w; ++i) { 12273 NK_ASSERT(pixels[i] == 0); 12274 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); 12275 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); 12276 } 12277 pixels += stride_in_bytes; 12278 } 12279 } 12280 NK_INTERN void 12281 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, 12282 int kernel_width) 12283 { 12284 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; 12285 int safe_h = h - kernel_width; 12286 int j; 12287 12288 for (j=0; j < w; ++j) 12289 { 12290 int i; 12291 unsigned int total; 12292 NK_MEMSET(buffer, 0, (nk_size)kernel_width); 12293 12294 total = 0; 12295 12296 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 12297 switch (kernel_width) { 12298 case 2: 12299 for (i=0; i <= safe_h; ++i) { 12300 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12301 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12302 pixels[i*stride_in_bytes] = (unsigned char) (total / 2); 12303 } 12304 break; 12305 case 3: 12306 for (i=0; i <= safe_h; ++i) { 12307 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12308 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12309 pixels[i*stride_in_bytes] = (unsigned char) (total / 3); 12310 } 12311 break; 12312 case 4: 12313 for (i=0; i <= safe_h; ++i) { 12314 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12315 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12316 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); 12317 } 12318 break; 12319 case 5: 12320 for (i=0; i <= safe_h; ++i) { 12321 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12322 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12323 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); 12324 } 12325 break; 12326 default: 12327 for (i=0; i <= safe_h; ++i) { 12328 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12329 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12330 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); 12331 } 12332 break; 12333 } 12334 12335 for (; i < h; ++i) { 12336 NK_ASSERT(pixels[i*stride_in_bytes] == 0); 12337 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); 12338 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); 12339 } 12340 pixels += 1; 12341 } 12342 } 12343 NK_INTERN float 12344 nk_tt__oversample_shift(int oversample) 12345 { 12346 if (!oversample) 12347 return 0.0f; 12348 12349 /* The prefilter is a box filter of width "oversample", */ 12350 /* which shifts phase by (oversample - 1)/2 pixels in */ 12351 /* oversampled space. We want to shift in the opposite */ 12352 /* direction to counter this. */ 12353 return (float)-(oversample - 1) / (2.0f * (float)oversample); 12354 } 12355 NK_INTERN int 12356 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc, 12357 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, 12358 int num_ranges, struct nk_rp_rect *rects) 12359 { 12360 /* rects array must be big enough to accommodate all characters in the given ranges */ 12361 int i,j,k; 12362 k = 0; 12363 12364 for (i=0; i < num_ranges; ++i) { 12365 float fh = ranges[i].font_size; 12366 float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh): 12367 nk_tt_ScaleForMappingEmToPixels(info, -fh); 12368 ranges[i].h_oversample = (unsigned char) spc->h_oversample; 12369 ranges[i].v_oversample = (unsigned char) spc->v_oversample; 12370 for (j=0; j < ranges[i].num_chars; ++j) { 12371 int x0,y0,x1,y1; 12372 int codepoint = ranges[i].first_unicode_codepoint_in_range ? 12373 ranges[i].first_unicode_codepoint_in_range + j : 12374 ranges[i].array_of_unicode_codepoints[j]; 12375 12376 int glyph = nk_tt_FindGlyphIndex(info, codepoint); 12377 nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample, 12378 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); 12379 rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1); 12380 rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1); 12381 ++k; 12382 } 12383 } 12384 return k; 12385 } 12386 NK_INTERN int 12387 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc, 12388 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, 12389 int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc) 12390 { 12391 int i,j,k, return_value = 1; 12392 /* save current values */ 12393 int old_h_over = (int)spc->h_oversample; 12394 int old_v_over = (int)spc->v_oversample; 12395 /* rects array must be big enough to accommodate all characters in the given ranges */ 12396 12397 k = 0; 12398 for (i=0; i < num_ranges; ++i) 12399 { 12400 float fh = ranges[i].font_size; 12401 float recip_h,recip_v,sub_x,sub_y; 12402 float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh): 12403 nk_tt_ScaleForMappingEmToPixels(info, -fh); 12404 12405 spc->h_oversample = ranges[i].h_oversample; 12406 spc->v_oversample = ranges[i].v_oversample; 12407 12408 recip_h = 1.0f / (float)spc->h_oversample; 12409 recip_v = 1.0f / (float)spc->v_oversample; 12410 12411 sub_x = nk_tt__oversample_shift((int)spc->h_oversample); 12412 sub_y = nk_tt__oversample_shift((int)spc->v_oversample); 12413 12414 for (j=0; j < ranges[i].num_chars; ++j) 12415 { 12416 struct nk_rp_rect *r = &rects[k]; 12417 if (r->was_packed) 12418 { 12419 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j]; 12420 int advance, lsb, x0,y0,x1,y1; 12421 int codepoint = ranges[i].first_unicode_codepoint_in_range ? 12422 ranges[i].first_unicode_codepoint_in_range + j : 12423 ranges[i].array_of_unicode_codepoints[j]; 12424 int glyph = nk_tt_FindGlyphIndex(info, codepoint); 12425 nk_rp_coord pad = (nk_rp_coord) spc->padding; 12426 12427 /* pad on left and top */ 12428 r->x = (nk_rp_coord)((int)r->x + (int)pad); 12429 r->y = (nk_rp_coord)((int)r->y + (int)pad); 12430 r->w = (nk_rp_coord)((int)r->w - (int)pad); 12431 r->h = (nk_rp_coord)((int)r->h - (int)pad); 12432 12433 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb); 12434 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample, 12435 (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1); 12436 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, 12437 (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1), 12438 spc->stride_in_bytes, scale * (float)spc->h_oversample, 12439 scale * (float)spc->v_oversample, 0,0, glyph, alloc); 12440 12441 if (spc->h_oversample > 1) 12442 nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 12443 r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample); 12444 12445 if (spc->v_oversample > 1) 12446 nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 12447 r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample); 12448 12449 bc->x0 = (nk_ushort) r->x; 12450 bc->y0 = (nk_ushort) r->y; 12451 bc->x1 = (nk_ushort) (r->x + r->w); 12452 bc->y1 = (nk_ushort) (r->y + r->h); 12453 bc->xadvance = scale * (float)advance; 12454 bc->xoff = (float) x0 * recip_h + sub_x; 12455 bc->yoff = (float) y0 * recip_v + sub_y; 12456 bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x; 12457 bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y; 12458 } else { 12459 return_value = 0; /* if any fail, report failure */ 12460 } 12461 ++k; 12462 } 12463 } 12464 /* restore original values */ 12465 spc->h_oversample = (unsigned int)old_h_over; 12466 spc->v_oversample = (unsigned int)old_v_over; 12467 return return_value; 12468 } 12469 NK_INTERN void 12470 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph, 12471 int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q, 12472 int align_to_integer) 12473 { 12474 float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph; 12475 struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index); 12476 if (align_to_integer) { 12477 int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f); 12478 int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f); 12479 12480 float x = (float)tx; 12481 float y = (float)ty; 12482 12483 q->x0 = x; 12484 q->y0 = y; 12485 q->x1 = x + b->xoff2 - b->xoff; 12486 q->y1 = y + b->yoff2 - b->yoff; 12487 } else { 12488 q->x0 = *xpos + b->xoff; 12489 q->y0 = *ypos + b->yoff; 12490 q->x1 = *xpos + b->xoff2; 12491 q->y1 = *ypos + b->yoff2; 12492 } 12493 q->s0 = b->x0 * ipw; 12494 q->t0 = b->y0 * iph; 12495 q->s1 = b->x1 * ipw; 12496 q->t1 = b->y1 * iph; 12497 *xpos += b->xadvance; 12498 } 12499 12500 /* ------------------------------------------------------------- 12501 * 12502 * FONT BAKING 12503 * 12504 * --------------------------------------------------------------*/ 12505 struct nk_font_bake_data { 12506 struct nk_tt_fontinfo info; 12507 struct nk_rp_rect *rects; 12508 struct nk_tt_pack_range *ranges; 12509 nk_rune range_count; 12510 }; 12511 12512 struct nk_font_baker { 12513 struct nk_allocator alloc; 12514 struct nk_tt_pack_context spc; 12515 struct nk_font_bake_data *build; 12516 struct nk_tt_packedchar *packed_chars; 12517 struct nk_rp_rect *rects; 12518 struct nk_tt_pack_range *ranges; 12519 }; 12520 12521 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect); 12522 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range); 12523 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar); 12524 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data); 12525 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker); 12526 12527 NK_INTERN int 12528 nk_range_count(const nk_rune *range) 12529 { 12530 const nk_rune *iter = range; 12531 NK_ASSERT(range); 12532 if (!range) return 0; 12533 while (*(iter++) != 0); 12534 return (iter == range) ? 0 : (int)((iter - range)/2); 12535 } 12536 NK_INTERN int 12537 nk_range_glyph_count(const nk_rune *range, int count) 12538 { 12539 int i = 0; 12540 int total_glyphs = 0; 12541 for (i = 0; i < count; ++i) { 12542 int diff; 12543 nk_rune f = range[(i*2)+0]; 12544 nk_rune t = range[(i*2)+1]; 12545 NK_ASSERT(t >= f); 12546 diff = (int)((t - f) + 1); 12547 total_glyphs += diff; 12548 } 12549 return total_glyphs; 12550 } 12551 NK_API const nk_rune* 12552 nk_font_default_glyph_ranges(void) 12553 { 12554 NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0}; 12555 return ranges; 12556 } 12557 NK_API const nk_rune* 12558 nk_font_chinese_glyph_ranges(void) 12559 { 12560 NK_STORAGE const nk_rune ranges[] = { 12561 0x0020, 0x00FF, 12562 0x3000, 0x30FF, 12563 0x31F0, 0x31FF, 12564 0xFF00, 0xFFEF, 12565 0x4e00, 0x9FAF, 12566 0 12567 }; 12568 return ranges; 12569 } 12570 NK_API const nk_rune* 12571 nk_font_cyrillic_glyph_ranges(void) 12572 { 12573 NK_STORAGE const nk_rune ranges[] = { 12574 0x0020, 0x00FF, 12575 0x0400, 0x052F, 12576 0x2DE0, 0x2DFF, 12577 0xA640, 0xA69F, 12578 0 12579 }; 12580 return ranges; 12581 } 12582 NK_API const nk_rune* 12583 nk_font_korean_glyph_ranges(void) 12584 { 12585 NK_STORAGE const nk_rune ranges[] = { 12586 0x0020, 0x00FF, 12587 0x3131, 0x3163, 12588 0xAC00, 0xD79D, 12589 0 12590 }; 12591 return ranges; 12592 } 12593 NK_INTERN void 12594 nk_font_baker_memory(nk_size *temp, int *glyph_count, 12595 struct nk_font_config *config_list, int count) 12596 { 12597 int range_count = 0; 12598 int total_range_count = 0; 12599 struct nk_font_config *iter, *i; 12600 12601 NK_ASSERT(config_list); 12602 NK_ASSERT(glyph_count); 12603 if (!config_list) { 12604 *temp = 0; 12605 *glyph_count = 0; 12606 return; 12607 } 12608 *glyph_count = 0; 12609 for (iter = config_list; iter; iter = iter->next) { 12610 i = iter; 12611 do {if (!i->range) iter->range = nk_font_default_glyph_ranges(); 12612 range_count = nk_range_count(i->range); 12613 total_range_count += range_count; 12614 *glyph_count += nk_range_glyph_count(i->range, range_count); 12615 } while ((i = i->n) != iter); 12616 } 12617 *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect); 12618 *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range); 12619 *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar); 12620 *temp += (nk_size)count * sizeof(struct nk_font_bake_data); 12621 *temp += sizeof(struct nk_font_baker); 12622 *temp += nk_rect_align + nk_range_align + nk_char_align; 12623 *temp += nk_build_align + nk_baker_align; 12624 } 12625 NK_INTERN struct nk_font_baker* 12626 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc) 12627 { 12628 struct nk_font_baker *baker; 12629 if (!memory) return 0; 12630 /* setup baker inside a memory block */ 12631 baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align); 12632 baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align); 12633 baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align); 12634 baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align); 12635 baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align); 12636 baker->alloc = *alloc; 12637 return baker; 12638 } 12639 NK_INTERN int 12640 nk_font_bake_pack(struct nk_font_baker *baker, 12641 nk_size *image_memory, int *width, int *height, struct nk_recti *custom, 12642 const struct nk_font_config *config_list, int count, 12643 struct nk_allocator *alloc) 12644 { 12645 NK_STORAGE const nk_size max_height = 1024 * 32; 12646 const struct nk_font_config *config_iter, *it; 12647 int total_glyph_count = 0; 12648 int total_range_count = 0; 12649 int range_count = 0; 12650 int i = 0; 12651 12652 NK_ASSERT(image_memory); 12653 NK_ASSERT(width); 12654 NK_ASSERT(height); 12655 NK_ASSERT(config_list); 12656 NK_ASSERT(count); 12657 NK_ASSERT(alloc); 12658 12659 if (!image_memory || !width || !height || !config_list || !count) return nk_false; 12660 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 12661 it = config_iter; 12662 do {range_count = nk_range_count(it->range); 12663 total_range_count += range_count; 12664 total_glyph_count += nk_range_glyph_count(it->range, range_count); 12665 } while ((it = it->n) != config_iter); 12666 } 12667 /* setup font baker from temporary memory */ 12668 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 12669 it = config_iter; 12670 do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0)) 12671 return nk_false; 12672 } while ((it = it->n) != config_iter); 12673 } 12674 *height = 0; 12675 *width = (total_glyph_count > 1000) ? 1024 : 512; 12676 nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc); 12677 { 12678 int input_i = 0; 12679 int range_n = 0; 12680 int rect_n = 0; 12681 int char_n = 0; 12682 12683 if (custom) { 12684 /* pack custom user data first so it will be in the upper left corner*/ 12685 struct nk_rp_rect custom_space; 12686 nk_zero(&custom_space, sizeof(custom_space)); 12687 custom_space.w = (nk_rp_coord)(custom->w); 12688 custom_space.h = (nk_rp_coord)(custom->h); 12689 12690 nk_tt_PackSetOversampling(&baker->spc, 1, 1); 12691 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1); 12692 *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h)); 12693 12694 custom->x = (short)custom_space.x; 12695 custom->y = (short)custom_space.y; 12696 custom->w = (short)custom_space.w; 12697 custom->h = (short)custom_space.h; 12698 } 12699 12700 /* first font pass: pack all glyphs */ 12701 for (input_i = 0, config_iter = config_list; input_i < count && config_iter; 12702 config_iter = config_iter->next) { 12703 it = config_iter; 12704 do {int n = 0; 12705 int glyph_count; 12706 const nk_rune *in_range; 12707 const struct nk_font_config *cfg = it; 12708 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12709 12710 /* count glyphs + ranges in current font */ 12711 glyph_count = 0; range_count = 0; 12712 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) { 12713 glyph_count += (int)(in_range[1] - in_range[0]) + 1; 12714 range_count++; 12715 } 12716 12717 /* setup ranges */ 12718 tmp->ranges = baker->ranges + range_n; 12719 tmp->range_count = (nk_rune)range_count; 12720 range_n += range_count; 12721 for (i = 0; i < range_count; ++i) { 12722 in_range = &cfg->range[i * 2]; 12723 tmp->ranges[i].font_size = cfg->size; 12724 tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0]; 12725 tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1; 12726 tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n; 12727 char_n += tmp->ranges[i].num_chars; 12728 } 12729 12730 /* pack */ 12731 tmp->rects = baker->rects + rect_n; 12732 rect_n += glyph_count; 12733 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 12734 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info, 12735 tmp->ranges, (int)tmp->range_count, tmp->rects); 12736 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n); 12737 12738 /* texture height */ 12739 for (i = 0; i < n; ++i) { 12740 if (tmp->rects[i].was_packed) 12741 *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h); 12742 } 12743 } while ((it = it->n) != config_iter); 12744 } 12745 NK_ASSERT(rect_n == total_glyph_count); 12746 NK_ASSERT(char_n == total_glyph_count); 12747 NK_ASSERT(range_n == total_range_count); 12748 } 12749 *height = (int)nk_round_up_pow2((nk_uint)*height); 12750 *image_memory = (nk_size)(*width) * (nk_size)(*height); 12751 return nk_true; 12752 } 12753 NK_INTERN void 12754 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height, 12755 struct nk_font_glyph *glyphs, int glyphs_count, 12756 const struct nk_font_config *config_list, int font_count) 12757 { 12758 int input_i = 0; 12759 nk_rune glyph_n = 0; 12760 const struct nk_font_config *config_iter; 12761 const struct nk_font_config *it; 12762 12763 NK_ASSERT(image_memory); 12764 NK_ASSERT(width); 12765 NK_ASSERT(height); 12766 NK_ASSERT(config_list); 12767 NK_ASSERT(baker); 12768 NK_ASSERT(font_count); 12769 NK_ASSERT(glyphs_count); 12770 if (!image_memory || !width || !height || !config_list || 12771 !font_count || !glyphs || !glyphs_count) 12772 return; 12773 12774 /* second font pass: render glyphs */ 12775 nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height)); 12776 baker->spc.pixels = (unsigned char*)image_memory; 12777 baker->spc.height = (int)height; 12778 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 12779 config_iter = config_iter->next) { 12780 it = config_iter; 12781 do {const struct nk_font_config *cfg = it; 12782 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12783 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 12784 nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, 12785 (int)tmp->range_count, tmp->rects, &baker->alloc); 12786 } while ((it = it->n) != config_iter); 12787 } nk_tt_PackEnd(&baker->spc, &baker->alloc); 12788 12789 /* third pass: setup font and glyphs */ 12790 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 12791 config_iter = config_iter->next) { 12792 it = config_iter; 12793 do {nk_size i = 0; 12794 int char_idx = 0; 12795 nk_rune glyph_count = 0; 12796 const struct nk_font_config *cfg = it; 12797 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12798 struct nk_baked_font *dst_font = cfg->font; 12799 12800 float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size); 12801 int unscaled_ascent, unscaled_descent, unscaled_line_gap; 12802 nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent, 12803 &unscaled_line_gap); 12804 12805 /* fill baked font */ 12806 if (!cfg->merge_mode) { 12807 dst_font->ranges = cfg->range; 12808 dst_font->height = cfg->size; 12809 dst_font->ascent = ((float)unscaled_ascent * font_scale); 12810 dst_font->descent = ((float)unscaled_descent * font_scale); 12811 dst_font->glyph_offset = glyph_n; 12812 } 12813 12814 /* fill own baked font glyph array */ 12815 for (i = 0; i < tmp->range_count; ++i) { 12816 struct nk_tt_pack_range *range = &tmp->ranges[i]; 12817 for (char_idx = 0; char_idx < range->num_chars; char_idx++) 12818 { 12819 nk_rune codepoint = 0; 12820 float dummy_x = 0, dummy_y = 0; 12821 struct nk_tt_aligned_quad q; 12822 struct nk_font_glyph *glyph; 12823 12824 /* query glyph bounds from stb_truetype */ 12825 const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx]; 12826 if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue; 12827 codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx); 12828 nk_tt_GetPackedQuad(range->chardata_for_range, (int)width, 12829 (int)height, char_idx, &dummy_x, &dummy_y, &q, 0); 12830 12831 /* fill own glyph type with data */ 12832 glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count]; 12833 glyph->codepoint = codepoint; 12834 glyph->x0 = q.x0; glyph->y0 = q.y0; 12835 glyph->x1 = q.x1; glyph->y1 = q.y1; 12836 glyph->y0 += (dst_font->ascent + 0.5f); 12837 glyph->y1 += (dst_font->ascent + 0.5f); 12838 glyph->w = glyph->x1 - glyph->x0 + 0.5f; 12839 glyph->h = glyph->y1 - glyph->y0; 12840 12841 if (cfg->coord_type == NK_COORD_PIXEL) { 12842 glyph->u0 = q.s0 * (float)width; 12843 glyph->v0 = q.t0 * (float)height; 12844 glyph->u1 = q.s1 * (float)width; 12845 glyph->v1 = q.t1 * (float)height; 12846 } else { 12847 glyph->u0 = q.s0; 12848 glyph->v0 = q.t0; 12849 glyph->u1 = q.s1; 12850 glyph->v1 = q.t1; 12851 } 12852 glyph->xadvance = (pc->xadvance + cfg->spacing.x); 12853 if (cfg->pixel_snap) 12854 glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f); 12855 glyph_count++; 12856 } 12857 } 12858 dst_font->glyph_count += glyph_count; 12859 glyph_n += glyph_count; 12860 } while ((it = it->n) != config_iter); 12861 } 12862 } 12863 NK_INTERN void 12864 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height, 12865 struct nk_recti img_dst, const char *texture_data_mask, int tex_width, 12866 int tex_height, char white, char black) 12867 { 12868 nk_byte *pixels; 12869 int y = 0; 12870 int x = 0; 12871 int n = 0; 12872 12873 NK_ASSERT(img_memory); 12874 NK_ASSERT(img_width); 12875 NK_ASSERT(img_height); 12876 NK_ASSERT(texture_data_mask); 12877 NK_UNUSED(tex_height); 12878 if (!img_memory || !img_width || !img_height || !texture_data_mask) 12879 return; 12880 12881 pixels = (nk_byte*)img_memory; 12882 for (y = 0, n = 0; y < tex_height; ++y) { 12883 for (x = 0; x < tex_width; ++x, ++n) { 12884 const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width); 12885 const int off1 = off0 + 1 + tex_width; 12886 pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00; 12887 pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00; 12888 } 12889 } 12890 } 12891 NK_INTERN void 12892 nk_font_bake_convert(void *out_memory, int img_width, int img_height, 12893 const void *in_memory) 12894 { 12895 int n = 0; 12896 nk_rune *dst; 12897 const nk_byte *src; 12898 12899 NK_ASSERT(out_memory); 12900 NK_ASSERT(in_memory); 12901 NK_ASSERT(img_width); 12902 NK_ASSERT(img_height); 12903 if (!out_memory || !in_memory || !img_height || !img_width) return; 12904 12905 dst = (nk_rune*)out_memory; 12906 src = (const nk_byte*)in_memory; 12907 for (n = (int)(img_width * img_height); n > 0; n--) 12908 *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF; 12909 } 12910 12911 /* ------------------------------------------------------------- 12912 * 12913 * FONT 12914 * 12915 * --------------------------------------------------------------*/ 12916 NK_INTERN float 12917 nk_font_text_width(nk_handle handle, float height, const char *text, int len) 12918 { 12919 nk_rune unicode; 12920 int text_len = 0; 12921 float text_width = 0; 12922 int glyph_len = 0; 12923 float scale = 0; 12924 12925 struct nk_font *font = (struct nk_font*)handle.ptr; 12926 NK_ASSERT(font); 12927 NK_ASSERT(font->glyphs); 12928 if (!font || !text || !len) 12929 return 0; 12930 12931 scale = height/font->info.height; 12932 glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len); 12933 if (!glyph_len) return 0; 12934 while (text_len <= (int)len && glyph_len) { 12935 const struct nk_font_glyph *g; 12936 if (unicode == NK_UTF_INVALID) break; 12937 12938 /* query currently drawn glyph information */ 12939 g = nk_font_find_glyph(font, unicode); 12940 text_width += g->xadvance * scale; 12941 12942 /* offset next glyph */ 12943 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len); 12944 text_len += glyph_len; 12945 } 12946 return text_width; 12947 } 12948 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 12949 NK_INTERN void 12950 nk_font_query_font_glyph(nk_handle handle, float height, 12951 struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 12952 { 12953 float scale; 12954 const struct nk_font_glyph *g; 12955 struct nk_font *font; 12956 12957 NK_ASSERT(glyph); 12958 NK_UNUSED(next_codepoint); 12959 12960 font = (struct nk_font*)handle.ptr; 12961 NK_ASSERT(font); 12962 NK_ASSERT(font->glyphs); 12963 if (!font || !glyph) 12964 return; 12965 12966 scale = height/font->info.height; 12967 g = nk_font_find_glyph(font, codepoint); 12968 glyph->width = (g->x1 - g->x0) * scale; 12969 glyph->height = (g->y1 - g->y0) * scale; 12970 glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); 12971 glyph->xadvance = (g->xadvance * scale); 12972 glyph->uv[0] = nk_vec2(g->u0, g->v0); 12973 glyph->uv[1] = nk_vec2(g->u1, g->v1); 12974 } 12975 #endif 12976 NK_API const struct nk_font_glyph* 12977 nk_font_find_glyph(struct nk_font *font, nk_rune unicode) 12978 { 12979 int i = 0; 12980 int count; 12981 int total_glyphs = 0; 12982 const struct nk_font_glyph *glyph = 0; 12983 const struct nk_font_config *iter = 0; 12984 12985 NK_ASSERT(font); 12986 NK_ASSERT(font->glyphs); 12987 NK_ASSERT(font->info.ranges); 12988 if (!font || !font->glyphs) return 0; 12989 12990 glyph = font->fallback; 12991 iter = font->config; 12992 do {count = nk_range_count(iter->range); 12993 for (i = 0; i < count; ++i) { 12994 nk_rune f = iter->range[(i*2)+0]; 12995 nk_rune t = iter->range[(i*2)+1]; 12996 int diff = (int)((t - f) + 1); 12997 if (unicode >= f && unicode <= t) 12998 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))]; 12999 total_glyphs += diff; 13000 } 13001 } while ((iter = iter->n) != font->config); 13002 return glyph; 13003 } 13004 NK_INTERN void 13005 nk_font_init(struct nk_font *font, float pixel_height, 13006 nk_rune fallback_codepoint, struct nk_font_glyph *glyphs, 13007 const struct nk_baked_font *baked_font, nk_handle atlas) 13008 { 13009 struct nk_baked_font baked; 13010 NK_ASSERT(font); 13011 NK_ASSERT(glyphs); 13012 NK_ASSERT(baked_font); 13013 if (!font || !glyphs || !baked_font) 13014 return; 13015 13016 baked = *baked_font; 13017 font->fallback = 0; 13018 font->info = baked; 13019 font->scale = (float)pixel_height / (float)font->info.height; 13020 font->glyphs = &glyphs[baked_font->glyph_offset]; 13021 font->texture = atlas; 13022 font->fallback_codepoint = fallback_codepoint; 13023 font->fallback = nk_font_find_glyph(font, fallback_codepoint); 13024 13025 font->handle.height = font->info.height * font->scale; 13026 font->handle.width = nk_font_text_width; 13027 font->handle.userdata.ptr = font; 13028 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13029 font->handle.query = nk_font_query_font_glyph; 13030 font->handle.texture = font->texture; 13031 #endif 13032 } 13033 13034 /* --------------------------------------------------------------------------- 13035 * 13036 * DEFAULT FONT 13037 * 13038 * ProggyClean.ttf 13039 * Copyright (c) 2004, 2005 Tristan Grimmer 13040 * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) 13041 * Download and more information at http://upperbounds.net 13042 *-----------------------------------------------------------------------------*/ 13043 #ifdef __clang__ 13044 #pragma clang diagnostic push 13045 #pragma clang diagnostic ignored "-Woverlength-strings" 13046 #elif defined(__GNUC__) || defined(__GNUG__) 13047 #pragma GCC diagnostic push 13048 #pragma GCC diagnostic ignored "-Woverlength-strings" 13049 #endif 13050 13051 #ifdef NK_INCLUDE_DEFAULT_FONT 13052 13053 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] = 13054 "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" 13055 "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#" 13056 "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL" 13057 "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N" 13058 "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N" 13059 "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cXm#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)" 13060 "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX" 13061 "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc." 13062 "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G" 13063 "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)" 13064 "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#" 13065 "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM" 13066 "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu" 13067 "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/" 13068 "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L" 13069 "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#" 13070 "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)(" 13071 "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h" 13072 "o;#2:;%d	v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" 13073 "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-" 13074 "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-" 13075 "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO" 13076 "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%" 13077 "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]" 13078 "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et" 13079 "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:" 13080 "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL(" 13081 "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<" 13082 "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?" 13083 "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;" 13084 ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M" 13085 "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(" 13086 "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs" 13087 "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" 13088 "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-" 13089 "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" 13090 "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P	r+$%CE=68>K8r0=dSC%%(@p7" 13091 ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@" 13092 "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*" 13093 "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u" 13094 "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#" 13095 "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#" 13096 "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0" 13097 "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" 13098 "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#" 13099 "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD" 13100 ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+" 13101 "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*" 13102 "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7" 13103 ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A" 13104 "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7" 13105 "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT" 13106 "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M" 13107 ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>" 13108 "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%" 13109 "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;" 13110 "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:" 13111 "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%" 13112 "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-" 13113 "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*" 13114 "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY" 13115 "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-" 13116 "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`" 13117 "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/" 13118 "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj" 13119 "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V" 13120 "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK" 13121 "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa" 13122 ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>" 13123 "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I" 13124 "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#" 13125 "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$" 13126 "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)" 13127 "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo" 13128 "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P" 13129 "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO" 13130 "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#" 13131 ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>" 13132 "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#" 13133 "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" 13134 "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#" 13135 "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#" 13136 "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#" 13137 "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" 13138 "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" 13139 "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; 13140 13141 #endif /* NK_INCLUDE_DEFAULT_FONT */ 13142 13143 #define NK_CURSOR_DATA_W 90 13144 #define NK_CURSOR_DATA_H 27 13145 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] = 13146 { 13147 "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" 13148 "..- -X.....X- X.X - X.X -X.....X - X.....X" 13149 "--- -XXX.XXX- X...X - X...X -X....X - X....X" 13150 "X - X.X - X.....X - X.....X -X...X - X...X" 13151 "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" 13152 "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" 13153 "X..X - X.X - X.X - X.X -XX X.X - X.X XX" 13154 "X...X - X.X - X.X - XX X.X XX - X.X - X.X " 13155 "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " 13156 "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " 13157 "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " 13158 "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " 13159 "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " 13160 "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " 13161 "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " 13162 "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " 13163 "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " 13164 "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" 13165 "X.X X..X - -X.......X- X.......X - XX XX - " 13166 "XX X..X - - X.....X - X.....X - X.X X.X - " 13167 " X..X - X...X - X...X - X..X X..X - " 13168 " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " 13169 "------------ - X - X -X.....................X- " 13170 " ----------------------------------- X...XXXXXXXXXXXXX...X - " 13171 " - X..X X..X - " 13172 " - X.X X.X - " 13173 " - XX XX - " 13174 }; 13175 13176 #ifdef __clang__ 13177 #pragma clang diagnostic pop 13178 #elif defined(__GNUC__) || defined(__GNUG__) 13179 #pragma GCC diagnostic pop 13180 #endif 13181 13182 NK_GLOBAL unsigned char *nk__barrier; 13183 NK_GLOBAL unsigned char *nk__barrier2; 13184 NK_GLOBAL unsigned char *nk__barrier3; 13185 NK_GLOBAL unsigned char *nk__barrier4; 13186 NK_GLOBAL unsigned char *nk__dout; 13187 13188 NK_INTERN unsigned int 13189 nk_decompress_length(unsigned char *input) 13190 { 13191 return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]); 13192 } 13193 NK_INTERN void 13194 nk__match(unsigned char *data, unsigned int length) 13195 { 13196 /* INVERSE of memmove... write each byte before copying the next...*/ 13197 NK_ASSERT (nk__dout + length <= nk__barrier); 13198 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 13199 if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; } 13200 while (length--) *nk__dout++ = *data++; 13201 } 13202 NK_INTERN void 13203 nk__lit(unsigned char *data, unsigned int length) 13204 { 13205 NK_ASSERT (nk__dout + length <= nk__barrier); 13206 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 13207 if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; } 13208 NK_MEMCPY(nk__dout, data, length); 13209 nk__dout += length; 13210 } 13211 NK_INTERN unsigned char* 13212 nk_decompress_token(unsigned char *i) 13213 { 13214 #define nk__in2(x) ((i[x] << 8) + i[(x)+1]) 13215 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1)) 13216 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1)) 13217 13218 if (*i >= 0x20) { /* use fewer if's for cases that expand small */ 13219 if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2; 13220 else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3; 13221 else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); 13222 } else { /* more ifs for cases that expand large, since overhead is amortized */ 13223 if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4; 13224 else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5; 13225 else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1); 13226 else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1); 13227 else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5; 13228 else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6; 13229 } 13230 return i; 13231 } 13232 NK_INTERN unsigned int 13233 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) 13234 { 13235 const unsigned long ADLER_MOD = 65521; 13236 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; 13237 unsigned long blocklen, i; 13238 13239 blocklen = buflen % 5552; 13240 while (buflen) { 13241 for (i=0; i + 7 < blocklen; i += 8) { 13242 s1 += buffer[0]; s2 += s1; 13243 s1 += buffer[1]; s2 += s1; 13244 s1 += buffer[2]; s2 += s1; 13245 s1 += buffer[3]; s2 += s1; 13246 s1 += buffer[4]; s2 += s1; 13247 s1 += buffer[5]; s2 += s1; 13248 s1 += buffer[6]; s2 += s1; 13249 s1 += buffer[7]; s2 += s1; 13250 buffer += 8; 13251 } 13252 for (; i < blocklen; ++i) { 13253 s1 += *buffer++; s2 += s1; 13254 } 13255 13256 s1 %= ADLER_MOD; s2 %= ADLER_MOD; 13257 buflen -= (unsigned int)blocklen; 13258 blocklen = 5552; 13259 } 13260 return (unsigned int)(s2 << 16) + (unsigned int)s1; 13261 } 13262 NK_INTERN unsigned int 13263 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length) 13264 { 13265 unsigned int olen; 13266 if (nk__in4(0) != 0x57bC0000) return 0; 13267 if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */ 13268 olen = nk_decompress_length(i); 13269 nk__barrier2 = i; 13270 nk__barrier3 = i+length; 13271 nk__barrier = output + olen; 13272 nk__barrier4 = output; 13273 i += 16; 13274 13275 nk__dout = output; 13276 for (;;) { 13277 unsigned char *old_i = i; 13278 i = nk_decompress_token(i); 13279 if (i == old_i) { 13280 if (*i == 0x05 && i[1] == 0xfa) { 13281 NK_ASSERT(nk__dout == output + olen); 13282 if (nk__dout != output + olen) return 0; 13283 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2)) 13284 return 0; 13285 return olen; 13286 } else { 13287 NK_ASSERT(0); /* NOTREACHED */ 13288 return 0; 13289 } 13290 } 13291 NK_ASSERT(nk__dout <= output + olen); 13292 if (nk__dout > output + olen) 13293 return 0; 13294 } 13295 } 13296 NK_INTERN unsigned int 13297 nk_decode_85_byte(char c) 13298 { 13299 return (unsigned int)((c >= '\\') ? c-36 : c-35); 13300 } 13301 NK_INTERN void 13302 nk_decode_85(unsigned char* dst, const unsigned char* src) 13303 { 13304 while (*src) 13305 { 13306 unsigned int tmp = 13307 nk_decode_85_byte((char)src[0]) + 13308 85 * (nk_decode_85_byte((char)src[1]) + 13309 85 * (nk_decode_85_byte((char)src[2]) + 13310 85 * (nk_decode_85_byte((char)src[3]) + 13311 85 * nk_decode_85_byte((char)src[4])))); 13312 13313 /* we can't assume little-endianess. */ 13314 dst[0] = (unsigned char)((tmp >> 0) & 0xFF); 13315 dst[1] = (unsigned char)((tmp >> 8) & 0xFF); 13316 dst[2] = (unsigned char)((tmp >> 16) & 0xFF); 13317 dst[3] = (unsigned char)((tmp >> 24) & 0xFF); 13318 13319 src += 5; 13320 dst += 4; 13321 } 13322 } 13323 13324 /* ------------------------------------------------------------- 13325 * 13326 * FONT ATLAS 13327 * 13328 * --------------------------------------------------------------*/ 13329 NK_API struct nk_font_config 13330 nk_font_config(float pixel_height) 13331 { 13332 struct nk_font_config cfg; 13333 nk_zero_struct(cfg); 13334 cfg.ttf_blob = 0; 13335 cfg.ttf_size = 0; 13336 cfg.ttf_data_owned_by_atlas = 0; 13337 cfg.size = pixel_height; 13338 cfg.oversample_h = 3; 13339 cfg.oversample_v = 1; 13340 cfg.pixel_snap = 0; 13341 cfg.coord_type = NK_COORD_UV; 13342 cfg.spacing = nk_vec2(0,0); 13343 cfg.range = nk_font_default_glyph_ranges(); 13344 cfg.merge_mode = 0; 13345 cfg.fallback_glyph = '?'; 13346 cfg.font = 0; 13347 cfg.n = 0; 13348 return cfg; 13349 } 13350 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 13351 NK_API void 13352 nk_font_atlas_init_default(struct nk_font_atlas *atlas) 13353 { 13354 NK_ASSERT(atlas); 13355 if (!atlas) return; 13356 nk_zero_struct(*atlas); 13357 atlas->temporary.userdata.ptr = 0; 13358 atlas->temporary.alloc = nk_malloc; 13359 atlas->temporary.free = nk_mfree; 13360 atlas->permanent.userdata.ptr = 0; 13361 atlas->permanent.alloc = nk_malloc; 13362 atlas->permanent.free = nk_mfree; 13363 } 13364 #endif 13365 NK_API void 13366 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc) 13367 { 13368 NK_ASSERT(atlas); 13369 NK_ASSERT(alloc); 13370 if (!atlas || !alloc) return; 13371 nk_zero_struct(*atlas); 13372 atlas->permanent = *alloc; 13373 atlas->temporary = *alloc; 13374 } 13375 NK_API void 13376 nk_font_atlas_init_custom(struct nk_font_atlas *atlas, 13377 struct nk_allocator *permanent, struct nk_allocator *temporary) 13378 { 13379 NK_ASSERT(atlas); 13380 NK_ASSERT(permanent); 13381 NK_ASSERT(temporary); 13382 if (!atlas || !permanent || !temporary) return; 13383 nk_zero_struct(*atlas); 13384 atlas->permanent = *permanent; 13385 atlas->temporary = *temporary; 13386 } 13387 NK_API void 13388 nk_font_atlas_begin(struct nk_font_atlas *atlas) 13389 { 13390 NK_ASSERT(atlas); 13391 NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free); 13392 NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free); 13393 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free || 13394 !atlas->temporary.alloc || !atlas->temporary.free) return; 13395 if (atlas->glyphs) { 13396 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13397 atlas->glyphs = 0; 13398 } 13399 if (atlas->pixel) { 13400 atlas->permanent.free(atlas->permanent.userdata, atlas->pixel); 13401 atlas->pixel = 0; 13402 } 13403 } 13404 NK_API struct nk_font* 13405 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config) 13406 { 13407 struct nk_font *font = 0; 13408 struct nk_font_config *cfg; 13409 13410 NK_ASSERT(atlas); 13411 NK_ASSERT(atlas->permanent.alloc); 13412 NK_ASSERT(atlas->permanent.free); 13413 NK_ASSERT(atlas->temporary.alloc); 13414 NK_ASSERT(atlas->temporary.free); 13415 13416 NK_ASSERT(config); 13417 NK_ASSERT(config->ttf_blob); 13418 NK_ASSERT(config->ttf_size); 13419 NK_ASSERT(config->size > 0.0f); 13420 13421 if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f|| 13422 !atlas->permanent.alloc || !atlas->permanent.free || 13423 !atlas->temporary.alloc || !atlas->temporary.free) 13424 return 0; 13425 13426 /* allocate font config */ 13427 cfg = (struct nk_font_config*) 13428 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config)); 13429 NK_MEMCPY(cfg, config, sizeof(*config)); 13430 cfg->n = cfg; 13431 cfg->p = cfg; 13432 13433 if (!config->merge_mode) { 13434 /* insert font config into list */ 13435 if (!atlas->config) { 13436 atlas->config = cfg; 13437 cfg->next = 0; 13438 } else { 13439 struct nk_font_config *i = atlas->config; 13440 while (i->next) i = i->next; 13441 i->next = cfg; 13442 cfg->next = 0; 13443 } 13444 /* allocate new font */ 13445 font = (struct nk_font*) 13446 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font)); 13447 NK_ASSERT(font); 13448 nk_zero(font, sizeof(*font)); 13449 if (!font) return 0; 13450 font->config = cfg; 13451 13452 /* insert font into list */ 13453 if (!atlas->fonts) { 13454 atlas->fonts = font; 13455 font->next = 0; 13456 } else { 13457 struct nk_font *i = atlas->fonts; 13458 while (i->next) i = i->next; 13459 i->next = font; 13460 font->next = 0; 13461 } 13462 cfg->font = &font->info; 13463 } else { 13464 /* extend previously added font */ 13465 struct nk_font *f = 0; 13466 struct nk_font_config *c = 0; 13467 NK_ASSERT(atlas->font_num); 13468 f = atlas->fonts; 13469 c = f->config; 13470 cfg->font = &f->info; 13471 13472 cfg->n = c; 13473 cfg->p = c->p; 13474 c->p->n = cfg; 13475 c->p = cfg; 13476 } 13477 /* create own copy of .TTF font blob */ 13478 if (!config->ttf_data_owned_by_atlas) { 13479 cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size); 13480 NK_ASSERT(cfg->ttf_blob); 13481 if (!cfg->ttf_blob) { 13482 atlas->font_num++; 13483 return 0; 13484 } 13485 NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size); 13486 cfg->ttf_data_owned_by_atlas = 1; 13487 } 13488 atlas->font_num++; 13489 return font; 13490 } 13491 NK_API struct nk_font* 13492 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, 13493 nk_size size, float height, const struct nk_font_config *config) 13494 { 13495 struct nk_font_config cfg; 13496 NK_ASSERT(memory); 13497 NK_ASSERT(size); 13498 13499 NK_ASSERT(atlas); 13500 NK_ASSERT(atlas->temporary.alloc); 13501 NK_ASSERT(atlas->temporary.free); 13502 NK_ASSERT(atlas->permanent.alloc); 13503 NK_ASSERT(atlas->permanent.free); 13504 if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size || 13505 !atlas->permanent.alloc || !atlas->permanent.free) 13506 return 0; 13507 13508 cfg = (config) ? *config: nk_font_config(height); 13509 cfg.ttf_blob = memory; 13510 cfg.ttf_size = size; 13511 cfg.size = height; 13512 cfg.ttf_data_owned_by_atlas = 0; 13513 return nk_font_atlas_add(atlas, &cfg); 13514 } 13515 #ifdef NK_INCLUDE_STANDARD_IO 13516 NK_API struct nk_font* 13517 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, 13518 float height, const struct nk_font_config *config) 13519 { 13520 nk_size size; 13521 char *memory; 13522 struct nk_font_config cfg; 13523 13524 NK_ASSERT(atlas); 13525 NK_ASSERT(atlas->temporary.alloc); 13526 NK_ASSERT(atlas->temporary.free); 13527 NK_ASSERT(atlas->permanent.alloc); 13528 NK_ASSERT(atlas->permanent.free); 13529 13530 if (!atlas || !file_path) return 0; 13531 memory = nk_file_load(file_path, &size, &atlas->permanent); 13532 if (!memory) return 0; 13533 13534 cfg = (config) ? *config: nk_font_config(height); 13535 cfg.ttf_blob = memory; 13536 cfg.ttf_size = size; 13537 cfg.size = height; 13538 cfg.ttf_data_owned_by_atlas = 1; 13539 return nk_font_atlas_add(atlas, &cfg); 13540 } 13541 #endif 13542 NK_API struct nk_font* 13543 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas, 13544 void *compressed_data, nk_size compressed_size, float height, 13545 const struct nk_font_config *config) 13546 { 13547 unsigned int decompressed_size; 13548 void *decompressed_data; 13549 struct nk_font_config cfg; 13550 13551 NK_ASSERT(atlas); 13552 NK_ASSERT(atlas->temporary.alloc); 13553 NK_ASSERT(atlas->temporary.free); 13554 NK_ASSERT(atlas->permanent.alloc); 13555 NK_ASSERT(atlas->permanent.free); 13556 13557 NK_ASSERT(compressed_data); 13558 NK_ASSERT(compressed_size); 13559 if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free || 13560 !atlas->permanent.alloc || !atlas->permanent.free) 13561 return 0; 13562 13563 decompressed_size = nk_decompress_length((unsigned char*)compressed_data); 13564 decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size); 13565 NK_ASSERT(decompressed_data); 13566 if (!decompressed_data) return 0; 13567 nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data, 13568 (unsigned int)compressed_size); 13569 13570 cfg = (config) ? *config: nk_font_config(height); 13571 cfg.ttf_blob = decompressed_data; 13572 cfg.ttf_size = decompressed_size; 13573 cfg.size = height; 13574 cfg.ttf_data_owned_by_atlas = 1; 13575 return nk_font_atlas_add(atlas, &cfg); 13576 } 13577 NK_API struct nk_font* 13578 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas, 13579 const char *data_base85, float height, const struct nk_font_config *config) 13580 { 13581 int compressed_size; 13582 void *compressed_data; 13583 struct nk_font *font; 13584 13585 NK_ASSERT(atlas); 13586 NK_ASSERT(atlas->temporary.alloc); 13587 NK_ASSERT(atlas->temporary.free); 13588 NK_ASSERT(atlas->permanent.alloc); 13589 NK_ASSERT(atlas->permanent.free); 13590 13591 NK_ASSERT(data_base85); 13592 if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free || 13593 !atlas->permanent.alloc || !atlas->permanent.free) 13594 return 0; 13595 13596 compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4; 13597 compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size); 13598 NK_ASSERT(compressed_data); 13599 if (!compressed_data) return 0; 13600 nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85); 13601 font = nk_font_atlas_add_compressed(atlas, compressed_data, 13602 (nk_size)compressed_size, height, config); 13603 atlas->temporary.free(atlas->temporary.userdata, compressed_data); 13604 return font; 13605 } 13606 13607 #ifdef NK_INCLUDE_DEFAULT_FONT 13608 NK_API struct nk_font* 13609 nk_font_atlas_add_default(struct nk_font_atlas *atlas, 13610 float pixel_height, const struct nk_font_config *config) 13611 { 13612 NK_ASSERT(atlas); 13613 NK_ASSERT(atlas->temporary.alloc); 13614 NK_ASSERT(atlas->temporary.free); 13615 NK_ASSERT(atlas->permanent.alloc); 13616 NK_ASSERT(atlas->permanent.free); 13617 return nk_font_atlas_add_compressed_base85(atlas, 13618 nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config); 13619 } 13620 #endif 13621 NK_API const void* 13622 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height, 13623 enum nk_font_atlas_format fmt) 13624 { 13625 int i = 0; 13626 void *tmp = 0; 13627 nk_size tmp_size, img_size; 13628 struct nk_font *font_iter; 13629 struct nk_font_baker *baker; 13630 13631 NK_ASSERT(atlas); 13632 NK_ASSERT(atlas->temporary.alloc); 13633 NK_ASSERT(atlas->temporary.free); 13634 NK_ASSERT(atlas->permanent.alloc); 13635 NK_ASSERT(atlas->permanent.free); 13636 13637 NK_ASSERT(width); 13638 NK_ASSERT(height); 13639 if (!atlas || !width || !height || 13640 !atlas->temporary.alloc || !atlas->temporary.free || 13641 !atlas->permanent.alloc || !atlas->permanent.free) 13642 return 0; 13643 13644 #ifdef NK_INCLUDE_DEFAULT_FONT 13645 /* no font added so just use default font */ 13646 if (!atlas->font_num) 13647 atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0); 13648 #endif 13649 NK_ASSERT(atlas->font_num); 13650 if (!atlas->font_num) return 0; 13651 13652 /* allocate temporary baker memory required for the baking process */ 13653 nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num); 13654 tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size); 13655 NK_ASSERT(tmp); 13656 if (!tmp) goto failed; 13657 13658 /* allocate glyph memory for all fonts */ 13659 baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary); 13660 atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc( 13661 atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count); 13662 NK_ASSERT(atlas->glyphs); 13663 if (!atlas->glyphs) 13664 goto failed; 13665 13666 /* pack all glyphs into a tight fit space */ 13667 atlas->custom.w = (NK_CURSOR_DATA_W*2)+1; 13668 atlas->custom.h = NK_CURSOR_DATA_H + 1; 13669 if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom, 13670 atlas->config, atlas->font_num, &atlas->temporary)) 13671 goto failed; 13672 13673 /* allocate memory for the baked image font atlas */ 13674 atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size); 13675 NK_ASSERT(atlas->pixel); 13676 if (!atlas->pixel) 13677 goto failed; 13678 13679 /* bake glyphs and custom white pixel into image */ 13680 nk_font_bake(baker, atlas->pixel, *width, *height, 13681 atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num); 13682 nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom, 13683 nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X'); 13684 13685 if (fmt == NK_FONT_ATLAS_RGBA32) { 13686 /* convert alpha8 image into rgba32 image */ 13687 void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0, 13688 (nk_size)(*width * *height * 4)); 13689 NK_ASSERT(img_rgba); 13690 if (!img_rgba) goto failed; 13691 nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel); 13692 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13693 atlas->pixel = img_rgba; 13694 } 13695 atlas->tex_width = *width; 13696 atlas->tex_height = *height; 13697 13698 /* initialize each font */ 13699 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 13700 struct nk_font *font = font_iter; 13701 struct nk_font_config *config = font->config; 13702 nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs, 13703 config->font, nk_handle_ptr(0)); 13704 } 13705 13706 /* initialize each cursor */ 13707 {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = { 13708 /* Pos Size Offset */ 13709 {{ 0, 3}, {12,19}, { 0, 0}}, 13710 {{13, 0}, { 7,16}, { 4, 8}}, 13711 {{31, 0}, {23,23}, {11,11}}, 13712 {{21, 0}, { 9, 23}, { 5,11}}, 13713 {{55,18}, {23, 9}, {11, 5}}, 13714 {{73, 0}, {17,17}, { 9, 9}}, 13715 {{55, 0}, {17,17}, { 9, 9}} 13716 }; 13717 for (i = 0; i < NK_CURSOR_COUNT; ++i) { 13718 struct nk_cursor *cursor = &atlas->cursors[i]; 13719 cursor->img.w = (unsigned short)*width; 13720 cursor->img.h = (unsigned short)*height; 13721 cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x); 13722 cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y); 13723 cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x; 13724 cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y; 13725 cursor->size = nk_cursor_data[i][1]; 13726 cursor->offset = nk_cursor_data[i][2]; 13727 }} 13728 /* free temporary memory */ 13729 atlas->temporary.free(atlas->temporary.userdata, tmp); 13730 return atlas->pixel; 13731 13732 failed: 13733 /* error so cleanup all memory */ 13734 if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp); 13735 if (atlas->glyphs) { 13736 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13737 atlas->glyphs = 0; 13738 } 13739 if (atlas->pixel) { 13740 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13741 atlas->pixel = 0; 13742 } 13743 return 0; 13744 } 13745 NK_API void 13746 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, 13747 struct nk_draw_null_texture *null) 13748 { 13749 int i = 0; 13750 struct nk_font *font_iter; 13751 NK_ASSERT(atlas); 13752 if (!atlas) { 13753 if (!null) return; 13754 null->texture = texture; 13755 null->uv = nk_vec2(0.5f,0.5f); 13756 } 13757 if (null) { 13758 null->texture = texture; 13759 null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; 13760 null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; 13761 } 13762 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 13763 font_iter->texture = texture; 13764 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13765 font_iter->handle.texture = texture; 13766 #endif 13767 } 13768 for (i = 0; i < NK_CURSOR_COUNT; ++i) 13769 atlas->cursors[i].img.handle = texture; 13770 13771 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13772 atlas->pixel = 0; 13773 atlas->tex_width = 0; 13774 atlas->tex_height = 0; 13775 atlas->custom.x = 0; 13776 atlas->custom.y = 0; 13777 atlas->custom.w = 0; 13778 atlas->custom.h = 0; 13779 } 13780 NK_API void 13781 nk_font_atlas_cleanup(struct nk_font_atlas *atlas) 13782 { 13783 NK_ASSERT(atlas); 13784 NK_ASSERT(atlas->temporary.alloc); 13785 NK_ASSERT(atlas->temporary.free); 13786 NK_ASSERT(atlas->permanent.alloc); 13787 NK_ASSERT(atlas->permanent.free); 13788 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 13789 if (atlas->config) { 13790 struct nk_font_config *iter; 13791 for (iter = atlas->config; iter; iter = iter->next) { 13792 struct nk_font_config *i; 13793 for (i = iter->n; i != iter; i = i->n) { 13794 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 13795 i->ttf_blob = 0; 13796 } 13797 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 13798 iter->ttf_blob = 0; 13799 } 13800 } 13801 } 13802 NK_API void 13803 nk_font_atlas_clear(struct nk_font_atlas *atlas) 13804 { 13805 NK_ASSERT(atlas); 13806 NK_ASSERT(atlas->temporary.alloc); 13807 NK_ASSERT(atlas->temporary.free); 13808 NK_ASSERT(atlas->permanent.alloc); 13809 NK_ASSERT(atlas->permanent.free); 13810 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 13811 13812 if (atlas->config) { 13813 struct nk_font_config *iter, *next; 13814 for (iter = atlas->config; iter; iter = next) { 13815 struct nk_font_config *i, *n; 13816 for (i = iter->n; i != iter; i = n) { 13817 n = i->n; 13818 if (i->ttf_blob) 13819 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 13820 atlas->permanent.free(atlas->permanent.userdata, i); 13821 } 13822 next = iter->next; 13823 if (i->ttf_blob) 13824 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 13825 atlas->permanent.free(atlas->permanent.userdata, iter); 13826 } 13827 atlas->config = 0; 13828 } 13829 if (atlas->fonts) { 13830 struct nk_font *iter, *next; 13831 for (iter = atlas->fonts; iter; iter = next) { 13832 next = iter->next; 13833 atlas->permanent.free(atlas->permanent.userdata, iter); 13834 } 13835 atlas->fonts = 0; 13836 } 13837 if (atlas->glyphs) 13838 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13839 nk_zero_struct(*atlas); 13840 } 13841 #endif 13842 13843 13844 13845 13846 13847 /* =============================================================== 13848 * 13849 * INPUT 13850 * 13851 * ===============================================================*/ 13852 NK_API void 13853 nk_input_begin(struct nk_context *ctx) 13854 { 13855 int i; 13856 struct nk_input *in; 13857 NK_ASSERT(ctx); 13858 if (!ctx) return; 13859 in = &ctx->input; 13860 for (i = 0; i < NK_BUTTON_MAX; ++i) 13861 in->mouse.buttons[i].clicked = 0; 13862 13863 in->keyboard.text_len = 0; 13864 in->mouse.scroll_delta = nk_vec2(0,0); 13865 in->mouse.prev.x = in->mouse.pos.x; 13866 in->mouse.prev.y = in->mouse.pos.y; 13867 in->mouse.delta.x = 0; 13868 in->mouse.delta.y = 0; 13869 for (i = 0; i < NK_KEY_MAX; i++) 13870 in->keyboard.keys[i].clicked = 0; 13871 } 13872 NK_API void 13873 nk_input_end(struct nk_context *ctx) 13874 { 13875 struct nk_input *in; 13876 NK_ASSERT(ctx); 13877 if (!ctx) return; 13878 in = &ctx->input; 13879 if (in->mouse.grab) 13880 in->mouse.grab = 0; 13881 if (in->mouse.ungrab) { 13882 in->mouse.grabbed = 0; 13883 in->mouse.ungrab = 0; 13884 in->mouse.grab = 0; 13885 } 13886 } 13887 NK_API void 13888 nk_input_motion(struct nk_context *ctx, int x, int y) 13889 { 13890 struct nk_input *in; 13891 NK_ASSERT(ctx); 13892 if (!ctx) return; 13893 in = &ctx->input; 13894 in->mouse.pos.x = (float)x; 13895 in->mouse.pos.y = (float)y; 13896 in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x; 13897 in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y; 13898 } 13899 NK_API void 13900 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down) 13901 { 13902 struct nk_input *in; 13903 NK_ASSERT(ctx); 13904 if (!ctx) return; 13905 in = &ctx->input; 13906 if (in->keyboard.keys[key].down != down) 13907 in->keyboard.keys[key].clicked++; 13908 in->keyboard.keys[key].down = down; 13909 } 13910 NK_API void 13911 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down) 13912 { 13913 struct nk_mouse_button *btn; 13914 struct nk_input *in; 13915 NK_ASSERT(ctx); 13916 if (!ctx) return; 13917 in = &ctx->input; 13918 if (in->mouse.buttons[id].down == down) return; 13919 13920 btn = &in->mouse.buttons[id]; 13921 btn->clicked_pos.x = (float)x; 13922 btn->clicked_pos.y = (float)y; 13923 btn->down = down; 13924 btn->clicked++; 13925 } 13926 NK_API void 13927 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val) 13928 { 13929 NK_ASSERT(ctx); 13930 if (!ctx) return; 13931 ctx->input.mouse.scroll_delta.x += val.x; 13932 ctx->input.mouse.scroll_delta.y += val.y; 13933 } 13934 NK_API void 13935 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph) 13936 { 13937 int len = 0; 13938 nk_rune unicode; 13939 struct nk_input *in; 13940 13941 NK_ASSERT(ctx); 13942 if (!ctx) return; 13943 in = &ctx->input; 13944 13945 len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE); 13946 if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) { 13947 nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len], 13948 NK_INPUT_MAX - in->keyboard.text_len); 13949 in->keyboard.text_len += len; 13950 } 13951 } 13952 NK_API void 13953 nk_input_char(struct nk_context *ctx, char c) 13954 { 13955 nk_glyph glyph; 13956 NK_ASSERT(ctx); 13957 if (!ctx) return; 13958 glyph[0] = c; 13959 nk_input_glyph(ctx, glyph); 13960 } 13961 NK_API void 13962 nk_input_unicode(struct nk_context *ctx, nk_rune unicode) 13963 { 13964 nk_glyph rune; 13965 NK_ASSERT(ctx); 13966 if (!ctx) return; 13967 nk_utf_encode(unicode, rune, NK_UTF_SIZE); 13968 nk_input_glyph(ctx, rune); 13969 } 13970 NK_API int 13971 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id) 13972 { 13973 const struct nk_mouse_button *btn; 13974 if (!i) return nk_false; 13975 btn = &i->mouse.buttons[id]; 13976 return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false; 13977 } 13978 NK_API int 13979 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 13980 struct nk_rect b) 13981 { 13982 const struct nk_mouse_button *btn; 13983 if (!i) return nk_false; 13984 btn = &i->mouse.buttons[id]; 13985 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) 13986 return nk_false; 13987 return nk_true; 13988 } 13989 NK_API int 13990 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 13991 struct nk_rect b, int down) 13992 { 13993 const struct nk_mouse_button *btn; 13994 if (!i) return nk_false; 13995 btn = &i->mouse.buttons[id]; 13996 return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down); 13997 } 13998 NK_API int 13999 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 14000 struct nk_rect b) 14001 { 14002 const struct nk_mouse_button *btn; 14003 if (!i) return nk_false; 14004 btn = &i->mouse.buttons[id]; 14005 return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) && 14006 btn->clicked) ? nk_true : nk_false; 14007 } 14008 NK_API int 14009 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 14010 struct nk_rect b, int down) 14011 { 14012 const struct nk_mouse_button *btn; 14013 if (!i) return nk_false; 14014 btn = &i->mouse.buttons[id]; 14015 return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) && 14016 btn->clicked) ? nk_true : nk_false; 14017 } 14018 NK_API int 14019 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b) 14020 { 14021 int i, down = 0; 14022 for (i = 0; i < NK_BUTTON_MAX; ++i) 14023 down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b); 14024 return down; 14025 } 14026 NK_API int 14027 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect) 14028 { 14029 if (!i) return nk_false; 14030 return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h); 14031 } 14032 NK_API int 14033 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect) 14034 { 14035 if (!i) return nk_false; 14036 return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h); 14037 } 14038 NK_API int 14039 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect) 14040 { 14041 if (!i) return nk_false; 14042 if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false; 14043 return nk_input_is_mouse_click_in_rect(i, id, rect); 14044 } 14045 NK_API int 14046 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id) 14047 { 14048 if (!i) return nk_false; 14049 return i->mouse.buttons[id].down; 14050 } 14051 NK_API int 14052 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id) 14053 { 14054 const struct nk_mouse_button *b; 14055 if (!i) return nk_false; 14056 b = &i->mouse.buttons[id]; 14057 if (b->down && b->clicked) 14058 return nk_true; 14059 return nk_false; 14060 } 14061 NK_API int 14062 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id) 14063 { 14064 if (!i) return nk_false; 14065 return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked); 14066 } 14067 NK_API int 14068 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key) 14069 { 14070 const struct nk_key *k; 14071 if (!i) return nk_false; 14072 k = &i->keyboard.keys[key]; 14073 if ((k->down && k->clicked) || (!k->down && k->clicked >= 2)) 14074 return nk_true; 14075 return nk_false; 14076 } 14077 NK_API int 14078 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key) 14079 { 14080 const struct nk_key *k; 14081 if (!i) return nk_false; 14082 k = &i->keyboard.keys[key]; 14083 if ((!k->down && k->clicked) || (k->down && k->clicked >= 2)) 14084 return nk_true; 14085 return nk_false; 14086 } 14087 NK_API int 14088 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key) 14089 { 14090 const struct nk_key *k; 14091 if (!i) return nk_false; 14092 k = &i->keyboard.keys[key]; 14093 if (k->down) return nk_true; 14094 return nk_false; 14095 } 14096 14097 14098 14099 14100 14101 /* =============================================================== 14102 * 14103 * STYLE 14104 * 14105 * ===============================================================*/ 14106 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);} 14107 #define NK_COLOR_MAP(NK_COLOR)\ 14108 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \ 14109 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \ 14110 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \ 14111 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \ 14112 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \ 14113 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \ 14114 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \ 14115 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \ 14116 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ 14117 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ 14118 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ 14119 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ 14120 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ 14121 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ 14122 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ 14123 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ 14124 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ 14125 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ 14126 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ 14127 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ 14128 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ 14129 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \ 14130 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \ 14131 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \ 14132 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ 14133 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \ 14134 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \ 14135 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) 14136 14137 NK_GLOBAL const struct nk_color 14138 nk_default_color_style[NK_COLOR_COUNT] = { 14139 #define NK_COLOR(a,b,c,d,e) {b,c,d,e}, 14140 NK_COLOR_MAP(NK_COLOR) 14141 #undef NK_COLOR 14142 }; 14143 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = { 14144 #define NK_COLOR(a,b,c,d,e) #a, 14145 NK_COLOR_MAP(NK_COLOR) 14146 #undef NK_COLOR 14147 }; 14148 14149 NK_API const char* 14150 nk_style_get_color_by_name(enum nk_style_colors c) 14151 { 14152 return nk_color_names[c]; 14153 } 14154 NK_API struct nk_style_item 14155 nk_style_item_image(struct nk_image img) 14156 { 14157 struct nk_style_item i; 14158 i.type = NK_STYLE_ITEM_IMAGE; 14159 i.data.image = img; 14160 return i; 14161 } 14162 NK_API struct nk_style_item 14163 nk_style_item_color(struct nk_color col) 14164 { 14165 struct nk_style_item i; 14166 i.type = NK_STYLE_ITEM_COLOR; 14167 i.data.color = col; 14168 return i; 14169 } 14170 NK_API struct nk_style_item 14171 nk_style_item_hide(void) 14172 { 14173 struct nk_style_item i; 14174 i.type = NK_STYLE_ITEM_COLOR; 14175 i.data.color = nk_rgba(0,0,0,0); 14176 return i; 14177 } 14178 NK_API void 14179 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) 14180 { 14181 struct nk_style *style; 14182 struct nk_style_text *text; 14183 struct nk_style_button *button; 14184 struct nk_style_toggle *toggle; 14185 struct nk_style_selectable *select; 14186 struct nk_style_slider *slider; 14187 struct nk_style_progress *prog; 14188 struct nk_style_scrollbar *scroll; 14189 struct nk_style_edit *edit; 14190 struct nk_style_property *property; 14191 struct nk_style_combo *combo; 14192 struct nk_style_chart *chart; 14193 struct nk_style_tab *tab; 14194 struct nk_style_window *win; 14195 14196 NK_ASSERT(ctx); 14197 if (!ctx) return; 14198 style = &ctx->style; 14199 table = (!table) ? nk_default_color_style: table; 14200 14201 /* default text */ 14202 text = &style->text; 14203 text->color = table[NK_COLOR_TEXT]; 14204 text->padding = nk_vec2(0,0); 14205 14206 /* default button */ 14207 button = &style->button; 14208 nk_zero_struct(*button); 14209 button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]); 14210 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 14211 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 14212 button->border_color = table[NK_COLOR_BORDER]; 14213 button->text_background = table[NK_COLOR_BUTTON]; 14214 button->text_normal = table[NK_COLOR_TEXT]; 14215 button->text_hover = table[NK_COLOR_TEXT]; 14216 button->text_active = table[NK_COLOR_TEXT]; 14217 button->padding = nk_vec2(2.0f,2.0f); 14218 button->image_padding = nk_vec2(0.0f,0.0f); 14219 button->touch_padding = nk_vec2(0.0f, 0.0f); 14220 button->userdata = nk_handle_ptr(0); 14221 button->text_alignment = NK_TEXT_CENTERED; 14222 button->border = 1.0f; 14223 button->rounding = 4.0f; 14224 button->draw_begin = 0; 14225 button->draw_end = 0; 14226 14227 /* contextual button */ 14228 button = &style->contextual_button; 14229 nk_zero_struct(*button); 14230 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14231 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 14232 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 14233 button->border_color = table[NK_COLOR_WINDOW]; 14234 button->text_background = table[NK_COLOR_WINDOW]; 14235 button->text_normal = table[NK_COLOR_TEXT]; 14236 button->text_hover = table[NK_COLOR_TEXT]; 14237 button->text_active = table[NK_COLOR_TEXT]; 14238 button->padding = nk_vec2(2.0f,2.0f); 14239 button->touch_padding = nk_vec2(0.0f,0.0f); 14240 button->userdata = nk_handle_ptr(0); 14241 button->text_alignment = NK_TEXT_CENTERED; 14242 button->border = 0.0f; 14243 button->rounding = 0.0f; 14244 button->draw_begin = 0; 14245 button->draw_end = 0; 14246 14247 /* menu button */ 14248 button = &style->menu_button; 14249 nk_zero_struct(*button); 14250 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14251 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 14252 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 14253 button->border_color = table[NK_COLOR_WINDOW]; 14254 button->text_background = table[NK_COLOR_WINDOW]; 14255 button->text_normal = table[NK_COLOR_TEXT]; 14256 button->text_hover = table[NK_COLOR_TEXT]; 14257 button->text_active = table[NK_COLOR_TEXT]; 14258 button->padding = nk_vec2(2.0f,2.0f); 14259 button->touch_padding = nk_vec2(0.0f,0.0f); 14260 button->userdata = nk_handle_ptr(0); 14261 button->text_alignment = NK_TEXT_CENTERED; 14262 button->border = 0.0f; 14263 button->rounding = 1.0f; 14264 button->draw_begin = 0; 14265 button->draw_end = 0; 14266 14267 /* checkbox toggle */ 14268 toggle = &style->checkbox; 14269 nk_zero_struct(*toggle); 14270 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 14271 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14272 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14273 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14274 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14275 toggle->userdata = nk_handle_ptr(0); 14276 toggle->text_background = table[NK_COLOR_WINDOW]; 14277 toggle->text_normal = table[NK_COLOR_TEXT]; 14278 toggle->text_hover = table[NK_COLOR_TEXT]; 14279 toggle->text_active = table[NK_COLOR_TEXT]; 14280 toggle->padding = nk_vec2(2.0f, 2.0f); 14281 toggle->touch_padding = nk_vec2(0,0); 14282 toggle->border_color = nk_rgba(0,0,0,0); 14283 toggle->border = 0.0f; 14284 toggle->spacing = 4; 14285 14286 /* option toggle */ 14287 toggle = &style->option; 14288 nk_zero_struct(*toggle); 14289 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 14290 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14291 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14292 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14293 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14294 toggle->userdata = nk_handle_ptr(0); 14295 toggle->text_background = table[NK_COLOR_WINDOW]; 14296 toggle->text_normal = table[NK_COLOR_TEXT]; 14297 toggle->text_hover = table[NK_COLOR_TEXT]; 14298 toggle->text_active = table[NK_COLOR_TEXT]; 14299 toggle->padding = nk_vec2(3.0f, 3.0f); 14300 toggle->touch_padding = nk_vec2(0,0); 14301 toggle->border_color = nk_rgba(0,0,0,0); 14302 toggle->border = 0.0f; 14303 toggle->spacing = 4; 14304 14305 /* selectable */ 14306 select = &style->selectable; 14307 nk_zero_struct(*select); 14308 select->normal = nk_style_item_color(table[NK_COLOR_SELECT]); 14309 select->hover = nk_style_item_color(table[NK_COLOR_SELECT]); 14310 select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]); 14311 select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14312 select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14313 select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14314 select->text_normal = table[NK_COLOR_TEXT]; 14315 select->text_hover = table[NK_COLOR_TEXT]; 14316 select->text_pressed = table[NK_COLOR_TEXT]; 14317 select->text_normal_active = table[NK_COLOR_TEXT]; 14318 select->text_hover_active = table[NK_COLOR_TEXT]; 14319 select->text_pressed_active = table[NK_COLOR_TEXT]; 14320 select->padding = nk_vec2(2.0f,2.0f); 14321 select->image_padding = nk_vec2(2.0f,2.0f); 14322 select->touch_padding = nk_vec2(0,0); 14323 select->userdata = nk_handle_ptr(0); 14324 select->rounding = 0.0f; 14325 select->draw_begin = 0; 14326 select->draw_end = 0; 14327 14328 /* slider */ 14329 slider = &style->slider; 14330 nk_zero_struct(*slider); 14331 slider->normal = nk_style_item_hide(); 14332 slider->hover = nk_style_item_hide(); 14333 slider->active = nk_style_item_hide(); 14334 slider->bar_normal = table[NK_COLOR_SLIDER]; 14335 slider->bar_hover = table[NK_COLOR_SLIDER]; 14336 slider->bar_active = table[NK_COLOR_SLIDER]; 14337 slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR]; 14338 slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 14339 slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 14340 slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 14341 slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT; 14342 slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT; 14343 slider->cursor_size = nk_vec2(16,16); 14344 slider->padding = nk_vec2(2,2); 14345 slider->spacing = nk_vec2(2,2); 14346 slider->userdata = nk_handle_ptr(0); 14347 slider->show_buttons = nk_false; 14348 slider->bar_height = 8; 14349 slider->rounding = 0; 14350 slider->draw_begin = 0; 14351 slider->draw_end = 0; 14352 14353 /* slider buttons */ 14354 button = &style->slider.inc_button; 14355 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 14356 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 14357 button->active = nk_style_item_color(nk_rgb(44,44,44)); 14358 button->border_color = nk_rgb(65,65,65); 14359 button->text_background = nk_rgb(40,40,40); 14360 button->text_normal = nk_rgb(175,175,175); 14361 button->text_hover = nk_rgb(175,175,175); 14362 button->text_active = nk_rgb(175,175,175); 14363 button->padding = nk_vec2(8.0f,8.0f); 14364 button->touch_padding = nk_vec2(0.0f,0.0f); 14365 button->userdata = nk_handle_ptr(0); 14366 button->text_alignment = NK_TEXT_CENTERED; 14367 button->border = 1.0f; 14368 button->rounding = 0.0f; 14369 button->draw_begin = 0; 14370 button->draw_end = 0; 14371 style->slider.dec_button = style->slider.inc_button; 14372 14373 /* progressbar */ 14374 prog = &style->progress; 14375 nk_zero_struct(*prog); 14376 prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]); 14377 prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]); 14378 prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]); 14379 prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 14380 prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 14381 prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 14382 prog->border_color = nk_rgba(0,0,0,0); 14383 prog->cursor_border_color = nk_rgba(0,0,0,0); 14384 prog->userdata = nk_handle_ptr(0); 14385 prog->padding = nk_vec2(4,4); 14386 prog->rounding = 0; 14387 prog->border = 0; 14388 prog->cursor_rounding = 0; 14389 prog->cursor_border = 0; 14390 prog->draw_begin = 0; 14391 prog->draw_end = 0; 14392 14393 /* scrollbars */ 14394 scroll = &style->scrollh; 14395 nk_zero_struct(*scroll); 14396 scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14397 scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14398 scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14399 scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]); 14400 scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]); 14401 scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]); 14402 scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID; 14403 scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID; 14404 scroll->userdata = nk_handle_ptr(0); 14405 scroll->border_color = table[NK_COLOR_SCROLLBAR]; 14406 scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR]; 14407 scroll->padding = nk_vec2(0,0); 14408 scroll->show_buttons = nk_false; 14409 scroll->border = 0; 14410 scroll->rounding = 0; 14411 scroll->border_cursor = 0; 14412 scroll->rounding_cursor = 0; 14413 scroll->draw_begin = 0; 14414 scroll->draw_end = 0; 14415 style->scrollv = style->scrollh; 14416 14417 /* scrollbars buttons */ 14418 button = &style->scrollh.inc_button; 14419 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 14420 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 14421 button->active = nk_style_item_color(nk_rgb(44,44,44)); 14422 button->border_color = nk_rgb(65,65,65); 14423 button->text_background = nk_rgb(40,40,40); 14424 button->text_normal = nk_rgb(175,175,175); 14425 button->text_hover = nk_rgb(175,175,175); 14426 button->text_active = nk_rgb(175,175,175); 14427 button->padding = nk_vec2(4.0f,4.0f); 14428 button->touch_padding = nk_vec2(0.0f,0.0f); 14429 button->userdata = nk_handle_ptr(0); 14430 button->text_alignment = NK_TEXT_CENTERED; 14431 button->border = 1.0f; 14432 button->rounding = 0.0f; 14433 button->draw_begin = 0; 14434 button->draw_end = 0; 14435 style->scrollh.dec_button = style->scrollh.inc_button; 14436 style->scrollv.inc_button = style->scrollh.inc_button; 14437 style->scrollv.dec_button = style->scrollh.inc_button; 14438 14439 /* edit */ 14440 edit = &style->edit; 14441 nk_zero_struct(*edit); 14442 edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]); 14443 edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]); 14444 edit->active = nk_style_item_color(table[NK_COLOR_EDIT]); 14445 edit->cursor_normal = table[NK_COLOR_TEXT]; 14446 edit->cursor_hover = table[NK_COLOR_TEXT]; 14447 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 14448 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 14449 edit->border_color = table[NK_COLOR_BORDER]; 14450 edit->text_normal = table[NK_COLOR_TEXT]; 14451 edit->text_hover = table[NK_COLOR_TEXT]; 14452 edit->text_active = table[NK_COLOR_TEXT]; 14453 edit->selected_normal = table[NK_COLOR_TEXT]; 14454 edit->selected_hover = table[NK_COLOR_TEXT]; 14455 edit->selected_text_normal = table[NK_COLOR_EDIT]; 14456 edit->selected_text_hover = table[NK_COLOR_EDIT]; 14457 edit->scrollbar_size = nk_vec2(10,10); 14458 edit->scrollbar = style->scrollv; 14459 edit->padding = nk_vec2(4,4); 14460 edit->row_padding = 2; 14461 edit->cursor_size = 4; 14462 edit->border = 1; 14463 edit->rounding = 0; 14464 14465 /* property */ 14466 property = &style->property; 14467 nk_zero_struct(*property); 14468 property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14469 property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14470 property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14471 property->border_color = table[NK_COLOR_BORDER]; 14472 property->label_normal = table[NK_COLOR_TEXT]; 14473 property->label_hover = table[NK_COLOR_TEXT]; 14474 property->label_active = table[NK_COLOR_TEXT]; 14475 property->sym_left = NK_SYMBOL_TRIANGLE_LEFT; 14476 property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT; 14477 property->userdata = nk_handle_ptr(0); 14478 property->padding = nk_vec2(4,4); 14479 property->border = 1; 14480 property->rounding = 10; 14481 property->draw_begin = 0; 14482 property->draw_end = 0; 14483 14484 /* property buttons */ 14485 button = &style->property.dec_button; 14486 nk_zero_struct(*button); 14487 button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14488 button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14489 button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14490 button->border_color = nk_rgba(0,0,0,0); 14491 button->text_background = table[NK_COLOR_PROPERTY]; 14492 button->text_normal = table[NK_COLOR_TEXT]; 14493 button->text_hover = table[NK_COLOR_TEXT]; 14494 button->text_active = table[NK_COLOR_TEXT]; 14495 button->padding = nk_vec2(0.0f,0.0f); 14496 button->touch_padding = nk_vec2(0.0f,0.0f); 14497 button->userdata = nk_handle_ptr(0); 14498 button->text_alignment = NK_TEXT_CENTERED; 14499 button->border = 0.0f; 14500 button->rounding = 0.0f; 14501 button->draw_begin = 0; 14502 button->draw_end = 0; 14503 style->property.inc_button = style->property.dec_button; 14504 14505 /* property edit */ 14506 edit = &style->property.edit; 14507 nk_zero_struct(*edit); 14508 edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14509 edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14510 edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14511 edit->border_color = nk_rgba(0,0,0,0); 14512 edit->cursor_normal = table[NK_COLOR_TEXT]; 14513 edit->cursor_hover = table[NK_COLOR_TEXT]; 14514 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 14515 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 14516 edit->text_normal = table[NK_COLOR_TEXT]; 14517 edit->text_hover = table[NK_COLOR_TEXT]; 14518 edit->text_active = table[NK_COLOR_TEXT]; 14519 edit->selected_normal = table[NK_COLOR_TEXT]; 14520 edit->selected_hover = table[NK_COLOR_TEXT]; 14521 edit->selected_text_normal = table[NK_COLOR_EDIT]; 14522 edit->selected_text_hover = table[NK_COLOR_EDIT]; 14523 edit->padding = nk_vec2(0,0); 14524 edit->cursor_size = 8; 14525 edit->border = 0; 14526 edit->rounding = 0; 14527 14528 /* chart */ 14529 chart = &style->chart; 14530 nk_zero_struct(*chart); 14531 chart->background = nk_style_item_color(table[NK_COLOR_CHART]); 14532 chart->border_color = table[NK_COLOR_BORDER]; 14533 chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT]; 14534 chart->color = table[NK_COLOR_CHART_COLOR]; 14535 chart->padding = nk_vec2(4,4); 14536 chart->border = 0; 14537 chart->rounding = 0; 14538 14539 /* combo */ 14540 combo = &style->combo; 14541 combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 14542 combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 14543 combo->active = nk_style_item_color(table[NK_COLOR_COMBO]); 14544 combo->border_color = table[NK_COLOR_BORDER]; 14545 combo->label_normal = table[NK_COLOR_TEXT]; 14546 combo->label_hover = table[NK_COLOR_TEXT]; 14547 combo->label_active = table[NK_COLOR_TEXT]; 14548 combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN; 14549 combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN; 14550 combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN; 14551 combo->content_padding = nk_vec2(4,4); 14552 combo->button_padding = nk_vec2(0,4); 14553 combo->spacing = nk_vec2(4,0); 14554 combo->border = 1; 14555 combo->rounding = 0; 14556 14557 /* combo button */ 14558 button = &style->combo.button; 14559 nk_zero_struct(*button); 14560 button->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 14561 button->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 14562 button->active = nk_style_item_color(table[NK_COLOR_COMBO]); 14563 button->border_color = nk_rgba(0,0,0,0); 14564 button->text_background = table[NK_COLOR_COMBO]; 14565 button->text_normal = table[NK_COLOR_TEXT]; 14566 button->text_hover = table[NK_COLOR_TEXT]; 14567 button->text_active = table[NK_COLOR_TEXT]; 14568 button->padding = nk_vec2(2.0f,2.0f); 14569 button->touch_padding = nk_vec2(0.0f,0.0f); 14570 button->userdata = nk_handle_ptr(0); 14571 button->text_alignment = NK_TEXT_CENTERED; 14572 button->border = 0.0f; 14573 button->rounding = 0.0f; 14574 button->draw_begin = 0; 14575 button->draw_end = 0; 14576 14577 /* tab */ 14578 tab = &style->tab; 14579 tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14580 tab->border_color = table[NK_COLOR_BORDER]; 14581 tab->text = table[NK_COLOR_TEXT]; 14582 tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT; 14583 tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN; 14584 tab->padding = nk_vec2(4,4); 14585 tab->spacing = nk_vec2(4,4); 14586 tab->indent = 10.0f; 14587 tab->border = 1; 14588 tab->rounding = 0; 14589 14590 /* tab button */ 14591 button = &style->tab.tab_minimize_button; 14592 nk_zero_struct(*button); 14593 button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14594 button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14595 button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14596 button->border_color = nk_rgba(0,0,0,0); 14597 button->text_background = table[NK_COLOR_TAB_HEADER]; 14598 button->text_normal = table[NK_COLOR_TEXT]; 14599 button->text_hover = table[NK_COLOR_TEXT]; 14600 button->text_active = table[NK_COLOR_TEXT]; 14601 button->padding = nk_vec2(2.0f,2.0f); 14602 button->touch_padding = nk_vec2(0.0f,0.0f); 14603 button->userdata = nk_handle_ptr(0); 14604 button->text_alignment = NK_TEXT_CENTERED; 14605 button->border = 0.0f; 14606 button->rounding = 0.0f; 14607 button->draw_begin = 0; 14608 button->draw_end = 0; 14609 style->tab.tab_maximize_button =*button; 14610 14611 /* node button */ 14612 button = &style->tab.node_minimize_button; 14613 nk_zero_struct(*button); 14614 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14615 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 14616 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 14617 button->border_color = nk_rgba(0,0,0,0); 14618 button->text_background = table[NK_COLOR_TAB_HEADER]; 14619 button->text_normal = table[NK_COLOR_TEXT]; 14620 button->text_hover = table[NK_COLOR_TEXT]; 14621 button->text_active = table[NK_COLOR_TEXT]; 14622 button->padding = nk_vec2(2.0f,2.0f); 14623 button->touch_padding = nk_vec2(0.0f,0.0f); 14624 button->userdata = nk_handle_ptr(0); 14625 button->text_alignment = NK_TEXT_CENTERED; 14626 button->border = 0.0f; 14627 button->rounding = 0.0f; 14628 button->draw_begin = 0; 14629 button->draw_end = 0; 14630 style->tab.node_maximize_button =*button; 14631 14632 /* window header */ 14633 win = &style->window; 14634 win->header.align = NK_HEADER_RIGHT; 14635 win->header.close_symbol = NK_SYMBOL_X; 14636 win->header.minimize_symbol = NK_SYMBOL_MINUS; 14637 win->header.maximize_symbol = NK_SYMBOL_PLUS; 14638 win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14639 win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14640 win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]); 14641 win->header.label_normal = table[NK_COLOR_TEXT]; 14642 win->header.label_hover = table[NK_COLOR_TEXT]; 14643 win->header.label_active = table[NK_COLOR_TEXT]; 14644 win->header.label_padding = nk_vec2(4,4); 14645 win->header.padding = nk_vec2(4,4); 14646 win->header.spacing = nk_vec2(0,0); 14647 14648 /* window header close button */ 14649 button = &style->window.header.close_button; 14650 nk_zero_struct(*button); 14651 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14652 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14653 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 14654 button->border_color = nk_rgba(0,0,0,0); 14655 button->text_background = table[NK_COLOR_HEADER]; 14656 button->text_normal = table[NK_COLOR_TEXT]; 14657 button->text_hover = table[NK_COLOR_TEXT]; 14658 button->text_active = table[NK_COLOR_TEXT]; 14659 button->padding = nk_vec2(0.0f,0.0f); 14660 button->touch_padding = nk_vec2(0.0f,0.0f); 14661 button->userdata = nk_handle_ptr(0); 14662 button->text_alignment = NK_TEXT_CENTERED; 14663 button->border = 0.0f; 14664 button->rounding = 0.0f; 14665 button->draw_begin = 0; 14666 button->draw_end = 0; 14667 14668 /* window header minimize button */ 14669 button = &style->window.header.minimize_button; 14670 nk_zero_struct(*button); 14671 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14672 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14673 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 14674 button->border_color = nk_rgba(0,0,0,0); 14675 button->text_background = table[NK_COLOR_HEADER]; 14676 button->text_normal = table[NK_COLOR_TEXT]; 14677 button->text_hover = table[NK_COLOR_TEXT]; 14678 button->text_active = table[NK_COLOR_TEXT]; 14679 button->padding = nk_vec2(0.0f,0.0f); 14680 button->touch_padding = nk_vec2(0.0f,0.0f); 14681 button->userdata = nk_handle_ptr(0); 14682 button->text_alignment = NK_TEXT_CENTERED; 14683 button->border = 0.0f; 14684 button->rounding = 0.0f; 14685 button->draw_begin = 0; 14686 button->draw_end = 0; 14687 14688 /* window */ 14689 win->background = table[NK_COLOR_WINDOW]; 14690 win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]); 14691 win->border_color = table[NK_COLOR_BORDER]; 14692 win->popup_border_color = table[NK_COLOR_BORDER]; 14693 win->combo_border_color = table[NK_COLOR_BORDER]; 14694 win->contextual_border_color = table[NK_COLOR_BORDER]; 14695 win->menu_border_color = table[NK_COLOR_BORDER]; 14696 win->group_border_color = table[NK_COLOR_BORDER]; 14697 win->tooltip_border_color = table[NK_COLOR_BORDER]; 14698 win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]); 14699 14700 win->rounding = 0.0f; 14701 win->spacing = nk_vec2(4,4); 14702 win->scrollbar_size = nk_vec2(10,10); 14703 win->min_size = nk_vec2(64,64); 14704 14705 win->combo_border = 1.0f; 14706 win->contextual_border = 1.0f; 14707 win->menu_border = 1.0f; 14708 win->group_border = 1.0f; 14709 win->tooltip_border = 1.0f; 14710 win->popup_border = 1.0f; 14711 win->border = 2.0f; 14712 win->min_row_height_padding = 8; 14713 14714 win->padding = nk_vec2(4,4); 14715 win->group_padding = nk_vec2(4,4); 14716 win->popup_padding = nk_vec2(4,4); 14717 win->combo_padding = nk_vec2(4,4); 14718 win->contextual_padding = nk_vec2(4,4); 14719 win->menu_padding = nk_vec2(4,4); 14720 win->tooltip_padding = nk_vec2(4,4); 14721 } 14722 NK_API void 14723 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font) 14724 { 14725 struct nk_style *style; 14726 NK_ASSERT(ctx); 14727 14728 if (!ctx) return; 14729 style = &ctx->style; 14730 style->font = font; 14731 ctx->stacks.fonts.head = 0; 14732 if (ctx->current) 14733 nk_layout_reset_min_row_height(ctx); 14734 } 14735 NK_API int 14736 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font) 14737 { 14738 struct nk_config_stack_user_font *font_stack; 14739 struct nk_config_stack_user_font_element *element; 14740 14741 NK_ASSERT(ctx); 14742 if (!ctx) return 0; 14743 14744 font_stack = &ctx->stacks.fonts; 14745 NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements)); 14746 if (font_stack->head >= (int)NK_LEN(font_stack->elements)) 14747 return 0; 14748 14749 element = &font_stack->elements[font_stack->head++]; 14750 element->address = &ctx->style.font; 14751 element->old_value = ctx->style.font; 14752 ctx->style.font = font; 14753 return 1; 14754 } 14755 NK_API int 14756 nk_style_pop_font(struct nk_context *ctx) 14757 { 14758 struct nk_config_stack_user_font *font_stack; 14759 struct nk_config_stack_user_font_element *element; 14760 14761 NK_ASSERT(ctx); 14762 if (!ctx) return 0; 14763 14764 font_stack = &ctx->stacks.fonts; 14765 NK_ASSERT(font_stack->head > 0); 14766 if (font_stack->head < 1) 14767 return 0; 14768 14769 element = &font_stack->elements[--font_stack->head]; 14770 *element->address = element->old_value; 14771 return 1; 14772 } 14773 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \ 14774 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\ 14775 {\ 14776 struct nk_config_stack_##type * type_stack;\ 14777 struct nk_config_stack_##type##_element *element;\ 14778 NK_ASSERT(ctx);\ 14779 if (!ctx) return 0;\ 14780 type_stack = &ctx->stacks.stack;\ 14781 NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\ 14782 if (type_stack->head >= (int)NK_LEN(type_stack->elements))\ 14783 return 0;\ 14784 element = &type_stack->elements[type_stack->head++];\ 14785 element->address = address;\ 14786 element->old_value = *address;\ 14787 *address = value;\ 14788 return 1;\ 14789 } 14790 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \ 14791 nk_style_pop_##type(struct nk_context *ctx)\ 14792 {\ 14793 struct nk_config_stack_##type *type_stack;\ 14794 struct nk_config_stack_##type##_element *element;\ 14795 NK_ASSERT(ctx);\ 14796 if (!ctx) return 0;\ 14797 type_stack = &ctx->stacks.stack;\ 14798 NK_ASSERT(type_stack->head > 0);\ 14799 if (type_stack->head < 1)\ 14800 return 0;\ 14801 element = &type_stack->elements[--type_stack->head];\ 14802 *element->address = element->old_value;\ 14803 return 1;\ 14804 } 14805 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items) 14806 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats) 14807 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors) 14808 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags) 14809 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors) 14810 14811 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items) 14812 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats) 14813 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors) 14814 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags) 14815 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors) 14816 14817 NK_API int 14818 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c) 14819 { 14820 struct nk_style *style; 14821 NK_ASSERT(ctx); 14822 if (!ctx) return 0; 14823 style = &ctx->style; 14824 if (style->cursors[c]) { 14825 style->cursor_active = style->cursors[c]; 14826 return 1; 14827 } 14828 return 0; 14829 } 14830 NK_API void 14831 nk_style_show_cursor(struct nk_context *ctx) 14832 { 14833 ctx->style.cursor_visible = nk_true; 14834 } 14835 NK_API void 14836 nk_style_hide_cursor(struct nk_context *ctx) 14837 { 14838 ctx->style.cursor_visible = nk_false; 14839 } 14840 NK_API void 14841 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor, 14842 const struct nk_cursor *c) 14843 { 14844 struct nk_style *style; 14845 NK_ASSERT(ctx); 14846 if (!ctx) return; 14847 style = &ctx->style; 14848 style->cursors[cursor] = c; 14849 } 14850 NK_API void 14851 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors) 14852 { 14853 int i = 0; 14854 struct nk_style *style; 14855 NK_ASSERT(ctx); 14856 if (!ctx) return; 14857 style = &ctx->style; 14858 for (i = 0; i < NK_CURSOR_COUNT; ++i) 14859 style->cursors[i] = &cursors[i]; 14860 style->cursor_visible = nk_true; 14861 } 14862 14863 14864 14865 14866 14867 /* ============================================================== 14868 * 14869 * CONTEXT 14870 * 14871 * ===============================================================*/ 14872 NK_INTERN void 14873 nk_setup(struct nk_context *ctx, const struct nk_user_font *font) 14874 { 14875 NK_ASSERT(ctx); 14876 if (!ctx) return; 14877 nk_zero_struct(*ctx); 14878 nk_style_default(ctx); 14879 ctx->seq = 1; 14880 if (font) ctx->style.font = font; 14881 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 14882 nk_draw_list_init(&ctx->draw_list); 14883 #endif 14884 } 14885 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 14886 NK_API int 14887 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font) 14888 { 14889 struct nk_allocator alloc; 14890 alloc.userdata.ptr = 0; 14891 alloc.alloc = nk_malloc; 14892 alloc.free = nk_mfree; 14893 return nk_init(ctx, &alloc, font); 14894 } 14895 #endif 14896 NK_API int 14897 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, 14898 const struct nk_user_font *font) 14899 { 14900 NK_ASSERT(memory); 14901 if (!memory) return 0; 14902 nk_setup(ctx, font); 14903 nk_buffer_init_fixed(&ctx->memory, memory, size); 14904 ctx->use_pool = nk_false; 14905 return 1; 14906 } 14907 NK_API int 14908 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, 14909 struct nk_buffer *pool, const struct nk_user_font *font) 14910 { 14911 NK_ASSERT(cmds); 14912 NK_ASSERT(pool); 14913 if (!cmds || !pool) return 0; 14914 14915 nk_setup(ctx, font); 14916 ctx->memory = *cmds; 14917 if (pool->type == NK_BUFFER_FIXED) { 14918 /* take memory from buffer and alloc fixed pool */ 14919 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size); 14920 } else { 14921 /* create dynamic pool from buffer allocator */ 14922 struct nk_allocator *alloc = &pool->pool; 14923 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 14924 } 14925 ctx->use_pool = nk_true; 14926 return 1; 14927 } 14928 NK_API int 14929 nk_init(struct nk_context *ctx, struct nk_allocator *alloc, 14930 const struct nk_user_font *font) 14931 { 14932 NK_ASSERT(alloc); 14933 if (!alloc) return 0; 14934 nk_setup(ctx, font); 14935 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE); 14936 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 14937 ctx->use_pool = nk_true; 14938 return 1; 14939 } 14940 #ifdef NK_INCLUDE_COMMAND_USERDATA 14941 NK_API void 14942 nk_set_user_data(struct nk_context *ctx, nk_handle handle) 14943 { 14944 if (!ctx) return; 14945 ctx->userdata = handle; 14946 if (ctx->current) 14947 ctx->current->buffer.userdata = handle; 14948 } 14949 #endif 14950 NK_API void 14951 nk_free(struct nk_context *ctx) 14952 { 14953 NK_ASSERT(ctx); 14954 if (!ctx) return; 14955 nk_buffer_free(&ctx->memory); 14956 if (ctx->use_pool) 14957 nk_pool_free(&ctx->pool); 14958 14959 nk_zero(&ctx->input, sizeof(ctx->input)); 14960 nk_zero(&ctx->style, sizeof(ctx->style)); 14961 nk_zero(&ctx->memory, sizeof(ctx->memory)); 14962 14963 ctx->seq = 0; 14964 ctx->build = 0; 14965 ctx->begin = 0; 14966 ctx->end = 0; 14967 ctx->active = 0; 14968 ctx->current = 0; 14969 ctx->freelist = 0; 14970 ctx->count = 0; 14971 } 14972 NK_API void 14973 nk_clear(struct nk_context *ctx) 14974 { 14975 struct nk_window *iter; 14976 struct nk_window *next; 14977 NK_ASSERT(ctx); 14978 14979 if (!ctx) return; 14980 if (ctx->use_pool) 14981 nk_buffer_clear(&ctx->memory); 14982 else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); 14983 14984 ctx->build = 0; 14985 ctx->memory.calls = 0; 14986 ctx->last_widget_state = 0; 14987 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 14988 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); 14989 14990 /* garbage collector */ 14991 iter = ctx->begin; 14992 while (iter) { 14993 /* make sure valid minimized windows do not get removed */ 14994 if ((iter->flags & NK_WINDOW_MINIMIZED) && 14995 !(iter->flags & NK_WINDOW_CLOSED) && 14996 iter->seq == ctx->seq) { 14997 iter = iter->next; 14998 continue; 14999 } 15000 /* remove hotness from hidden or closed windows*/ 15001 if (((iter->flags & NK_WINDOW_HIDDEN) || 15002 (iter->flags & NK_WINDOW_CLOSED)) && 15003 iter == ctx->active) { 15004 ctx->active = iter->prev; 15005 ctx->end = iter->prev; 15006 if (!ctx->end) 15007 ctx->begin = 0; 15008 if (ctx->active) 15009 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM; 15010 } 15011 /* free unused popup windows */ 15012 if (iter->popup.win && iter->popup.win->seq != ctx->seq) { 15013 nk_free_window(ctx, iter->popup.win); 15014 iter->popup.win = 0; 15015 } 15016 /* remove unused window state tables */ 15017 {struct nk_table *n, *it = iter->tables; 15018 while (it) { 15019 n = it->next; 15020 if (it->seq != ctx->seq) { 15021 nk_remove_table(iter, it); 15022 nk_zero(it, sizeof(union nk_page_data)); 15023 nk_free_table(ctx, it); 15024 if (it == iter->tables) 15025 iter->tables = n; 15026 } it = n; 15027 }} 15028 /* window itself is not used anymore so free */ 15029 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { 15030 next = iter->next; 15031 nk_remove_window(ctx, iter); 15032 nk_free_window(ctx, iter); 15033 iter = next; 15034 } else iter = iter->next; 15035 } 15036 ctx->seq++; 15037 } 15038 NK_LIB void 15039 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 15040 { 15041 NK_ASSERT(ctx); 15042 NK_ASSERT(buffer); 15043 if (!ctx || !buffer) return; 15044 buffer->begin = ctx->memory.allocated; 15045 buffer->end = buffer->begin; 15046 buffer->last = buffer->begin; 15047 buffer->clip = nk_null_rect; 15048 } 15049 NK_LIB void 15050 nk_start(struct nk_context *ctx, struct nk_window *win) 15051 { 15052 NK_ASSERT(ctx); 15053 NK_ASSERT(win); 15054 nk_start_buffer(ctx, &win->buffer); 15055 } 15056 NK_LIB void 15057 nk_start_popup(struct nk_context *ctx, struct nk_window *win) 15058 { 15059 struct nk_popup_buffer *buf; 15060 NK_ASSERT(ctx); 15061 NK_ASSERT(win); 15062 if (!ctx || !win) return; 15063 15064 /* save buffer fill state for popup */ 15065 buf = &win->popup.buf; 15066 buf->begin = win->buffer.end; 15067 buf->end = win->buffer.end; 15068 buf->parent = win->buffer.last; 15069 buf->last = buf->begin; 15070 buf->active = nk_true; 15071 } 15072 NK_LIB void 15073 nk_finish_popup(struct nk_context *ctx, struct nk_window *win) 15074 { 15075 struct nk_popup_buffer *buf; 15076 NK_ASSERT(ctx); 15077 NK_ASSERT(win); 15078 if (!ctx || !win) return; 15079 15080 buf = &win->popup.buf; 15081 buf->last = win->buffer.last; 15082 buf->end = win->buffer.end; 15083 } 15084 NK_LIB void 15085 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 15086 { 15087 NK_ASSERT(ctx); 15088 NK_ASSERT(buffer); 15089 if (!ctx || !buffer) return; 15090 buffer->end = ctx->memory.allocated; 15091 } 15092 NK_LIB void 15093 nk_finish(struct nk_context *ctx, struct nk_window *win) 15094 { 15095 struct nk_popup_buffer *buf; 15096 struct nk_command *parent_last; 15097 void *memory; 15098 15099 NK_ASSERT(ctx); 15100 NK_ASSERT(win); 15101 if (!ctx || !win) return; 15102 nk_finish_buffer(ctx, &win->buffer); 15103 if (!win->popup.buf.active) return; 15104 15105 buf = &win->popup.buf; 15106 memory = ctx->memory.memory.ptr; 15107 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent); 15108 parent_last->next = buf->end; 15109 } 15110 NK_LIB void 15111 nk_build(struct nk_context *ctx) 15112 { 15113 struct nk_window *it = 0; 15114 struct nk_command *cmd = 0; 15115 nk_byte *buffer = 0; 15116 15117 /* draw cursor overlay */ 15118 if (!ctx->style.cursor_active) 15119 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 15120 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) { 15121 struct nk_rect mouse_bounds; 15122 const struct nk_cursor *cursor = ctx->style.cursor_active; 15123 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF); 15124 nk_start_buffer(ctx, &ctx->overlay); 15125 15126 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x; 15127 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y; 15128 mouse_bounds.w = cursor->size.x; 15129 mouse_bounds.h = cursor->size.y; 15130 15131 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white); 15132 nk_finish_buffer(ctx, &ctx->overlay); 15133 } 15134 /* build one big draw command list out of all window buffers */ 15135 it = ctx->begin; 15136 buffer = (nk_byte*)ctx->memory.memory.ptr; 15137 while (it != 0) { 15138 struct nk_window *next = it->next; 15139 if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)|| 15140 it->seq != ctx->seq) 15141 goto cont; 15142 15143 cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last); 15144 while (next && ((next->buffer.last == next->buffer.begin) || 15145 (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq)) 15146 next = next->next; /* skip empty command buffers */ 15147 15148 if (next) cmd->next = next->buffer.begin; 15149 cont: it = next; 15150 } 15151 /* append all popup draw commands into lists */ 15152 it = ctx->begin; 15153 while (it != 0) { 15154 struct nk_window *next = it->next; 15155 struct nk_popup_buffer *buf; 15156 if (!it->popup.buf.active) 15157 goto skip; 15158 15159 buf = &it->popup.buf; 15160 cmd->next = buf->begin; 15161 cmd = nk_ptr_add(struct nk_command, buffer, buf->last); 15162 buf->active = nk_false; 15163 skip: it = next; 15164 } 15165 if (cmd) { 15166 /* append overlay commands */ 15167 if (ctx->overlay.end != ctx->overlay.begin) 15168 cmd->next = ctx->overlay.begin; 15169 else cmd->next = ctx->memory.allocated; 15170 } 15171 } 15172 NK_API const struct nk_command* 15173 nk__begin(struct nk_context *ctx) 15174 { 15175 struct nk_window *iter; 15176 nk_byte *buffer; 15177 NK_ASSERT(ctx); 15178 if (!ctx) return 0; 15179 if (!ctx->count) return 0; 15180 15181 buffer = (nk_byte*)ctx->memory.memory.ptr; 15182 if (!ctx->build) { 15183 nk_build(ctx); 15184 ctx->build = nk_true; 15185 } 15186 iter = ctx->begin; 15187 while (iter && ((iter->buffer.begin == iter->buffer.end) || 15188 (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq)) 15189 iter = iter->next; 15190 if (!iter) return 0; 15191 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin); 15192 } 15193 15194 NK_API const struct nk_command* 15195 nk__next(struct nk_context *ctx, const struct nk_command *cmd) 15196 { 15197 nk_byte *buffer; 15198 const struct nk_command *next; 15199 NK_ASSERT(ctx); 15200 if (!ctx || !cmd || !ctx->count) return 0; 15201 if (cmd->next >= ctx->memory.allocated) return 0; 15202 buffer = (nk_byte*)ctx->memory.memory.ptr; 15203 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next); 15204 return next; 15205 } 15206 15207 15208 15209 15210 15211 15212 /* =============================================================== 15213 * 15214 * POOL 15215 * 15216 * ===============================================================*/ 15217 NK_LIB void 15218 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, 15219 unsigned int capacity) 15220 { 15221 nk_zero(pool, sizeof(*pool)); 15222 pool->alloc = *alloc; 15223 pool->capacity = capacity; 15224 pool->type = NK_BUFFER_DYNAMIC; 15225 pool->pages = 0; 15226 } 15227 NK_LIB void 15228 nk_pool_free(struct nk_pool *pool) 15229 { 15230 struct nk_page *iter = pool->pages; 15231 if (!pool) return; 15232 if (pool->type == NK_BUFFER_FIXED) return; 15233 while (iter) { 15234 struct nk_page *next = iter->next; 15235 pool->alloc.free(pool->alloc.userdata, iter); 15236 iter = next; 15237 } 15238 } 15239 NK_LIB void 15240 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size) 15241 { 15242 nk_zero(pool, sizeof(*pool)); 15243 NK_ASSERT(size >= sizeof(struct nk_page)); 15244 if (size < sizeof(struct nk_page)) return; 15245 pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element); 15246 pool->pages = (struct nk_page*)memory; 15247 pool->type = NK_BUFFER_FIXED; 15248 pool->size = size; 15249 } 15250 NK_LIB struct nk_page_element* 15251 nk_pool_alloc(struct nk_pool *pool) 15252 { 15253 if (!pool->pages || pool->pages->size >= pool->capacity) { 15254 /* allocate new page */ 15255 struct nk_page *page; 15256 if (pool->type == NK_BUFFER_FIXED) { 15257 NK_ASSERT(pool->pages); 15258 if (!pool->pages) return 0; 15259 NK_ASSERT(pool->pages->size < pool->capacity); 15260 return 0; 15261 } else { 15262 nk_size size = sizeof(struct nk_page); 15263 size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data); 15264 page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size); 15265 page->next = pool->pages; 15266 pool->pages = page; 15267 page->size = 0; 15268 } 15269 } return &pool->pages->win[pool->pages->size++]; 15270 } 15271 15272 15273 15274 15275 15276 /* =============================================================== 15277 * 15278 * PAGE ELEMENT 15279 * 15280 * ===============================================================*/ 15281 NK_LIB struct nk_page_element* 15282 nk_create_page_element(struct nk_context *ctx) 15283 { 15284 struct nk_page_element *elem; 15285 if (ctx->freelist) { 15286 /* unlink page element from free list */ 15287 elem = ctx->freelist; 15288 ctx->freelist = elem->next; 15289 } else if (ctx->use_pool) { 15290 /* allocate page element from memory pool */ 15291 elem = nk_pool_alloc(&ctx->pool); 15292 NK_ASSERT(elem); 15293 if (!elem) return 0; 15294 } else { 15295 /* allocate new page element from back of fixed size memory buffer */ 15296 NK_STORAGE const nk_size size = sizeof(struct nk_page_element); 15297 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element); 15298 elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align); 15299 NK_ASSERT(elem); 15300 if (!elem) return 0; 15301 } 15302 nk_zero_struct(*elem); 15303 elem->next = 0; 15304 elem->prev = 0; 15305 return elem; 15306 } 15307 NK_LIB void 15308 nk_link_page_element_into_freelist(struct nk_context *ctx, 15309 struct nk_page_element *elem) 15310 { 15311 /* link table into freelist */ 15312 if (!ctx->freelist) { 15313 ctx->freelist = elem; 15314 } else { 15315 elem->next = ctx->freelist; 15316 ctx->freelist = elem; 15317 } 15318 } 15319 NK_LIB void 15320 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem) 15321 { 15322 /* we have a pool so just add to free list */ 15323 if (ctx->use_pool) { 15324 nk_link_page_element_into_freelist(ctx, elem); 15325 return; 15326 } 15327 /* if possible remove last element from back of fixed memory buffer */ 15328 {void *elem_end = (void*)(elem + 1); 15329 void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size; 15330 if (elem_end == buffer_end) 15331 ctx->memory.size -= sizeof(struct nk_page_element); 15332 else nk_link_page_element_into_freelist(ctx, elem);} 15333 } 15334 15335 15336 15337 15338 15339 /* =============================================================== 15340 * 15341 * TABLE 15342 * 15343 * ===============================================================*/ 15344 NK_LIB struct nk_table* 15345 nk_create_table(struct nk_context *ctx) 15346 { 15347 struct nk_page_element *elem; 15348 elem = nk_create_page_element(ctx); 15349 if (!elem) return 0; 15350 nk_zero_struct(*elem); 15351 return &elem->data.tbl; 15352 } 15353 NK_LIB void 15354 nk_free_table(struct nk_context *ctx, struct nk_table *tbl) 15355 { 15356 union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl); 15357 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 15358 nk_free_page_element(ctx, pe); 15359 } 15360 NK_LIB void 15361 nk_push_table(struct nk_window *win, struct nk_table *tbl) 15362 { 15363 if (!win->tables) { 15364 win->tables = tbl; 15365 tbl->next = 0; 15366 tbl->prev = 0; 15367 tbl->size = 0; 15368 win->table_count = 1; 15369 return; 15370 } 15371 win->tables->prev = tbl; 15372 tbl->next = win->tables; 15373 tbl->prev = 0; 15374 tbl->size = 0; 15375 win->tables = tbl; 15376 win->table_count++; 15377 } 15378 NK_LIB void 15379 nk_remove_table(struct nk_window *win, struct nk_table *tbl) 15380 { 15381 if (win->tables == tbl) 15382 win->tables = tbl->next; 15383 if (tbl->next) 15384 tbl->next->prev = tbl->prev; 15385 if (tbl->prev) 15386 tbl->prev->next = tbl->next; 15387 tbl->next = 0; 15388 tbl->prev = 0; 15389 } 15390 NK_LIB nk_uint* 15391 nk_add_value(struct nk_context *ctx, struct nk_window *win, 15392 nk_hash name, nk_uint value) 15393 { 15394 NK_ASSERT(ctx); 15395 NK_ASSERT(win); 15396 if (!win || !ctx) return 0; 15397 if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) { 15398 struct nk_table *tbl = nk_create_table(ctx); 15399 NK_ASSERT(tbl); 15400 if (!tbl) return 0; 15401 nk_push_table(win, tbl); 15402 } 15403 win->tables->seq = win->seq; 15404 win->tables->keys[win->tables->size] = name; 15405 win->tables->values[win->tables->size] = value; 15406 return &win->tables->values[win->tables->size++]; 15407 } 15408 NK_LIB nk_uint* 15409 nk_find_value(struct nk_window *win, nk_hash name) 15410 { 15411 struct nk_table *iter = win->tables; 15412 while (iter) { 15413 unsigned int i = 0; 15414 unsigned int size = iter->size; 15415 for (i = 0; i < size; ++i) { 15416 if (iter->keys[i] == name) { 15417 iter->seq = win->seq; 15418 return &iter->values[i]; 15419 } 15420 } size = NK_VALUE_PAGE_CAPACITY; 15421 iter = iter->next; 15422 } 15423 return 0; 15424 } 15425 15426 15427 15428 15429 15430 /* =============================================================== 15431 * 15432 * PANEL 15433 * 15434 * ===============================================================*/ 15435 NK_LIB void* 15436 nk_create_panel(struct nk_context *ctx) 15437 { 15438 struct nk_page_element *elem; 15439 elem = nk_create_page_element(ctx); 15440 if (!elem) return 0; 15441 nk_zero_struct(*elem); 15442 return &elem->data.pan; 15443 } 15444 NK_LIB void 15445 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan) 15446 { 15447 union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan); 15448 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 15449 nk_free_page_element(ctx, pe); 15450 } 15451 NK_LIB int 15452 nk_panel_has_header(nk_flags flags, const char *title) 15453 { 15454 int active = 0; 15455 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); 15456 active = active || (flags & NK_WINDOW_TITLE); 15457 active = active && !(flags & NK_WINDOW_HIDDEN) && title; 15458 return active; 15459 } 15460 NK_LIB struct nk_vec2 15461 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type) 15462 { 15463 switch (type) { 15464 default: 15465 case NK_PANEL_WINDOW: return style->window.padding; 15466 case NK_PANEL_GROUP: return style->window.group_padding; 15467 case NK_PANEL_POPUP: return style->window.popup_padding; 15468 case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding; 15469 case NK_PANEL_COMBO: return style->window.combo_padding; 15470 case NK_PANEL_MENU: return style->window.menu_padding; 15471 case NK_PANEL_TOOLTIP: return style->window.menu_padding;} 15472 } 15473 NK_LIB float 15474 nk_panel_get_border(const struct nk_style *style, nk_flags flags, 15475 enum nk_panel_type type) 15476 { 15477 if (flags & NK_WINDOW_BORDER) { 15478 switch (type) { 15479 default: 15480 case NK_PANEL_WINDOW: return style->window.border; 15481 case NK_PANEL_GROUP: return style->window.group_border; 15482 case NK_PANEL_POPUP: return style->window.popup_border; 15483 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border; 15484 case NK_PANEL_COMBO: return style->window.combo_border; 15485 case NK_PANEL_MENU: return style->window.menu_border; 15486 case NK_PANEL_TOOLTIP: return style->window.menu_border; 15487 }} else return 0; 15488 } 15489 NK_LIB struct nk_color 15490 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type) 15491 { 15492 switch (type) { 15493 default: 15494 case NK_PANEL_WINDOW: return style->window.border_color; 15495 case NK_PANEL_GROUP: return style->window.group_border_color; 15496 case NK_PANEL_POPUP: return style->window.popup_border_color; 15497 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color; 15498 case NK_PANEL_COMBO: return style->window.combo_border_color; 15499 case NK_PANEL_MENU: return style->window.menu_border_color; 15500 case NK_PANEL_TOOLTIP: return style->window.menu_border_color;} 15501 } 15502 NK_LIB int 15503 nk_panel_is_sub(enum nk_panel_type type) 15504 { 15505 return (type & NK_PANEL_SET_SUB)?1:0; 15506 } 15507 NK_LIB int 15508 nk_panel_is_nonblock(enum nk_panel_type type) 15509 { 15510 return (type & NK_PANEL_SET_NONBLOCK)?1:0; 15511 } 15512 NK_LIB int 15513 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type) 15514 { 15515 struct nk_input *in; 15516 struct nk_window *win; 15517 struct nk_panel *layout; 15518 struct nk_command_buffer *out; 15519 const struct nk_style *style; 15520 const struct nk_user_font *font; 15521 15522 struct nk_vec2 scrollbar_size; 15523 struct nk_vec2 panel_padding; 15524 15525 NK_ASSERT(ctx); 15526 NK_ASSERT(ctx->current); 15527 NK_ASSERT(ctx->current->layout); 15528 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 15529 nk_zero(ctx->current->layout, sizeof(*ctx->current->layout)); 15530 if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) { 15531 nk_zero(ctx->current->layout, sizeof(struct nk_panel)); 15532 ctx->current->layout->type = panel_type; 15533 return 0; 15534 } 15535 /* pull state into local stack */ 15536 style = &ctx->style; 15537 font = style->font; 15538 win = ctx->current; 15539 layout = win->layout; 15540 out = &win->buffer; 15541 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input; 15542 #ifdef NK_INCLUDE_COMMAND_USERDATA 15543 win->buffer.userdata = ctx->userdata; 15544 #endif 15545 /* pull style configuration into local stack */ 15546 scrollbar_size = style->window.scrollbar_size; 15547 panel_padding = nk_panel_get_padding(style, panel_type); 15548 15549 /* window movement */ 15550 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { 15551 int left_mouse_down; 15552 int left_mouse_clicked; 15553 int left_mouse_click_in_cursor; 15554 15555 /* calculate draggable window space */ 15556 struct nk_rect header; 15557 header.x = win->bounds.x; 15558 header.y = win->bounds.y; 15559 header.w = win->bounds.w; 15560 if (nk_panel_has_header(win->flags, title)) { 15561 header.h = font->height + 2.0f * style->window.header.padding.y; 15562 header.h += 2.0f * style->window.header.label_padding.y; 15563 } else header.h = panel_padding.y; 15564 15565 /* window movement by dragging */ 15566 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 15567 left_mouse_clicked = (int)in->mouse.buttons[NK_BUTTON_LEFT].clicked; 15568 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 15569 NK_BUTTON_LEFT, header, nk_true); 15570 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 15571 win->bounds.x = win->bounds.x + in->mouse.delta.x; 15572 win->bounds.y = win->bounds.y + in->mouse.delta.y; 15573 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; 15574 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; 15575 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE]; 15576 } 15577 } 15578 15579 /* setup panel */ 15580 layout->type = panel_type; 15581 layout->flags = win->flags; 15582 layout->bounds = win->bounds; 15583 layout->bounds.x += panel_padding.x; 15584 layout->bounds.w -= 2*panel_padding.x; 15585 if (win->flags & NK_WINDOW_BORDER) { 15586 layout->border = nk_panel_get_border(style, win->flags, panel_type); 15587 layout->bounds = nk_shrink_rect(layout->bounds, layout->border); 15588 } else layout->border = 0; 15589 layout->at_y = layout->bounds.y; 15590 layout->at_x = layout->bounds.x; 15591 layout->max_x = 0; 15592 layout->header_height = 0; 15593 layout->footer_height = 0; 15594 nk_layout_reset_min_row_height(ctx); 15595 layout->row.index = 0; 15596 layout->row.columns = 0; 15597 layout->row.ratio = 0; 15598 layout->row.item_width = 0; 15599 layout->row.tree_depth = 0; 15600 layout->row.height = panel_padding.y; 15601 layout->has_scrolling = nk_true; 15602 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) 15603 layout->bounds.w -= scrollbar_size.x; 15604 if (!nk_panel_is_nonblock(panel_type)) { 15605 layout->footer_height = 0; 15606 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE) 15607 layout->footer_height = scrollbar_size.y; 15608 layout->bounds.h -= layout->footer_height; 15609 } 15610 15611 /* panel header */ 15612 if (nk_panel_has_header(win->flags, title)) 15613 { 15614 struct nk_text text; 15615 struct nk_rect header; 15616 const struct nk_style_item *background = 0; 15617 15618 /* calculate header bounds */ 15619 header.x = win->bounds.x; 15620 header.y = win->bounds.y; 15621 header.w = win->bounds.w; 15622 header.h = font->height + 2.0f * style->window.header.padding.y; 15623 header.h += (2.0f * style->window.header.label_padding.y); 15624 15625 /* shrink panel by header */ 15626 layout->header_height = header.h; 15627 layout->bounds.y += header.h; 15628 layout->bounds.h -= header.h; 15629 layout->at_y += header.h; 15630 15631 /* select correct header background and text color */ 15632 if (ctx->active == win) { 15633 background = &style->window.header.active; 15634 text.text = style->window.header.label_active; 15635 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) { 15636 background = &style->window.header.hover; 15637 text.text = style->window.header.label_hover; 15638 } else { 15639 background = &style->window.header.normal; 15640 text.text = style->window.header.label_normal; 15641 } 15642 15643 /* draw header background */ 15644 header.h += 1.0f; 15645 if (background->type == NK_STYLE_ITEM_IMAGE) { 15646 text.background = nk_rgba(0,0,0,0); 15647 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 15648 } else { 15649 text.background = background->data.color; 15650 nk_fill_rect(out, header, 0, background->data.color); 15651 } 15652 15653 /* window close button */ 15654 {struct nk_rect button; 15655 button.y = header.y + style->window.header.padding.y; 15656 button.h = header.h - 2 * style->window.header.padding.y; 15657 button.w = button.h; 15658 if (win->flags & NK_WINDOW_CLOSABLE) { 15659 nk_flags ws = 0; 15660 if (style->window.header.align == NK_HEADER_RIGHT) { 15661 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); 15662 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; 15663 } else { 15664 button.x = header.x + style->window.header.padding.x; 15665 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 15666 } 15667 15668 if (nk_do_button_symbol(&ws, &win->buffer, button, 15669 style->window.header.close_symbol, NK_BUTTON_DEFAULT, 15670 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 15671 { 15672 layout->flags |= NK_WINDOW_HIDDEN; 15673 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED; 15674 } 15675 } 15676 15677 /* window minimize button */ 15678 if (win->flags & NK_WINDOW_MINIMIZABLE) { 15679 nk_flags ws = 0; 15680 if (style->window.header.align == NK_HEADER_RIGHT) { 15681 button.x = (header.w + header.x) - button.w; 15682 if (!(win->flags & NK_WINDOW_CLOSABLE)) { 15683 button.x -= style->window.header.padding.x; 15684 header.w -= style->window.header.padding.x; 15685 } 15686 header.w -= button.w + style->window.header.spacing.x; 15687 } else { 15688 button.x = header.x; 15689 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 15690 } 15691 if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)? 15692 style->window.header.maximize_symbol: style->window.header.minimize_symbol, 15693 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 15694 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ? 15695 layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED: 15696 layout->flags | NK_WINDOW_MINIMIZED; 15697 }} 15698 15699 {/* window header title */ 15700 int text_len = nk_strlen(title); 15701 struct nk_rect label = {0,0,0,0}; 15702 float t = font->width(font->userdata, font->height, title, text_len); 15703 text.padding = nk_vec2(0,0); 15704 15705 label.x = header.x + style->window.header.padding.x; 15706 label.x += style->window.header.label_padding.x; 15707 label.y = header.y + style->window.header.label_padding.y; 15708 label.h = font->height + 2 * style->window.header.label_padding.y; 15709 label.w = t + 2 * style->window.header.spacing.x; 15710 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x); 15711 nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);} 15712 } 15713 15714 /* draw window background */ 15715 if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) { 15716 struct nk_rect body; 15717 body.x = win->bounds.x; 15718 body.w = win->bounds.w; 15719 body.y = (win->bounds.y + layout->header_height); 15720 body.h = (win->bounds.h - layout->header_height); 15721 if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE) 15722 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white); 15723 else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color); 15724 } 15725 15726 /* set clipping rectangle */ 15727 {struct nk_rect clip; 15728 layout->clip = layout->bounds; 15729 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, 15730 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); 15731 nk_push_scissor(out, clip); 15732 layout->clip = clip;} 15733 return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED); 15734 } 15735 NK_LIB void 15736 nk_panel_end(struct nk_context *ctx) 15737 { 15738 struct nk_input *in; 15739 struct nk_window *window; 15740 struct nk_panel *layout; 15741 const struct nk_style *style; 15742 struct nk_command_buffer *out; 15743 15744 struct nk_vec2 scrollbar_size; 15745 struct nk_vec2 panel_padding; 15746 15747 NK_ASSERT(ctx); 15748 NK_ASSERT(ctx->current); 15749 NK_ASSERT(ctx->current->layout); 15750 if (!ctx || !ctx->current || !ctx->current->layout) 15751 return; 15752 15753 window = ctx->current; 15754 layout = window->layout; 15755 style = &ctx->style; 15756 out = &window->buffer; 15757 in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input; 15758 if (!nk_panel_is_sub(layout->type)) 15759 nk_push_scissor(out, nk_null_rect); 15760 15761 /* cache configuration data */ 15762 scrollbar_size = style->window.scrollbar_size; 15763 panel_padding = nk_panel_get_padding(style, layout->type); 15764 15765 /* update the current cursor Y-position to point over the last added widget */ 15766 layout->at_y += layout->row.height; 15767 15768 /* dynamic panels */ 15769 if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED)) 15770 { 15771 /* update panel height to fit dynamic growth */ 15772 struct nk_rect empty_space; 15773 if (layout->at_y < (layout->bounds.y + layout->bounds.h)) 15774 layout->bounds.h = layout->at_y - layout->bounds.y; 15775 15776 /* fill top empty space */ 15777 empty_space.x = window->bounds.x; 15778 empty_space.y = layout->bounds.y; 15779 empty_space.h = panel_padding.y; 15780 empty_space.w = window->bounds.w; 15781 nk_fill_rect(out, empty_space, 0, style->window.background); 15782 15783 /* fill left empty space */ 15784 empty_space.x = window->bounds.x; 15785 empty_space.y = layout->bounds.y; 15786 empty_space.w = panel_padding.x + layout->border; 15787 empty_space.h = layout->bounds.h; 15788 nk_fill_rect(out, empty_space, 0, style->window.background); 15789 15790 /* fill right empty space */ 15791 empty_space.x = layout->bounds.x + layout->bounds.w - layout->border; 15792 empty_space.y = layout->bounds.y; 15793 empty_space.w = panel_padding.x + layout->border; 15794 empty_space.h = layout->bounds.h; 15795 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) 15796 empty_space.w += scrollbar_size.x; 15797 nk_fill_rect(out, empty_space, 0, style->window.background); 15798 15799 /* fill bottom empty space */ 15800 if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) { 15801 empty_space.x = window->bounds.x; 15802 empty_space.y = layout->bounds.y + layout->bounds.h; 15803 empty_space.w = window->bounds.w; 15804 empty_space.h = scrollbar_size.y; 15805 nk_fill_rect(out, empty_space, 0, style->window.background); 15806 } 15807 } 15808 15809 /* scrollbars */ 15810 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) && 15811 !(layout->flags & NK_WINDOW_MINIMIZED) && 15812 window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT) 15813 { 15814 struct nk_rect scroll; 15815 int scroll_has_scrolling; 15816 float scroll_target; 15817 float scroll_offset; 15818 float scroll_step; 15819 float scroll_inc; 15820 15821 /* mouse wheel scrolling */ 15822 if (nk_panel_is_sub(layout->type)) 15823 { 15824 /* sub-window mouse wheel scrolling */ 15825 struct nk_window *root_window = window; 15826 struct nk_panel *root_panel = window->layout; 15827 while (root_panel->parent) 15828 root_panel = root_panel->parent; 15829 while (root_window->parent) 15830 root_window = root_window->parent; 15831 15832 /* only allow scrolling if parent window is active */ 15833 scroll_has_scrolling = 0; 15834 if ((root_window == ctx->active) && layout->has_scrolling) { 15835 /* and panel is being hovered and inside clip rect*/ 15836 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) && 15837 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h, 15838 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h)) 15839 { 15840 /* deactivate all parent scrolling */ 15841 root_panel = window->layout; 15842 while (root_panel->parent) { 15843 root_panel->has_scrolling = nk_false; 15844 root_panel = root_panel->parent; 15845 } 15846 root_panel->has_scrolling = nk_false; 15847 scroll_has_scrolling = nk_true; 15848 } 15849 } 15850 } else if (!nk_panel_is_sub(layout->type)) { 15851 /* window mouse wheel scrolling */ 15852 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling; 15853 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling) 15854 window->scrolled = nk_true; 15855 else window->scrolled = nk_false; 15856 } else scroll_has_scrolling = nk_false; 15857 15858 { 15859 /* vertical scrollbar */ 15860 nk_flags state = 0; 15861 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 15862 scroll.y = layout->bounds.y; 15863 scroll.w = scrollbar_size.x; 15864 scroll.h = layout->bounds.h; 15865 15866 scroll_offset = (float)*layout->offset_y; 15867 scroll_step = scroll.h * 0.10f; 15868 scroll_inc = scroll.h * 0.01f; 15869 scroll_target = (float)(int)(layout->at_y - scroll.y); 15870 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling, 15871 scroll_offset, scroll_target, scroll_step, scroll_inc, 15872 &ctx->style.scrollv, in, style->font); 15873 *layout->offset_y = (nk_uint)scroll_offset; 15874 if (in && scroll_has_scrolling) 15875 in->mouse.scroll_delta.y = 0; 15876 } 15877 { 15878 /* horizontal scrollbar */ 15879 nk_flags state = 0; 15880 scroll.x = layout->bounds.x; 15881 scroll.y = layout->bounds.y + layout->bounds.h; 15882 scroll.w = layout->bounds.w; 15883 scroll.h = scrollbar_size.y; 15884 15885 scroll_offset = (float)*layout->offset_x; 15886 scroll_target = (float)(int)(layout->max_x - scroll.x); 15887 scroll_step = layout->max_x * 0.05f; 15888 scroll_inc = layout->max_x * 0.005f; 15889 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling, 15890 scroll_offset, scroll_target, scroll_step, scroll_inc, 15891 &ctx->style.scrollh, in, style->font); 15892 *layout->offset_x = (nk_uint)scroll_offset; 15893 } 15894 } 15895 15896 /* hide scroll if no user input */ 15897 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) { 15898 int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0; 15899 int is_window_hovered = nk_window_is_hovered(ctx); 15900 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 15901 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active)) 15902 window->scrollbar_hiding_timer += ctx->delta_time_seconds; 15903 else window->scrollbar_hiding_timer = 0; 15904 } else window->scrollbar_hiding_timer = 0; 15905 15906 /* window border */ 15907 if (layout->flags & NK_WINDOW_BORDER) 15908 { 15909 struct nk_color border_color = nk_panel_get_border_color(style, layout->type); 15910 const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) 15911 ? (style->window.border + window->bounds.y + layout->header_height) 15912 : ((layout->flags & NK_WINDOW_DYNAMIC) 15913 ? (layout->bounds.y + layout->bounds.h + layout->footer_height) 15914 : (window->bounds.y + window->bounds.h)); 15915 struct nk_rect b = window->bounds; 15916 b.h = padding_y - window->bounds.y; 15917 nk_stroke_rect(out, b, 0, layout->border, border_color); 15918 } 15919 15920 /* scaler */ 15921 if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED)) 15922 { 15923 /* calculate scaler bounds */ 15924 struct nk_rect scaler; 15925 scaler.w = scrollbar_size.x; 15926 scaler.h = scrollbar_size.y; 15927 scaler.y = layout->bounds.y + layout->bounds.h; 15928 if (layout->flags & NK_WINDOW_SCALE_LEFT) 15929 scaler.x = layout->bounds.x - panel_padding.x * 0.5f; 15930 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 15931 if (layout->flags & NK_WINDOW_NO_SCROLLBAR) 15932 scaler.x -= scaler.w; 15933 15934 /* draw scaler */ 15935 {const struct nk_style_item *item = &style->window.scaler; 15936 if (item->type == NK_STYLE_ITEM_IMAGE) 15937 nk_draw_image(out, scaler, &item->data.image, nk_white); 15938 else { 15939 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 15940 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x, 15941 scaler.y + scaler.h, scaler.x + scaler.w, 15942 scaler.y + scaler.h, item->data.color); 15943 } else { 15944 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w, 15945 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color); 15946 } 15947 }} 15948 15949 /* do window scaling */ 15950 if (!(window->flags & NK_WINDOW_ROM)) { 15951 struct nk_vec2 window_size = style->window.min_size; 15952 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 15953 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in, 15954 NK_BUTTON_LEFT, scaler, nk_true); 15955 15956 if (left_mouse_down && left_mouse_click_in_scaler) { 15957 float delta_x = in->mouse.delta.x; 15958 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 15959 delta_x = -delta_x; 15960 window->bounds.x += in->mouse.delta.x; 15961 } 15962 /* dragging in x-direction */ 15963 if (window->bounds.w + delta_x >= window_size.x) { 15964 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) { 15965 window->bounds.w = window->bounds.w + delta_x; 15966 scaler.x += in->mouse.delta.x; 15967 } 15968 } 15969 /* dragging in y-direction (only possible if static window) */ 15970 if (!(layout->flags & NK_WINDOW_DYNAMIC)) { 15971 if (window_size.y < window->bounds.h + in->mouse.delta.y) { 15972 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) { 15973 window->bounds.h = window->bounds.h + in->mouse.delta.y; 15974 scaler.y += in->mouse.delta.y; 15975 } 15976 } 15977 } 15978 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT]; 15979 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f; 15980 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f; 15981 } 15982 } 15983 } 15984 if (!nk_panel_is_sub(layout->type)) { 15985 /* window is hidden so clear command buffer */ 15986 if (layout->flags & NK_WINDOW_HIDDEN) 15987 nk_command_buffer_reset(&window->buffer); 15988 /* window is visible and not tab */ 15989 else nk_finish(ctx, window); 15990 } 15991 15992 /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */ 15993 if (layout->flags & NK_WINDOW_REMOVE_ROM) { 15994 layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 15995 layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 15996 } 15997 window->flags = layout->flags; 15998 15999 /* property garbage collector */ 16000 if (window->property.active && window->property.old != window->property.seq && 16001 window->property.active == window->property.prev) { 16002 nk_zero(&window->property, sizeof(window->property)); 16003 } else { 16004 window->property.old = window->property.seq; 16005 window->property.prev = window->property.active; 16006 window->property.seq = 0; 16007 } 16008 /* edit garbage collector */ 16009 if (window->edit.active && window->edit.old != window->edit.seq && 16010 window->edit.active == window->edit.prev) { 16011 nk_zero(&window->edit, sizeof(window->edit)); 16012 } else { 16013 window->edit.old = window->edit.seq; 16014 window->edit.prev = window->edit.active; 16015 window->edit.seq = 0; 16016 } 16017 /* contextual garbage collector */ 16018 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) { 16019 window->popup.con_count = 0; 16020 window->popup.con_old = 0; 16021 window->popup.active_con = 0; 16022 } else { 16023 window->popup.con_old = window->popup.con_count; 16024 window->popup.con_count = 0; 16025 } 16026 window->popup.combo_count = 0; 16027 /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */ 16028 NK_ASSERT(!layout->row.tree_depth); 16029 } 16030 16031 16032 16033 16034 16035 /* =============================================================== 16036 * 16037 * WINDOW 16038 * 16039 * ===============================================================*/ 16040 NK_LIB void* 16041 nk_create_window(struct nk_context *ctx) 16042 { 16043 struct nk_page_element *elem; 16044 elem = nk_create_page_element(ctx); 16045 if (!elem) return 0; 16046 elem->data.win.seq = ctx->seq; 16047 return &elem->data.win; 16048 } 16049 NK_LIB void 16050 nk_free_window(struct nk_context *ctx, struct nk_window *win) 16051 { 16052 /* unlink windows from list */ 16053 struct nk_table *it = win->tables; 16054 if (win->popup.win) { 16055 nk_free_window(ctx, win->popup.win); 16056 win->popup.win = 0; 16057 } 16058 win->next = 0; 16059 win->prev = 0; 16060 16061 while (it) { 16062 /*free window state tables */ 16063 struct nk_table *n = it->next; 16064 nk_remove_table(win, it); 16065 nk_free_table(ctx, it); 16066 if (it == win->tables) 16067 win->tables = n; 16068 it = n; 16069 } 16070 16071 /* link windows into freelist */ 16072 {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win); 16073 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 16074 nk_free_page_element(ctx, pe);} 16075 } 16076 NK_LIB struct nk_window* 16077 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name) 16078 { 16079 struct nk_window *iter; 16080 iter = ctx->begin; 16081 while (iter) { 16082 NK_ASSERT(iter != iter->next); 16083 if (iter->name == hash) { 16084 int max_len = nk_strlen(iter->name_string); 16085 if (!nk_stricmpn(iter->name_string, name, max_len)) 16086 return iter; 16087 } 16088 iter = iter->next; 16089 } 16090 return 0; 16091 } 16092 NK_LIB void 16093 nk_insert_window(struct nk_context *ctx, struct nk_window *win, 16094 enum nk_window_insert_location loc) 16095 { 16096 const struct nk_window *iter; 16097 NK_ASSERT(ctx); 16098 NK_ASSERT(win); 16099 if (!win || !ctx) return; 16100 16101 iter = ctx->begin; 16102 while (iter) { 16103 NK_ASSERT(iter != iter->next); 16104 NK_ASSERT(iter != win); 16105 if (iter == win) return; 16106 iter = iter->next; 16107 } 16108 16109 if (!ctx->begin) { 16110 win->next = 0; 16111 win->prev = 0; 16112 ctx->begin = win; 16113 ctx->end = win; 16114 ctx->count = 1; 16115 return; 16116 } 16117 if (loc == NK_INSERT_BACK) { 16118 struct nk_window *end; 16119 end = ctx->end; 16120 end->flags |= NK_WINDOW_ROM; 16121 end->next = win; 16122 win->prev = ctx->end; 16123 win->next = 0; 16124 ctx->end = win; 16125 ctx->active = ctx->end; 16126 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 16127 } else { 16128 /*ctx->end->flags |= NK_WINDOW_ROM;*/ 16129 ctx->begin->prev = win; 16130 win->next = ctx->begin; 16131 win->prev = 0; 16132 ctx->begin = win; 16133 ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM; 16134 } 16135 ctx->count++; 16136 } 16137 NK_LIB void 16138 nk_remove_window(struct nk_context *ctx, struct nk_window *win) 16139 { 16140 if (win == ctx->begin || win == ctx->end) { 16141 if (win == ctx->begin) { 16142 ctx->begin = win->next; 16143 if (win->next) 16144 win->next->prev = 0; 16145 } 16146 if (win == ctx->end) { 16147 ctx->end = win->prev; 16148 if (win->prev) 16149 win->prev->next = 0; 16150 } 16151 } else { 16152 if (win->next) 16153 win->next->prev = win->prev; 16154 if (win->prev) 16155 win->prev->next = win->next; 16156 } 16157 if (win == ctx->active || !ctx->active) { 16158 ctx->active = ctx->end; 16159 if (ctx->end) 16160 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 16161 } 16162 win->next = 0; 16163 win->prev = 0; 16164 ctx->count--; 16165 } 16166 NK_API int 16167 nk_begin(struct nk_context *ctx, const char *title, 16168 struct nk_rect bounds, nk_flags flags) 16169 { 16170 return nk_begin_titled(ctx, title, title, bounds, flags); 16171 } 16172 NK_API int 16173 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, 16174 struct nk_rect bounds, nk_flags flags) 16175 { 16176 struct nk_window *win; 16177 struct nk_style *style; 16178 nk_hash title_hash; 16179 int title_len; 16180 int ret = 0; 16181 16182 NK_ASSERT(ctx); 16183 NK_ASSERT(name); 16184 NK_ASSERT(title); 16185 NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font"); 16186 NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call"); 16187 if (!ctx || ctx->current || !title || !name) 16188 return 0; 16189 16190 /* find or create window */ 16191 style = &ctx->style; 16192 title_len = (int)nk_strlen(name); 16193 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16194 win = nk_find_window(ctx, title_hash, name); 16195 if (!win) { 16196 /* create new window */ 16197 nk_size name_length = (nk_size)nk_strlen(name); 16198 win = (struct nk_window*)nk_create_window(ctx); 16199 NK_ASSERT(win); 16200 if (!win) return 0; 16201 16202 if (flags & NK_WINDOW_BACKGROUND) 16203 nk_insert_window(ctx, win, NK_INSERT_FRONT); 16204 else nk_insert_window(ctx, win, NK_INSERT_BACK); 16205 nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON); 16206 16207 win->flags = flags; 16208 win->bounds = bounds; 16209 win->name = title_hash; 16210 name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); 16211 NK_MEMCPY(win->name_string, name, name_length); 16212 win->name_string[name_length] = 0; 16213 win->popup.win = 0; 16214 if (!ctx->active) 16215 ctx->active = win; 16216 } else { 16217 /* update window */ 16218 win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1); 16219 win->flags |= flags; 16220 if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE))) 16221 win->bounds = bounds; 16222 /* If this assert triggers you either: 16223 * 16224 * I.) Have more than one window with the same name or 16225 * II.) You forgot to actually draw the window. 16226 * More specific you did not call `nk_clear` (nk_clear will be 16227 * automatically called for you if you are using one of the 16228 * provided demo backends). */ 16229 NK_ASSERT(win->seq != ctx->seq); 16230 win->seq = ctx->seq; 16231 if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) { 16232 ctx->active = win; 16233 ctx->end = win; 16234 } 16235 } 16236 if (win->flags & NK_WINDOW_HIDDEN) { 16237 ctx->current = win; 16238 win->layout = 0; 16239 return 0; 16240 } else nk_start(ctx, win); 16241 16242 /* window overlapping */ 16243 if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT)) 16244 { 16245 int inpanel, ishovered; 16246 struct nk_window *iter = win; 16247 float h = ctx->style.font->height + 2.0f * style->window.header.padding.y + 16248 (2.0f * style->window.header.label_padding.y); 16249 struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))? 16250 win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h); 16251 16252 /* activate window if hovered and no other window is overlapping this window */ 16253 inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true); 16254 inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked; 16255 ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds); 16256 if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) { 16257 iter = win->next; 16258 while (iter) { 16259 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 16260 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 16261 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16262 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 16263 (!(iter->flags & NK_WINDOW_HIDDEN))) 16264 break; 16265 16266 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 16267 NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16268 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 16269 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 16270 break; 16271 iter = iter->next; 16272 } 16273 } 16274 16275 /* activate window if clicked */ 16276 if (iter && inpanel && (win != ctx->end)) { 16277 iter = win->next; 16278 while (iter) { 16279 /* try to find a panel with higher priority in the same position */ 16280 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 16281 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 16282 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y, 16283 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 16284 !(iter->flags & NK_WINDOW_HIDDEN)) 16285 break; 16286 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 16287 NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16288 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 16289 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 16290 break; 16291 iter = iter->next; 16292 } 16293 } 16294 if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) { 16295 win->flags |= (nk_flags)NK_WINDOW_ROM; 16296 iter->flags &= ~(nk_flags)NK_WINDOW_ROM; 16297 ctx->active = iter; 16298 if (!(iter->flags & NK_WINDOW_BACKGROUND)) { 16299 /* current window is active in that position so transfer to top 16300 * at the highest priority in stack */ 16301 nk_remove_window(ctx, iter); 16302 nk_insert_window(ctx, iter, NK_INSERT_BACK); 16303 } 16304 } else { 16305 if (!iter && ctx->end != win) { 16306 if (!(win->flags & NK_WINDOW_BACKGROUND)) { 16307 /* current window is active in that position so transfer to top 16308 * at the highest priority in stack */ 16309 nk_remove_window(ctx, win); 16310 nk_insert_window(ctx, win, NK_INSERT_BACK); 16311 } 16312 win->flags &= ~(nk_flags)NK_WINDOW_ROM; 16313 ctx->active = win; 16314 } 16315 if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND)) 16316 win->flags |= NK_WINDOW_ROM; 16317 } 16318 } 16319 win->layout = (struct nk_panel*)nk_create_panel(ctx); 16320 ctx->current = win; 16321 ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); 16322 win->layout->offset_x = &win->scrollbar.x; 16323 win->layout->offset_y = &win->scrollbar.y; 16324 return ret; 16325 } 16326 NK_API void 16327 nk_end(struct nk_context *ctx) 16328 { 16329 struct nk_panel *layout; 16330 NK_ASSERT(ctx); 16331 NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`"); 16332 if (!ctx || !ctx->current) 16333 return; 16334 16335 layout = ctx->current->layout; 16336 if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) { 16337 ctx->current = 0; 16338 return; 16339 } 16340 nk_panel_end(ctx); 16341 nk_free_panel(ctx, ctx->current->layout); 16342 ctx->current = 0; 16343 } 16344 NK_API struct nk_rect 16345 nk_window_get_bounds(const struct nk_context *ctx) 16346 { 16347 NK_ASSERT(ctx); 16348 NK_ASSERT(ctx->current); 16349 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 16350 return ctx->current->bounds; 16351 } 16352 NK_API struct nk_vec2 16353 nk_window_get_position(const struct nk_context *ctx) 16354 { 16355 NK_ASSERT(ctx); 16356 NK_ASSERT(ctx->current); 16357 if (!ctx || !ctx->current) return nk_vec2(0,0); 16358 return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y); 16359 } 16360 NK_API struct nk_vec2 16361 nk_window_get_size(const struct nk_context *ctx) 16362 { 16363 NK_ASSERT(ctx); 16364 NK_ASSERT(ctx->current); 16365 if (!ctx || !ctx->current) return nk_vec2(0,0); 16366 return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h); 16367 } 16368 NK_API float 16369 nk_window_get_width(const struct nk_context *ctx) 16370 { 16371 NK_ASSERT(ctx); 16372 NK_ASSERT(ctx->current); 16373 if (!ctx || !ctx->current) return 0; 16374 return ctx->current->bounds.w; 16375 } 16376 NK_API float 16377 nk_window_get_height(const struct nk_context *ctx) 16378 { 16379 NK_ASSERT(ctx); 16380 NK_ASSERT(ctx->current); 16381 if (!ctx || !ctx->current) return 0; 16382 return ctx->current->bounds.h; 16383 } 16384 NK_API struct nk_rect 16385 nk_window_get_content_region(struct nk_context *ctx) 16386 { 16387 NK_ASSERT(ctx); 16388 NK_ASSERT(ctx->current); 16389 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 16390 return ctx->current->layout->clip; 16391 } 16392 NK_API struct nk_vec2 16393 nk_window_get_content_region_min(struct nk_context *ctx) 16394 { 16395 NK_ASSERT(ctx); 16396 NK_ASSERT(ctx->current); 16397 NK_ASSERT(ctx->current->layout); 16398 if (!ctx || !ctx->current) return nk_vec2(0,0); 16399 return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y); 16400 } 16401 NK_API struct nk_vec2 16402 nk_window_get_content_region_max(struct nk_context *ctx) 16403 { 16404 NK_ASSERT(ctx); 16405 NK_ASSERT(ctx->current); 16406 NK_ASSERT(ctx->current->layout); 16407 if (!ctx || !ctx->current) return nk_vec2(0,0); 16408 return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w, 16409 ctx->current->layout->clip.y + ctx->current->layout->clip.h); 16410 } 16411 NK_API struct nk_vec2 16412 nk_window_get_content_region_size(struct nk_context *ctx) 16413 { 16414 NK_ASSERT(ctx); 16415 NK_ASSERT(ctx->current); 16416 NK_ASSERT(ctx->current->layout); 16417 if (!ctx || !ctx->current) return nk_vec2(0,0); 16418 return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h); 16419 } 16420 NK_API struct nk_command_buffer* 16421 nk_window_get_canvas(struct nk_context *ctx) 16422 { 16423 NK_ASSERT(ctx); 16424 NK_ASSERT(ctx->current); 16425 NK_ASSERT(ctx->current->layout); 16426 if (!ctx || !ctx->current) return 0; 16427 return &ctx->current->buffer; 16428 } 16429 NK_API struct nk_panel* 16430 nk_window_get_panel(struct nk_context *ctx) 16431 { 16432 NK_ASSERT(ctx); 16433 NK_ASSERT(ctx->current); 16434 if (!ctx || !ctx->current) return 0; 16435 return ctx->current->layout; 16436 } 16437 NK_API int 16438 nk_window_has_focus(const struct nk_context *ctx) 16439 { 16440 NK_ASSERT(ctx); 16441 NK_ASSERT(ctx->current); 16442 NK_ASSERT(ctx->current->layout); 16443 if (!ctx || !ctx->current) return 0; 16444 return ctx->current == ctx->active; 16445 } 16446 NK_API int 16447 nk_window_is_hovered(struct nk_context *ctx) 16448 { 16449 NK_ASSERT(ctx); 16450 NK_ASSERT(ctx->current); 16451 if (!ctx || !ctx->current) return 0; 16452 if(ctx->current->flags & NK_WINDOW_HIDDEN) 16453 return 0; 16454 return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds); 16455 } 16456 NK_API int 16457 nk_window_is_any_hovered(struct nk_context *ctx) 16458 { 16459 struct nk_window *iter; 16460 NK_ASSERT(ctx); 16461 if (!ctx) return 0; 16462 iter = ctx->begin; 16463 while (iter) { 16464 /* check if window is being hovered */ 16465 if(!(iter->flags & NK_WINDOW_HIDDEN)) { 16466 /* check if window popup is being hovered */ 16467 if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) 16468 return 1; 16469 16470 if (iter->flags & NK_WINDOW_MINIMIZED) { 16471 struct nk_rect header = iter->bounds; 16472 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; 16473 if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) 16474 return 1; 16475 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { 16476 return 1; 16477 } 16478 } 16479 iter = iter->next; 16480 } 16481 return 0; 16482 } 16483 NK_API int 16484 nk_item_is_any_active(struct nk_context *ctx) 16485 { 16486 int any_hovered = nk_window_is_any_hovered(ctx); 16487 int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 16488 return any_hovered || any_active; 16489 } 16490 NK_API int 16491 nk_window_is_collapsed(struct nk_context *ctx, const char *name) 16492 { 16493 int title_len; 16494 nk_hash title_hash; 16495 struct nk_window *win; 16496 NK_ASSERT(ctx); 16497 if (!ctx) return 0; 16498 16499 title_len = (int)nk_strlen(name); 16500 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16501 win = nk_find_window(ctx, title_hash, name); 16502 if (!win) return 0; 16503 return win->flags & NK_WINDOW_MINIMIZED; 16504 } 16505 NK_API int 16506 nk_window_is_closed(struct nk_context *ctx, const char *name) 16507 { 16508 int title_len; 16509 nk_hash title_hash; 16510 struct nk_window *win; 16511 NK_ASSERT(ctx); 16512 if (!ctx) return 1; 16513 16514 title_len = (int)nk_strlen(name); 16515 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16516 win = nk_find_window(ctx, title_hash, name); 16517 if (!win) return 1; 16518 return (win->flags & NK_WINDOW_CLOSED); 16519 } 16520 NK_API int 16521 nk_window_is_hidden(struct nk_context *ctx, const char *name) 16522 { 16523 int title_len; 16524 nk_hash title_hash; 16525 struct nk_window *win; 16526 NK_ASSERT(ctx); 16527 if (!ctx) return 1; 16528 16529 title_len = (int)nk_strlen(name); 16530 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16531 win = nk_find_window(ctx, title_hash, name); 16532 if (!win) return 1; 16533 return (win->flags & NK_WINDOW_HIDDEN); 16534 } 16535 NK_API int 16536 nk_window_is_active(struct nk_context *ctx, const char *name) 16537 { 16538 int title_len; 16539 nk_hash title_hash; 16540 struct nk_window *win; 16541 NK_ASSERT(ctx); 16542 if (!ctx) return 0; 16543 16544 title_len = (int)nk_strlen(name); 16545 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16546 win = nk_find_window(ctx, title_hash, name); 16547 if (!win) return 0; 16548 return win == ctx->active; 16549 } 16550 NK_API struct nk_window* 16551 nk_window_find(struct nk_context *ctx, const char *name) 16552 { 16553 int title_len; 16554 nk_hash title_hash; 16555 title_len = (int)nk_strlen(name); 16556 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16557 return nk_find_window(ctx, title_hash, name); 16558 } 16559 NK_API void 16560 nk_window_close(struct nk_context *ctx, const char *name) 16561 { 16562 struct nk_window *win; 16563 NK_ASSERT(ctx); 16564 if (!ctx) return; 16565 win = nk_window_find(ctx, name); 16566 if (!win) return; 16567 NK_ASSERT(ctx->current != win && "You cannot close a currently active window"); 16568 if (ctx->current == win) return; 16569 win->flags |= NK_WINDOW_HIDDEN; 16570 win->flags |= NK_WINDOW_CLOSED; 16571 } 16572 NK_API void 16573 nk_window_set_bounds(struct nk_context *ctx, 16574 const char *name, struct nk_rect bounds) 16575 { 16576 struct nk_window *win; 16577 NK_ASSERT(ctx); 16578 if (!ctx) return; 16579 win = nk_window_find(ctx, name); 16580 if (!win) return; 16581 NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window"); 16582 win->bounds = bounds; 16583 } 16584 NK_API void 16585 nk_window_set_position(struct nk_context *ctx, 16586 const char *name, struct nk_vec2 pos) 16587 { 16588 struct nk_window *win = nk_window_find(ctx, name); 16589 if (!win) return; 16590 win->bounds.x = pos.x; 16591 win->bounds.y = pos.y; 16592 } 16593 NK_API void 16594 nk_window_set_size(struct nk_context *ctx, 16595 const char *name, struct nk_vec2 size) 16596 { 16597 struct nk_window *win = nk_window_find(ctx, name); 16598 if (!win) return; 16599 win->bounds.w = size.x; 16600 win->bounds.h = size.y; 16601 } 16602 NK_API void 16603 nk_window_collapse(struct nk_context *ctx, const char *name, 16604 enum nk_collapse_states c) 16605 { 16606 int title_len; 16607 nk_hash title_hash; 16608 struct nk_window *win; 16609 NK_ASSERT(ctx); 16610 if (!ctx) return; 16611 16612 title_len = (int)nk_strlen(name); 16613 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16614 win = nk_find_window(ctx, title_hash, name); 16615 if (!win) return; 16616 if (c == NK_MINIMIZED) 16617 win->flags |= NK_WINDOW_MINIMIZED; 16618 else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED; 16619 } 16620 NK_API void 16621 nk_window_collapse_if(struct nk_context *ctx, const char *name, 16622 enum nk_collapse_states c, int cond) 16623 { 16624 NK_ASSERT(ctx); 16625 if (!ctx || !cond) return; 16626 nk_window_collapse(ctx, name, c); 16627 } 16628 NK_API void 16629 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s) 16630 { 16631 int title_len; 16632 nk_hash title_hash; 16633 struct nk_window *win; 16634 NK_ASSERT(ctx); 16635 if (!ctx) return; 16636 16637 title_len = (int)nk_strlen(name); 16638 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16639 win = nk_find_window(ctx, title_hash, name); 16640 if (!win) return; 16641 if (s == NK_HIDDEN) { 16642 win->flags |= NK_WINDOW_HIDDEN; 16643 } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN; 16644 } 16645 NK_API void 16646 nk_window_show_if(struct nk_context *ctx, const char *name, 16647 enum nk_show_states s, int cond) 16648 { 16649 NK_ASSERT(ctx); 16650 if (!ctx || !cond) return; 16651 nk_window_show(ctx, name, s); 16652 } 16653 16654 NK_API void 16655 nk_window_set_focus(struct nk_context *ctx, const char *name) 16656 { 16657 int title_len; 16658 nk_hash title_hash; 16659 struct nk_window *win; 16660 NK_ASSERT(ctx); 16661 if (!ctx) return; 16662 16663 title_len = (int)nk_strlen(name); 16664 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16665 win = nk_find_window(ctx, title_hash, name); 16666 if (win && ctx->end != win) { 16667 nk_remove_window(ctx, win); 16668 nk_insert_window(ctx, win, NK_INSERT_BACK); 16669 } 16670 ctx->active = win; 16671 } 16672 16673 16674 16675 16676 16677 /* =============================================================== 16678 * 16679 * POPUP 16680 * 16681 * ===============================================================*/ 16682 NK_API int 16683 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type, 16684 const char *title, nk_flags flags, struct nk_rect rect) 16685 { 16686 struct nk_window *popup; 16687 struct nk_window *win; 16688 struct nk_panel *panel; 16689 16690 int title_len; 16691 nk_hash title_hash; 16692 nk_size allocated; 16693 16694 NK_ASSERT(ctx); 16695 NK_ASSERT(title); 16696 NK_ASSERT(ctx->current); 16697 NK_ASSERT(ctx->current->layout); 16698 if (!ctx || !ctx->current || !ctx->current->layout) 16699 return 0; 16700 16701 win = ctx->current; 16702 panel = win->layout; 16703 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups"); 16704 (void)panel; 16705 title_len = (int)nk_strlen(title); 16706 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP); 16707 16708 popup = win->popup.win; 16709 if (!popup) { 16710 popup = (struct nk_window*)nk_create_window(ctx); 16711 popup->parent = win; 16712 win->popup.win = popup; 16713 win->popup.active = 0; 16714 win->popup.type = NK_PANEL_POPUP; 16715 } 16716 16717 /* make sure we have correct popup */ 16718 if (win->popup.name != title_hash) { 16719 if (!win->popup.active) { 16720 nk_zero(popup, sizeof(*popup)); 16721 win->popup.name = title_hash; 16722 win->popup.active = 1; 16723 win->popup.type = NK_PANEL_POPUP; 16724 } else return 0; 16725 } 16726 16727 /* popup position is local to window */ 16728 ctx->current = popup; 16729 rect.x += win->layout->clip.x; 16730 rect.y += win->layout->clip.y; 16731 16732 /* setup popup data */ 16733 popup->parent = win; 16734 popup->bounds = rect; 16735 popup->seq = ctx->seq; 16736 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 16737 popup->flags = flags; 16738 popup->flags |= NK_WINDOW_BORDER; 16739 if (type == NK_POPUP_DYNAMIC) 16740 popup->flags |= NK_WINDOW_DYNAMIC; 16741 16742 popup->buffer = win->buffer; 16743 nk_start_popup(ctx, win); 16744 allocated = ctx->memory.allocated; 16745 nk_push_scissor(&popup->buffer, nk_null_rect); 16746 16747 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) { 16748 /* popup is running therefore invalidate parent panels */ 16749 struct nk_panel *root; 16750 root = win->layout; 16751 while (root) { 16752 root->flags |= NK_WINDOW_ROM; 16753 root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 16754 root = root->parent; 16755 } 16756 win->popup.active = 1; 16757 popup->layout->offset_x = &popup->scrollbar.x; 16758 popup->layout->offset_y = &popup->scrollbar.y; 16759 popup->layout->parent = win->layout; 16760 return 1; 16761 } else { 16762 /* popup was closed/is invalid so cleanup */ 16763 struct nk_panel *root; 16764 root = win->layout; 16765 while (root) { 16766 root->flags |= NK_WINDOW_REMOVE_ROM; 16767 root = root->parent; 16768 } 16769 win->popup.buf.active = 0; 16770 win->popup.active = 0; 16771 ctx->memory.allocated = allocated; 16772 ctx->current = win; 16773 nk_free_panel(ctx, popup->layout); 16774 popup->layout = 0; 16775 return 0; 16776 } 16777 } 16778 NK_LIB int 16779 nk_nonblock_begin(struct nk_context *ctx, 16780 nk_flags flags, struct nk_rect body, struct nk_rect header, 16781 enum nk_panel_type panel_type) 16782 { 16783 struct nk_window *popup; 16784 struct nk_window *win; 16785 struct nk_panel *panel; 16786 int is_active = nk_true; 16787 16788 NK_ASSERT(ctx); 16789 NK_ASSERT(ctx->current); 16790 NK_ASSERT(ctx->current->layout); 16791 if (!ctx || !ctx->current || !ctx->current->layout) 16792 return 0; 16793 16794 /* popups cannot have popups */ 16795 win = ctx->current; 16796 panel = win->layout; 16797 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); 16798 (void)panel; 16799 popup = win->popup.win; 16800 if (!popup) { 16801 /* create window for nonblocking popup */ 16802 popup = (struct nk_window*)nk_create_window(ctx); 16803 popup->parent = win; 16804 win->popup.win = popup; 16805 win->popup.type = panel_type; 16806 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON); 16807 } else { 16808 /* close the popup if user pressed outside or in the header */ 16809 int pressed, in_body, in_header; 16810 pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 16811 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 16812 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); 16813 if (pressed && (!in_body || in_header)) 16814 is_active = nk_false; 16815 } 16816 win->popup.header = header; 16817 16818 if (!is_active) { 16819 /* remove read only mode from all parent panels */ 16820 struct nk_panel *root = win->layout; 16821 while (root) { 16822 root->flags |= NK_WINDOW_REMOVE_ROM; 16823 root = root->parent; 16824 } 16825 return is_active; 16826 } 16827 popup->bounds = body; 16828 popup->parent = win; 16829 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 16830 popup->flags = flags; 16831 popup->flags |= NK_WINDOW_BORDER; 16832 popup->flags |= NK_WINDOW_DYNAMIC; 16833 popup->seq = ctx->seq; 16834 win->popup.active = 1; 16835 NK_ASSERT(popup->layout); 16836 16837 nk_start_popup(ctx, win); 16838 popup->buffer = win->buffer; 16839 nk_push_scissor(&popup->buffer, nk_null_rect); 16840 ctx->current = popup; 16841 16842 nk_panel_begin(ctx, 0, panel_type); 16843 win->buffer = popup->buffer; 16844 popup->layout->parent = win->layout; 16845 popup->layout->offset_x = &popup->scrollbar.x; 16846 popup->layout->offset_y = &popup->scrollbar.y; 16847 16848 /* set read only mode to all parent panels */ 16849 {struct nk_panel *root; 16850 root = win->layout; 16851 while (root) { 16852 root->flags |= NK_WINDOW_ROM; 16853 root = root->parent; 16854 }} 16855 return is_active; 16856 } 16857 NK_API void 16858 nk_popup_close(struct nk_context *ctx) 16859 { 16860 struct nk_window *popup; 16861 NK_ASSERT(ctx); 16862 if (!ctx || !ctx->current) return; 16863 16864 popup = ctx->current; 16865 NK_ASSERT(popup->parent); 16866 NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP); 16867 popup->flags |= NK_WINDOW_HIDDEN; 16868 } 16869 NK_API void 16870 nk_popup_end(struct nk_context *ctx) 16871 { 16872 struct nk_window *win; 16873 struct nk_window *popup; 16874 16875 NK_ASSERT(ctx); 16876 NK_ASSERT(ctx->current); 16877 NK_ASSERT(ctx->current->layout); 16878 if (!ctx || !ctx->current || !ctx->current->layout) 16879 return; 16880 16881 popup = ctx->current; 16882 if (!popup->parent) return; 16883 win = popup->parent; 16884 if (popup->flags & NK_WINDOW_HIDDEN) { 16885 struct nk_panel *root; 16886 root = win->layout; 16887 while (root) { 16888 root->flags |= NK_WINDOW_REMOVE_ROM; 16889 root = root->parent; 16890 } 16891 win->popup.active = 0; 16892 } 16893 nk_push_scissor(&popup->buffer, nk_null_rect); 16894 nk_end(ctx); 16895 16896 win->buffer = popup->buffer; 16897 nk_finish_popup(ctx, win); 16898 ctx->current = win; 16899 nk_push_scissor(&win->buffer, win->layout->clip); 16900 } 16901 16902 16903 16904 16905 16906 /* ============================================================== 16907 * 16908 * CONTEXTUAL 16909 * 16910 * ===============================================================*/ 16911 NK_API int 16912 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size, 16913 struct nk_rect trigger_bounds) 16914 { 16915 struct nk_window *win; 16916 struct nk_window *popup; 16917 struct nk_rect body; 16918 16919 NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0}; 16920 int is_clicked = 0; 16921 int is_open = 0; 16922 int ret = 0; 16923 16924 NK_ASSERT(ctx); 16925 NK_ASSERT(ctx->current); 16926 NK_ASSERT(ctx->current->layout); 16927 if (!ctx || !ctx->current || !ctx->current->layout) 16928 return 0; 16929 16930 win = ctx->current; 16931 ++win->popup.con_count; 16932 if (ctx->current != ctx->active) 16933 return 0; 16934 16935 /* check if currently active contextual is active */ 16936 popup = win->popup.win; 16937 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL); 16938 is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds); 16939 if (win->popup.active_con && win->popup.con_count != win->popup.active_con) 16940 return 0; 16941 if (!is_open && win->popup.active_con) 16942 win->popup.active_con = 0; 16943 if ((!is_open && !is_clicked)) 16944 return 0; 16945 16946 /* calculate contextual position on click */ 16947 win->popup.active_con = win->popup.con_count; 16948 if (is_clicked) { 16949 body.x = ctx->input.mouse.pos.x; 16950 body.y = ctx->input.mouse.pos.y; 16951 } else { 16952 body.x = popup->bounds.x; 16953 body.y = popup->bounds.y; 16954 } 16955 body.w = size.x; 16956 body.h = size.y; 16957 16958 /* start nonblocking contextual popup */ 16959 ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body, 16960 null_rect, NK_PANEL_CONTEXTUAL); 16961 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL; 16962 else { 16963 win->popup.active_con = 0; 16964 win->popup.type = NK_PANEL_NONE; 16965 if (win->popup.win) 16966 win->popup.win->flags = 0; 16967 } 16968 return ret; 16969 } 16970 NK_API int 16971 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len, 16972 nk_flags alignment) 16973 { 16974 struct nk_window *win; 16975 const struct nk_input *in; 16976 const struct nk_style *style; 16977 16978 struct nk_rect bounds; 16979 enum nk_widget_layout_states state; 16980 16981 NK_ASSERT(ctx); 16982 NK_ASSERT(ctx->current); 16983 NK_ASSERT(ctx->current->layout); 16984 if (!ctx || !ctx->current || !ctx->current->layout) 16985 return 0; 16986 16987 win = ctx->current; 16988 style = &ctx->style; 16989 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 16990 if (!state) return nk_false; 16991 16992 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 16993 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 16994 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) { 16995 nk_contextual_close(ctx); 16996 return nk_true; 16997 } 16998 return nk_false; 16999 } 17000 NK_API int 17001 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align) 17002 { 17003 return nk_contextual_item_text(ctx, label, nk_strlen(label), align); 17004 } 17005 NK_API int 17006 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img, 17007 const char *text, int len, nk_flags align) 17008 { 17009 struct nk_window *win; 17010 const struct nk_input *in; 17011 const struct nk_style *style; 17012 17013 struct nk_rect bounds; 17014 enum nk_widget_layout_states state; 17015 17016 NK_ASSERT(ctx); 17017 NK_ASSERT(ctx->current); 17018 NK_ASSERT(ctx->current->layout); 17019 if (!ctx || !ctx->current || !ctx->current->layout) 17020 return 0; 17021 17022 win = ctx->current; 17023 style = &ctx->style; 17024 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17025 if (!state) return nk_false; 17026 17027 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17028 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, 17029 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){ 17030 nk_contextual_close(ctx); 17031 return nk_true; 17032 } 17033 return nk_false; 17034 } 17035 NK_API int 17036 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img, 17037 const char *label, nk_flags align) 17038 { 17039 return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align); 17040 } 17041 NK_API int 17042 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 17043 const char *text, int len, nk_flags align) 17044 { 17045 struct nk_window *win; 17046 const struct nk_input *in; 17047 const struct nk_style *style; 17048 17049 struct nk_rect bounds; 17050 enum nk_widget_layout_states state; 17051 17052 NK_ASSERT(ctx); 17053 NK_ASSERT(ctx->current); 17054 NK_ASSERT(ctx->current->layout); 17055 if (!ctx || !ctx->current || !ctx->current->layout) 17056 return 0; 17057 17058 win = ctx->current; 17059 style = &ctx->style; 17060 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17061 if (!state) return nk_false; 17062 17063 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17064 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 17065 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) { 17066 nk_contextual_close(ctx); 17067 return nk_true; 17068 } 17069 return nk_false; 17070 } 17071 NK_API int 17072 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 17073 const char *text, nk_flags align) 17074 { 17075 return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align); 17076 } 17077 NK_API void 17078 nk_contextual_close(struct nk_context *ctx) 17079 { 17080 NK_ASSERT(ctx); 17081 NK_ASSERT(ctx->current); 17082 NK_ASSERT(ctx->current->layout); 17083 if (!ctx || !ctx->current || !ctx->current->layout) return; 17084 nk_popup_close(ctx); 17085 } 17086 NK_API void 17087 nk_contextual_end(struct nk_context *ctx) 17088 { 17089 struct nk_window *popup; 17090 struct nk_panel *panel; 17091 NK_ASSERT(ctx); 17092 NK_ASSERT(ctx->current); 17093 if (!ctx || !ctx->current) return; 17094 17095 popup = ctx->current; 17096 panel = popup->layout; 17097 NK_ASSERT(popup->parent); 17098 NK_ASSERT(panel->type & NK_PANEL_SET_POPUP); 17099 if (panel->flags & NK_WINDOW_DYNAMIC) { 17100 /* Close behavior 17101 This is a bit of a hack solution since we do not know before we end our popup 17102 how big it will be. We therefore do not directly know when a 17103 click outside the non-blocking popup must close it at that direct frame. 17104 Instead it will be closed in the next frame.*/ 17105 struct nk_rect body = {0,0,0,0}; 17106 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) { 17107 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type); 17108 body = panel->bounds; 17109 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height); 17110 body.h = (panel->bounds.y + panel->bounds.h) - body.y; 17111 } 17112 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 17113 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 17114 if (pressed && in_body) 17115 popup->flags |= NK_WINDOW_HIDDEN; 17116 } 17117 } 17118 if (popup->flags & NK_WINDOW_HIDDEN) 17119 popup->seq = 0; 17120 nk_popup_end(ctx); 17121 return; 17122 } 17123 17124 17125 17126 17127 17128 /* =============================================================== 17129 * 17130 * MENU 17131 * 17132 * ===============================================================*/ 17133 NK_API void 17134 nk_menubar_begin(struct nk_context *ctx) 17135 { 17136 struct nk_panel *layout; 17137 NK_ASSERT(ctx); 17138 NK_ASSERT(ctx->current); 17139 NK_ASSERT(ctx->current->layout); 17140 if (!ctx || !ctx->current || !ctx->current->layout) 17141 return; 17142 17143 layout = ctx->current->layout; 17144 NK_ASSERT(layout->at_y == layout->bounds.y); 17145 /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin. 17146 If you want a menubar the first nuklear function after `nk_begin` has to be a 17147 `nk_menubar_begin` call. Inside the menubar you then have to allocate space for 17148 widgets (also supports multiple rows). 17149 Example: 17150 if (nk_begin(...)) { 17151 nk_menubar_begin(...); 17152 nk_layout_xxxx(...); 17153 nk_button(...); 17154 nk_layout_xxxx(...); 17155 nk_button(...); 17156 nk_menubar_end(...); 17157 } 17158 nk_end(...); 17159 */ 17160 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 17161 return; 17162 17163 layout->menu.x = layout->at_x; 17164 layout->menu.y = layout->at_y + layout->row.height; 17165 layout->menu.w = layout->bounds.w; 17166 layout->menu.offset.x = *layout->offset_x; 17167 layout->menu.offset.y = *layout->offset_y; 17168 *layout->offset_y = 0; 17169 } 17170 NK_API void 17171 nk_menubar_end(struct nk_context *ctx) 17172 { 17173 struct nk_window *win; 17174 struct nk_panel *layout; 17175 struct nk_command_buffer *out; 17176 17177 NK_ASSERT(ctx); 17178 NK_ASSERT(ctx->current); 17179 NK_ASSERT(ctx->current->layout); 17180 if (!ctx || !ctx->current || !ctx->current->layout) 17181 return; 17182 17183 win = ctx->current; 17184 out = &win->buffer; 17185 layout = win->layout; 17186 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 17187 return; 17188 17189 layout->menu.h = layout->at_y - layout->menu.y; 17190 layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height; 17191 layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height; 17192 17193 *layout->offset_x = layout->menu.offset.x; 17194 *layout->offset_y = layout->menu.offset.y; 17195 layout->at_y = layout->bounds.y - layout->row.height; 17196 17197 layout->clip.y = layout->bounds.y; 17198 layout->clip.h = layout->bounds.h; 17199 nk_push_scissor(out, layout->clip); 17200 } 17201 NK_INTERN int 17202 nk_menu_begin(struct nk_context *ctx, struct nk_window *win, 17203 const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size) 17204 { 17205 int is_open = 0; 17206 int is_active = 0; 17207 struct nk_rect body; 17208 struct nk_window *popup; 17209 nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU); 17210 17211 NK_ASSERT(ctx); 17212 NK_ASSERT(ctx->current); 17213 NK_ASSERT(ctx->current->layout); 17214 if (!ctx || !ctx->current || !ctx->current->layout) 17215 return 0; 17216 17217 body.x = header.x; 17218 body.w = size.x; 17219 body.y = header.y + header.h; 17220 body.h = size.y; 17221 17222 popup = win->popup.win; 17223 is_open = popup ? nk_true : nk_false; 17224 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU); 17225 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 17226 (!is_open && !is_active && !is_clicked)) return 0; 17227 if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU)) 17228 return 0; 17229 17230 win->popup.type = NK_PANEL_MENU; 17231 win->popup.name = hash; 17232 return 1; 17233 } 17234 NK_API int 17235 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len, 17236 nk_flags align, struct nk_vec2 size) 17237 { 17238 struct nk_window *win; 17239 const struct nk_input *in; 17240 struct nk_rect header; 17241 int is_clicked = nk_false; 17242 nk_flags state; 17243 17244 NK_ASSERT(ctx); 17245 NK_ASSERT(ctx->current); 17246 NK_ASSERT(ctx->current->layout); 17247 if (!ctx || !ctx->current || !ctx->current->layout) 17248 return 0; 17249 17250 win = ctx->current; 17251 state = nk_widget(&header, ctx); 17252 if (!state) return 0; 17253 in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17254 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header, 17255 title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 17256 is_clicked = nk_true; 17257 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17258 } 17259 NK_API int nk_menu_begin_label(struct nk_context *ctx, 17260 const char *text, nk_flags align, struct nk_vec2 size) 17261 { 17262 return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size); 17263 } 17264 NK_API int 17265 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img, 17266 struct nk_vec2 size) 17267 { 17268 struct nk_window *win; 17269 struct nk_rect header; 17270 const struct nk_input *in; 17271 int is_clicked = nk_false; 17272 nk_flags state; 17273 17274 NK_ASSERT(ctx); 17275 NK_ASSERT(ctx->current); 17276 NK_ASSERT(ctx->current->layout); 17277 if (!ctx || !ctx->current || !ctx->current->layout) 17278 return 0; 17279 17280 win = ctx->current; 17281 state = nk_widget(&header, ctx); 17282 if (!state) return 0; 17283 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17284 if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header, 17285 img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in)) 17286 is_clicked = nk_true; 17287 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 17288 } 17289 NK_API int 17290 nk_menu_begin_symbol(struct nk_context *ctx, const char *id, 17291 enum nk_symbol_type sym, struct nk_vec2 size) 17292 { 17293 struct nk_window *win; 17294 const struct nk_input *in; 17295 struct nk_rect header; 17296 int is_clicked = nk_false; 17297 nk_flags state; 17298 17299 NK_ASSERT(ctx); 17300 NK_ASSERT(ctx->current); 17301 NK_ASSERT(ctx->current->layout); 17302 if (!ctx || !ctx->current || !ctx->current->layout) 17303 return 0; 17304 17305 win = ctx->current; 17306 state = nk_widget(&header, ctx); 17307 if (!state) return 0; 17308 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17309 if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, 17310 sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 17311 is_clicked = nk_true; 17312 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 17313 } 17314 NK_API int 17315 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len, 17316 nk_flags align, struct nk_image img, struct nk_vec2 size) 17317 { 17318 struct nk_window *win; 17319 struct nk_rect header; 17320 const struct nk_input *in; 17321 int is_clicked = nk_false; 17322 nk_flags state; 17323 17324 NK_ASSERT(ctx); 17325 NK_ASSERT(ctx->current); 17326 NK_ASSERT(ctx->current->layout); 17327 if (!ctx || !ctx->current || !ctx->current->layout) 17328 return 0; 17329 17330 win = ctx->current; 17331 state = nk_widget(&header, ctx); 17332 if (!state) return 0; 17333 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17334 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 17335 header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 17336 ctx->style.font, in)) 17337 is_clicked = nk_true; 17338 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17339 } 17340 NK_API int 17341 nk_menu_begin_image_label(struct nk_context *ctx, 17342 const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size) 17343 { 17344 return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size); 17345 } 17346 NK_API int 17347 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len, 17348 nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size) 17349 { 17350 struct nk_window *win; 17351 struct nk_rect header; 17352 const struct nk_input *in; 17353 int is_clicked = nk_false; 17354 nk_flags state; 17355 17356 NK_ASSERT(ctx); 17357 NK_ASSERT(ctx->current); 17358 NK_ASSERT(ctx->current->layout); 17359 if (!ctx || !ctx->current || !ctx->current->layout) 17360 return 0; 17361 17362 win = ctx->current; 17363 state = nk_widget(&header, ctx); 17364 if (!state) return 0; 17365 17366 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17367 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, 17368 header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 17369 ctx->style.font, in)) is_clicked = nk_true; 17370 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17371 } 17372 NK_API int 17373 nk_menu_begin_symbol_label(struct nk_context *ctx, 17374 const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size ) 17375 { 17376 return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size); 17377 } 17378 NK_API int 17379 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align) 17380 { 17381 return nk_contextual_item_text(ctx, title, len, align); 17382 } 17383 NK_API int 17384 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align) 17385 { 17386 return nk_contextual_item_label(ctx, label, align); 17387 } 17388 NK_API int 17389 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img, 17390 const char *label, nk_flags align) 17391 { 17392 return nk_contextual_item_image_label(ctx, img, label, align); 17393 } 17394 NK_API int 17395 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img, 17396 const char *text, int len, nk_flags align) 17397 { 17398 return nk_contextual_item_image_text(ctx, img, text, len, align); 17399 } 17400 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 17401 const char *text, int len, nk_flags align) 17402 { 17403 return nk_contextual_item_symbol_text(ctx, sym, text, len, align); 17404 } 17405 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 17406 const char *label, nk_flags align) 17407 { 17408 return nk_contextual_item_symbol_label(ctx, sym, label, align); 17409 } 17410 NK_API void nk_menu_close(struct nk_context *ctx) 17411 { 17412 nk_contextual_close(ctx); 17413 } 17414 NK_API void 17415 nk_menu_end(struct nk_context *ctx) 17416 { 17417 nk_contextual_end(ctx); 17418 } 17419 17420 17421 17422 17423 17424 /* =============================================================== 17425 * 17426 * LAYOUT 17427 * 17428 * ===============================================================*/ 17429 NK_API void 17430 nk_layout_set_min_row_height(struct nk_context *ctx, float height) 17431 { 17432 struct nk_window *win; 17433 struct nk_panel *layout; 17434 17435 NK_ASSERT(ctx); 17436 NK_ASSERT(ctx->current); 17437 NK_ASSERT(ctx->current->layout); 17438 if (!ctx || !ctx->current || !ctx->current->layout) 17439 return; 17440 17441 win = ctx->current; 17442 layout = win->layout; 17443 layout->row.min_height = height; 17444 } 17445 NK_API void 17446 nk_layout_reset_min_row_height(struct nk_context *ctx) 17447 { 17448 struct nk_window *win; 17449 struct nk_panel *layout; 17450 17451 NK_ASSERT(ctx); 17452 NK_ASSERT(ctx->current); 17453 NK_ASSERT(ctx->current->layout); 17454 if (!ctx || !ctx->current || !ctx->current->layout) 17455 return; 17456 17457 win = ctx->current; 17458 layout = win->layout; 17459 layout->row.min_height = ctx->style.font->height; 17460 layout->row.min_height += ctx->style.text.padding.y*2; 17461 layout->row.min_height += ctx->style.window.min_row_height_padding*2; 17462 } 17463 NK_LIB float 17464 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, 17465 float total_space, int columns) 17466 { 17467 float panel_padding; 17468 float panel_spacing; 17469 float panel_space; 17470 17471 struct nk_vec2 spacing; 17472 struct nk_vec2 padding; 17473 17474 spacing = style->window.spacing; 17475 padding = nk_panel_get_padding(style, type); 17476 17477 /* calculate the usable panel space */ 17478 panel_padding = 2 * padding.x; 17479 panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x; 17480 panel_space = total_space - panel_padding - panel_spacing; 17481 return panel_space; 17482 } 17483 NK_LIB void 17484 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, 17485 float height, int cols) 17486 { 17487 struct nk_panel *layout; 17488 const struct nk_style *style; 17489 struct nk_command_buffer *out; 17490 17491 struct nk_vec2 item_spacing; 17492 struct nk_color color; 17493 17494 NK_ASSERT(ctx); 17495 NK_ASSERT(ctx->current); 17496 NK_ASSERT(ctx->current->layout); 17497 if (!ctx || !ctx->current || !ctx->current->layout) 17498 return; 17499 17500 /* prefetch some configuration data */ 17501 layout = win->layout; 17502 style = &ctx->style; 17503 out = &win->buffer; 17504 color = style->window.background; 17505 item_spacing = style->window.spacing; 17506 17507 /* if one of these triggers you forgot to add an `if` condition around either 17508 a window, group, popup, combobox or contextual menu `begin` and `end` block. 17509 Example: 17510 if (nk_begin(...) {...} nk_end(...); or 17511 if (nk_group_begin(...) { nk_group_end(...);} */ 17512 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 17513 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 17514 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 17515 17516 /* update the current row and set the current row layout */ 17517 layout->row.index = 0; 17518 layout->at_y += layout->row.height; 17519 layout->row.columns = cols; 17520 if (height == 0.0f) 17521 layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y; 17522 else layout->row.height = height + item_spacing.y; 17523 17524 layout->row.item_offset = 0; 17525 if (layout->flags & NK_WINDOW_DYNAMIC) { 17526 /* draw background for dynamic panels */ 17527 struct nk_rect background; 17528 background.x = win->bounds.x; 17529 background.w = win->bounds.w; 17530 background.y = layout->at_y - 1.0f; 17531 background.h = layout->row.height + 1.0f; 17532 nk_fill_rect(out, background, 0, color); 17533 } 17534 } 17535 NK_LIB void 17536 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, 17537 float height, int cols, int width) 17538 { 17539 /* update the current row and set the current row layout */ 17540 struct nk_window *win; 17541 NK_ASSERT(ctx); 17542 NK_ASSERT(ctx->current); 17543 NK_ASSERT(ctx->current->layout); 17544 if (!ctx || !ctx->current || !ctx->current->layout) 17545 return; 17546 17547 win = ctx->current; 17548 nk_panel_layout(ctx, win, height, cols); 17549 if (fmt == NK_DYNAMIC) 17550 win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED; 17551 else win->layout->row.type = NK_LAYOUT_STATIC_FIXED; 17552 17553 win->layout->row.ratio = 0; 17554 win->layout->row.filled = 0; 17555 win->layout->row.item_offset = 0; 17556 win->layout->row.item_width = (float)width; 17557 } 17558 NK_API float 17559 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width) 17560 { 17561 struct nk_window *win; 17562 NK_ASSERT(ctx); 17563 NK_ASSERT(pixel_width); 17564 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 17565 win = ctx->current; 17566 return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f); 17567 } 17568 NK_API void 17569 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols) 17570 { 17571 nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0); 17572 } 17573 NK_API void 17574 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols) 17575 { 17576 nk_row_layout(ctx, NK_STATIC, height, cols, item_width); 17577 } 17578 NK_API void 17579 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, 17580 float row_height, int cols) 17581 { 17582 struct nk_window *win; 17583 struct nk_panel *layout; 17584 17585 NK_ASSERT(ctx); 17586 NK_ASSERT(ctx->current); 17587 NK_ASSERT(ctx->current->layout); 17588 if (!ctx || !ctx->current || !ctx->current->layout) 17589 return; 17590 17591 win = ctx->current; 17592 layout = win->layout; 17593 nk_panel_layout(ctx, win, row_height, cols); 17594 if (fmt == NK_DYNAMIC) 17595 layout->row.type = NK_LAYOUT_DYNAMIC_ROW; 17596 else layout->row.type = NK_LAYOUT_STATIC_ROW; 17597 17598 layout->row.ratio = 0; 17599 layout->row.filled = 0; 17600 layout->row.item_width = 0; 17601 layout->row.item_offset = 0; 17602 layout->row.columns = cols; 17603 } 17604 NK_API void 17605 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width) 17606 { 17607 struct nk_window *win; 17608 struct nk_panel *layout; 17609 17610 NK_ASSERT(ctx); 17611 NK_ASSERT(ctx->current); 17612 NK_ASSERT(ctx->current->layout); 17613 if (!ctx || !ctx->current || !ctx->current->layout) 17614 return; 17615 17616 win = ctx->current; 17617 layout = win->layout; 17618 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 17619 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 17620 return; 17621 17622 if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) { 17623 float ratio = ratio_or_width; 17624 if ((ratio + layout->row.filled) > 1.0f) return; 17625 if (ratio > 0.0f) 17626 layout->row.item_width = NK_SATURATE(ratio); 17627 else layout->row.item_width = 1.0f - layout->row.filled; 17628 } else layout->row.item_width = ratio_or_width; 17629 } 17630 NK_API void 17631 nk_layout_row_end(struct nk_context *ctx) 17632 { 17633 struct nk_window *win; 17634 struct nk_panel *layout; 17635 17636 NK_ASSERT(ctx); 17637 NK_ASSERT(ctx->current); 17638 NK_ASSERT(ctx->current->layout); 17639 if (!ctx || !ctx->current || !ctx->current->layout) 17640 return; 17641 17642 win = ctx->current; 17643 layout = win->layout; 17644 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 17645 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 17646 return; 17647 layout->row.item_width = 0; 17648 layout->row.item_offset = 0; 17649 } 17650 NK_API void 17651 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt, 17652 float height, int cols, const float *ratio) 17653 { 17654 int i; 17655 int n_undef = 0; 17656 struct nk_window *win; 17657 struct nk_panel *layout; 17658 17659 NK_ASSERT(ctx); 17660 NK_ASSERT(ctx->current); 17661 NK_ASSERT(ctx->current->layout); 17662 if (!ctx || !ctx->current || !ctx->current->layout) 17663 return; 17664 17665 win = ctx->current; 17666 layout = win->layout; 17667 nk_panel_layout(ctx, win, height, cols); 17668 if (fmt == NK_DYNAMIC) { 17669 /* calculate width of undefined widget ratios */ 17670 float r = 0; 17671 layout->row.ratio = ratio; 17672 for (i = 0; i < cols; ++i) { 17673 if (ratio[i] < 0.0f) 17674 n_undef++; 17675 else r += ratio[i]; 17676 } 17677 r = NK_SATURATE(1.0f - r); 17678 layout->row.type = NK_LAYOUT_DYNAMIC; 17679 layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0; 17680 } else { 17681 layout->row.ratio = ratio; 17682 layout->row.type = NK_LAYOUT_STATIC; 17683 layout->row.item_width = 0; 17684 layout->row.item_offset = 0; 17685 } 17686 layout->row.item_offset = 0; 17687 layout->row.filled = 0; 17688 } 17689 NK_API void 17690 nk_layout_row_template_begin(struct nk_context *ctx, float height) 17691 { 17692 struct nk_window *win; 17693 struct nk_panel *layout; 17694 17695 NK_ASSERT(ctx); 17696 NK_ASSERT(ctx->current); 17697 NK_ASSERT(ctx->current->layout); 17698 if (!ctx || !ctx->current || !ctx->current->layout) 17699 return; 17700 17701 win = ctx->current; 17702 layout = win->layout; 17703 nk_panel_layout(ctx, win, height, 1); 17704 layout->row.type = NK_LAYOUT_TEMPLATE; 17705 layout->row.columns = 0; 17706 layout->row.ratio = 0; 17707 layout->row.item_width = 0; 17708 layout->row.item_height = 0; 17709 layout->row.item_offset = 0; 17710 layout->row.filled = 0; 17711 layout->row.item.x = 0; 17712 layout->row.item.y = 0; 17713 layout->row.item.w = 0; 17714 layout->row.item.h = 0; 17715 } 17716 NK_API void 17717 nk_layout_row_template_push_dynamic(struct nk_context *ctx) 17718 { 17719 struct nk_window *win; 17720 struct nk_panel *layout; 17721 17722 NK_ASSERT(ctx); 17723 NK_ASSERT(ctx->current); 17724 NK_ASSERT(ctx->current->layout); 17725 if (!ctx || !ctx->current || !ctx->current->layout) 17726 return; 17727 17728 win = ctx->current; 17729 layout = win->layout; 17730 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17731 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17732 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17733 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17734 layout->row.templates[layout->row.columns++] = -1.0f; 17735 } 17736 NK_API void 17737 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width) 17738 { 17739 struct nk_window *win; 17740 struct nk_panel *layout; 17741 17742 NK_ASSERT(ctx); 17743 NK_ASSERT(ctx->current); 17744 NK_ASSERT(ctx->current->layout); 17745 if (!ctx || !ctx->current || !ctx->current->layout) 17746 return; 17747 17748 win = ctx->current; 17749 layout = win->layout; 17750 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17751 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17752 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17753 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17754 layout->row.templates[layout->row.columns++] = -min_width; 17755 } 17756 NK_API void 17757 nk_layout_row_template_push_static(struct nk_context *ctx, float width) 17758 { 17759 struct nk_window *win; 17760 struct nk_panel *layout; 17761 17762 NK_ASSERT(ctx); 17763 NK_ASSERT(ctx->current); 17764 NK_ASSERT(ctx->current->layout); 17765 if (!ctx || !ctx->current || !ctx->current->layout) 17766 return; 17767 17768 win = ctx->current; 17769 layout = win->layout; 17770 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17771 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17772 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17773 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17774 layout->row.templates[layout->row.columns++] = width; 17775 } 17776 NK_API void 17777 nk_layout_row_template_end(struct nk_context *ctx) 17778 { 17779 struct nk_window *win; 17780 struct nk_panel *layout; 17781 17782 int i = 0; 17783 int variable_count = 0; 17784 int min_variable_count = 0; 17785 float min_fixed_width = 0.0f; 17786 float total_fixed_width = 0.0f; 17787 float max_variable_width = 0.0f; 17788 17789 NK_ASSERT(ctx); 17790 NK_ASSERT(ctx->current); 17791 NK_ASSERT(ctx->current->layout); 17792 if (!ctx || !ctx->current || !ctx->current->layout) 17793 return; 17794 17795 win = ctx->current; 17796 layout = win->layout; 17797 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17798 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17799 for (i = 0; i < layout->row.columns; ++i) { 17800 float width = layout->row.templates[i]; 17801 if (width >= 0.0f) { 17802 total_fixed_width += width; 17803 min_fixed_width += width; 17804 } else if (width < -1.0f) { 17805 width = -width; 17806 total_fixed_width += width; 17807 max_variable_width = NK_MAX(max_variable_width, width); 17808 variable_count++; 17809 } else { 17810 min_variable_count++; 17811 variable_count++; 17812 } 17813 } 17814 if (variable_count) { 17815 float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 17816 layout->bounds.w, layout->row.columns); 17817 float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count; 17818 int enough_space = var_width >= max_variable_width; 17819 if (!enough_space) 17820 var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count; 17821 for (i = 0; i < layout->row.columns; ++i) { 17822 float *width = &layout->row.templates[i]; 17823 *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width; 17824 } 17825 } 17826 } 17827 NK_API void 17828 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt, 17829 float height, int widget_count) 17830 { 17831 struct nk_window *win; 17832 struct nk_panel *layout; 17833 17834 NK_ASSERT(ctx); 17835 NK_ASSERT(ctx->current); 17836 NK_ASSERT(ctx->current->layout); 17837 if (!ctx || !ctx->current || !ctx->current->layout) 17838 return; 17839 17840 win = ctx->current; 17841 layout = win->layout; 17842 nk_panel_layout(ctx, win, height, widget_count); 17843 if (fmt == NK_STATIC) 17844 layout->row.type = NK_LAYOUT_STATIC_FREE; 17845 else layout->row.type = NK_LAYOUT_DYNAMIC_FREE; 17846 17847 layout->row.ratio = 0; 17848 layout->row.filled = 0; 17849 layout->row.item_width = 0; 17850 layout->row.item_offset = 0; 17851 } 17852 NK_API void 17853 nk_layout_space_end(struct nk_context *ctx) 17854 { 17855 struct nk_window *win; 17856 struct nk_panel *layout; 17857 17858 NK_ASSERT(ctx); 17859 NK_ASSERT(ctx->current); 17860 NK_ASSERT(ctx->current->layout); 17861 if (!ctx || !ctx->current || !ctx->current->layout) 17862 return; 17863 17864 win = ctx->current; 17865 layout = win->layout; 17866 layout->row.item_width = 0; 17867 layout->row.item_height = 0; 17868 layout->row.item_offset = 0; 17869 nk_zero(&layout->row.item, sizeof(layout->row.item)); 17870 } 17871 NK_API void 17872 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect) 17873 { 17874 struct nk_window *win; 17875 struct nk_panel *layout; 17876 17877 NK_ASSERT(ctx); 17878 NK_ASSERT(ctx->current); 17879 NK_ASSERT(ctx->current->layout); 17880 if (!ctx || !ctx->current || !ctx->current->layout) 17881 return; 17882 17883 win = ctx->current; 17884 layout = win->layout; 17885 layout->row.item = rect; 17886 } 17887 NK_API struct nk_rect 17888 nk_layout_space_bounds(struct nk_context *ctx) 17889 { 17890 struct nk_rect ret; 17891 struct nk_window *win; 17892 struct nk_panel *layout; 17893 17894 NK_ASSERT(ctx); 17895 NK_ASSERT(ctx->current); 17896 NK_ASSERT(ctx->current->layout); 17897 win = ctx->current; 17898 layout = win->layout; 17899 17900 ret.x = layout->clip.x; 17901 ret.y = layout->clip.y; 17902 ret.w = layout->clip.w; 17903 ret.h = layout->row.height; 17904 return ret; 17905 } 17906 NK_API struct nk_rect 17907 nk_layout_widget_bounds(struct nk_context *ctx) 17908 { 17909 struct nk_rect ret; 17910 struct nk_window *win; 17911 struct nk_panel *layout; 17912 17913 NK_ASSERT(ctx); 17914 NK_ASSERT(ctx->current); 17915 NK_ASSERT(ctx->current->layout); 17916 win = ctx->current; 17917 layout = win->layout; 17918 17919 ret.x = layout->at_x; 17920 ret.y = layout->at_y; 17921 ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0); 17922 ret.h = layout->row.height; 17923 return ret; 17924 } 17925 NK_API struct nk_vec2 17926 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret) 17927 { 17928 struct nk_window *win; 17929 struct nk_panel *layout; 17930 17931 NK_ASSERT(ctx); 17932 NK_ASSERT(ctx->current); 17933 NK_ASSERT(ctx->current->layout); 17934 win = ctx->current; 17935 layout = win->layout; 17936 17937 ret.x += layout->at_x - (float)*layout->offset_x; 17938 ret.y += layout->at_y - (float)*layout->offset_y; 17939 return ret; 17940 } 17941 NK_API struct nk_vec2 17942 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret) 17943 { 17944 struct nk_window *win; 17945 struct nk_panel *layout; 17946 17947 NK_ASSERT(ctx); 17948 NK_ASSERT(ctx->current); 17949 NK_ASSERT(ctx->current->layout); 17950 win = ctx->current; 17951 layout = win->layout; 17952 17953 ret.x += -layout->at_x + (float)*layout->offset_x; 17954 ret.y += -layout->at_y + (float)*layout->offset_y; 17955 return ret; 17956 } 17957 NK_API struct nk_rect 17958 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret) 17959 { 17960 struct nk_window *win; 17961 struct nk_panel *layout; 17962 17963 NK_ASSERT(ctx); 17964 NK_ASSERT(ctx->current); 17965 NK_ASSERT(ctx->current->layout); 17966 win = ctx->current; 17967 layout = win->layout; 17968 17969 ret.x += layout->at_x - (float)*layout->offset_x; 17970 ret.y += layout->at_y - (float)*layout->offset_y; 17971 return ret; 17972 } 17973 NK_API struct nk_rect 17974 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret) 17975 { 17976 struct nk_window *win; 17977 struct nk_panel *layout; 17978 17979 NK_ASSERT(ctx); 17980 NK_ASSERT(ctx->current); 17981 NK_ASSERT(ctx->current->layout); 17982 win = ctx->current; 17983 layout = win->layout; 17984 17985 ret.x += -layout->at_x + (float)*layout->offset_x; 17986 ret.y += -layout->at_y + (float)*layout->offset_y; 17987 return ret; 17988 } 17989 NK_LIB void 17990 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win) 17991 { 17992 struct nk_panel *layout = win->layout; 17993 struct nk_vec2 spacing = ctx->style.window.spacing; 17994 const float row_height = layout->row.height - spacing.y; 17995 nk_panel_layout(ctx, win, row_height, layout->row.columns); 17996 } 17997 NK_LIB void 17998 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, 17999 struct nk_window *win, int modify) 18000 { 18001 struct nk_panel *layout; 18002 const struct nk_style *style; 18003 18004 struct nk_vec2 spacing; 18005 struct nk_vec2 padding; 18006 18007 float item_offset = 0; 18008 float item_width = 0; 18009 float item_spacing = 0; 18010 float panel_space = 0; 18011 18012 NK_ASSERT(ctx); 18013 NK_ASSERT(ctx->current); 18014 NK_ASSERT(ctx->current->layout); 18015 if (!ctx || !ctx->current || !ctx->current->layout) 18016 return; 18017 18018 win = ctx->current; 18019 layout = win->layout; 18020 style = &ctx->style; 18021 NK_ASSERT(bounds); 18022 18023 spacing = style->window.spacing; 18024 padding = nk_panel_get_padding(style, layout->type); 18025 panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 18026 layout->bounds.w, layout->row.columns); 18027 18028 /* calculate the width of one item inside the current layout space */ 18029 switch (layout->row.type) { 18030 case NK_LAYOUT_DYNAMIC_FIXED: { 18031 /* scaling fixed size widgets item width */ 18032 item_width = NK_MAX(1.0f,panel_space) / (float)layout->row.columns; 18033 item_offset = (float)layout->row.index * item_width; 18034 item_spacing = (float)layout->row.index * spacing.x; 18035 } break; 18036 case NK_LAYOUT_DYNAMIC_ROW: { 18037 /* scaling single ratio widget width */ 18038 item_width = layout->row.item_width * panel_space; 18039 item_offset = layout->row.item_offset; 18040 item_spacing = 0; 18041 18042 if (modify) { 18043 layout->row.item_offset += item_width + spacing.x; 18044 layout->row.filled += layout->row.item_width; 18045 layout->row.index = 0; 18046 } 18047 } break; 18048 case NK_LAYOUT_DYNAMIC_FREE: { 18049 /* panel width depended free widget placing */ 18050 bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x); 18051 bounds->x -= (float)*layout->offset_x; 18052 bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); 18053 bounds->y -= (float)*layout->offset_y; 18054 bounds->w = layout->bounds.w * layout->row.item.w; 18055 bounds->h = layout->row.height * layout->row.item.h; 18056 return; 18057 } 18058 case NK_LAYOUT_DYNAMIC: { 18059 /* scaling arrays of panel width ratios for every widget */ 18060 float ratio; 18061 NK_ASSERT(layout->row.ratio); 18062 ratio = (layout->row.ratio[layout->row.index] < 0) ? 18063 layout->row.item_width : layout->row.ratio[layout->row.index]; 18064 18065 item_spacing = (float)layout->row.index * spacing.x; 18066 item_width = (ratio * panel_space); 18067 item_offset = layout->row.item_offset; 18068 18069 if (modify) { 18070 layout->row.item_offset += item_width; 18071 layout->row.filled += ratio; 18072 } 18073 } break; 18074 case NK_LAYOUT_STATIC_FIXED: { 18075 /* non-scaling fixed widgets item width */ 18076 item_width = layout->row.item_width; 18077 item_offset = (float)layout->row.index * item_width; 18078 item_spacing = (float)layout->row.index * spacing.x; 18079 } break; 18080 case NK_LAYOUT_STATIC_ROW: { 18081 /* scaling single ratio widget width */ 18082 item_width = layout->row.item_width; 18083 item_offset = layout->row.item_offset; 18084 item_spacing = (float)layout->row.index * spacing.x; 18085 if (modify) layout->row.item_offset += item_width; 18086 } break; 18087 case NK_LAYOUT_STATIC_FREE: { 18088 /* free widget placing */ 18089 bounds->x = layout->at_x + layout->row.item.x; 18090 bounds->w = layout->row.item.w; 18091 if (((bounds->x + bounds->w) > layout->max_x) && modify) 18092 layout->max_x = (bounds->x + bounds->w); 18093 bounds->x -= (float)*layout->offset_x; 18094 bounds->y = layout->at_y + layout->row.item.y; 18095 bounds->y -= (float)*layout->offset_y; 18096 bounds->h = layout->row.item.h; 18097 return; 18098 } 18099 case NK_LAYOUT_STATIC: { 18100 /* non-scaling array of panel pixel width for every widget */ 18101 item_spacing = (float)layout->row.index * spacing.x; 18102 item_width = layout->row.ratio[layout->row.index]; 18103 item_offset = layout->row.item_offset; 18104 if (modify) layout->row.item_offset += item_width; 18105 } break; 18106 case NK_LAYOUT_TEMPLATE: { 18107 /* stretchy row layout with combined dynamic/static widget width*/ 18108 NK_ASSERT(layout->row.index < layout->row.columns); 18109 NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 18110 item_width = layout->row.templates[layout->row.index]; 18111 item_offset = layout->row.item_offset; 18112 item_spacing = (float)layout->row.index * spacing.x; 18113 if (modify) layout->row.item_offset += item_width; 18114 } break; 18115 default: NK_ASSERT(0); break; 18116 }; 18117 18118 /* set the bounds of the newly allocated widget */ 18119 bounds->w = item_width; 18120 bounds->h = layout->row.height - spacing.y; 18121 bounds->y = layout->at_y - (float)*layout->offset_y; 18122 bounds->x = layout->at_x + item_offset + item_spacing + padding.x; 18123 if (((bounds->x + bounds->w) > layout->max_x) && modify) 18124 layout->max_x = bounds->x + bounds->w; 18125 bounds->x -= (float)*layout->offset_x; 18126 } 18127 NK_LIB void 18128 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx) 18129 { 18130 struct nk_window *win; 18131 struct nk_panel *layout; 18132 18133 NK_ASSERT(ctx); 18134 NK_ASSERT(ctx->current); 18135 NK_ASSERT(ctx->current->layout); 18136 if (!ctx || !ctx->current || !ctx->current->layout) 18137 return; 18138 18139 /* check if the end of the row has been hit and begin new row if so */ 18140 win = ctx->current; 18141 layout = win->layout; 18142 if (layout->row.index >= layout->row.columns) 18143 nk_panel_alloc_row(ctx, win); 18144 18145 /* calculate widget position and size */ 18146 nk_layout_widget_space(bounds, ctx, win, nk_true); 18147 layout->row.index++; 18148 } 18149 NK_LIB void 18150 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx) 18151 { 18152 float y; 18153 int index; 18154 struct nk_window *win; 18155 struct nk_panel *layout; 18156 18157 NK_ASSERT(ctx); 18158 NK_ASSERT(ctx->current); 18159 NK_ASSERT(ctx->current->layout); 18160 if (!ctx || !ctx->current || !ctx->current->layout) 18161 return; 18162 18163 win = ctx->current; 18164 layout = win->layout; 18165 y = layout->at_y; 18166 index = layout->row.index; 18167 if (layout->row.index >= layout->row.columns) { 18168 layout->at_y += layout->row.height; 18169 layout->row.index = 0; 18170 } 18171 nk_layout_widget_space(bounds, ctx, win, nk_false); 18172 if (!layout->row.index) { 18173 bounds->x -= layout->row.item_offset; 18174 } 18175 layout->at_y = y; 18176 layout->row.index = index; 18177 } 18178 18179 18180 18181 18182 18183 /* =============================================================== 18184 * 18185 * TREE 18186 * 18187 * ===============================================================*/ 18188 NK_INTERN int 18189 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type, 18190 struct nk_image *img, const char *title, enum nk_collapse_states *state) 18191 { 18192 struct nk_window *win; 18193 struct nk_panel *layout; 18194 const struct nk_style *style; 18195 struct nk_command_buffer *out; 18196 const struct nk_input *in; 18197 const struct nk_style_button *button; 18198 enum nk_symbol_type symbol; 18199 float row_height; 18200 18201 struct nk_vec2 item_spacing; 18202 struct nk_rect header = {0,0,0,0}; 18203 struct nk_rect sym = {0,0,0,0}; 18204 struct nk_text text; 18205 18206 nk_flags ws = 0; 18207 enum nk_widget_layout_states widget_state; 18208 18209 NK_ASSERT(ctx); 18210 NK_ASSERT(ctx->current); 18211 NK_ASSERT(ctx->current->layout); 18212 if (!ctx || !ctx->current || !ctx->current->layout) 18213 return 0; 18214 18215 /* cache some data */ 18216 win = ctx->current; 18217 layout = win->layout; 18218 out = &win->buffer; 18219 style = &ctx->style; 18220 item_spacing = style->window.spacing; 18221 18222 /* calculate header bounds and draw background */ 18223 row_height = style->font->height + 2 * style->tab.padding.y; 18224 nk_layout_set_min_row_height(ctx, row_height); 18225 nk_layout_row_dynamic(ctx, row_height, 1); 18226 nk_layout_reset_min_row_height(ctx); 18227 18228 widget_state = nk_widget(&header, ctx); 18229 if (type == NK_TREE_TAB) { 18230 const struct nk_style_item *background = &style->tab.background; 18231 if (background->type == NK_STYLE_ITEM_IMAGE) { 18232 nk_draw_image(out, header, &background->data.image, nk_white); 18233 text.background = nk_rgba(0,0,0,0); 18234 } else { 18235 text.background = background->data.color; 18236 nk_fill_rect(out, header, 0, style->tab.border_color); 18237 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 18238 style->tab.rounding, background->data.color); 18239 } 18240 } else text.background = style->window.background; 18241 18242 /* update node state */ 18243 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 18244 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 18245 if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT)) 18246 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED; 18247 18248 /* select correct button style */ 18249 if (*state == NK_MAXIMIZED) { 18250 symbol = style->tab.sym_maximize; 18251 if (type == NK_TREE_TAB) 18252 button = &style->tab.tab_maximize_button; 18253 else button = &style->tab.node_maximize_button; 18254 } else { 18255 symbol = style->tab.sym_minimize; 18256 if (type == NK_TREE_TAB) 18257 button = &style->tab.tab_minimize_button; 18258 else button = &style->tab.node_minimize_button; 18259 } 18260 18261 {/* draw triangle button */ 18262 sym.w = sym.h = style->font->height; 18263 sym.y = header.y + style->tab.padding.y; 18264 sym.x = header.x + style->tab.padding.x; 18265 nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, 18266 button, 0, style->font); 18267 18268 if (img) { 18269 /* draw optional image icon */ 18270 sym.x = sym.x + sym.w + 4 * item_spacing.x; 18271 nk_draw_image(&win->buffer, sym, img, nk_white); 18272 sym.w = style->font->height + style->tab.spacing.x;} 18273 } 18274 18275 {/* draw label */ 18276 struct nk_rect label; 18277 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 18278 label.x = sym.x + sym.w + item_spacing.x; 18279 label.y = sym.y; 18280 label.w = header.w - (sym.w + item_spacing.y + style->tab.indent); 18281 label.h = style->font->height; 18282 text.text = style->tab.text; 18283 text.padding = nk_vec2(0,0); 18284 nk_widget_text(out, label, title, nk_strlen(title), &text, 18285 NK_TEXT_LEFT, style->font);} 18286 18287 /* increase x-axis cursor widget position pointer */ 18288 if (*state == NK_MAXIMIZED) { 18289 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 18290 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 18291 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 18292 layout->row.tree_depth++; 18293 return nk_true; 18294 } else return nk_false; 18295 } 18296 NK_INTERN int 18297 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type, 18298 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 18299 const char *hash, int len, int line) 18300 { 18301 struct nk_window *win = ctx->current; 18302 int title_len = 0; 18303 nk_hash tree_hash = 0; 18304 nk_uint *state = 0; 18305 18306 /* retrieve tree state from internal widget state tables */ 18307 if (!hash) { 18308 title_len = (int)nk_strlen(title); 18309 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 18310 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 18311 state = nk_find_value(win, tree_hash); 18312 if (!state) { 18313 state = nk_add_value(ctx, win, tree_hash, 0); 18314 *state = initial_state; 18315 } 18316 return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state); 18317 } 18318 NK_API int 18319 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type, 18320 const char *title, enum nk_collapse_states *state) 18321 { 18322 return nk_tree_state_base(ctx, type, 0, title, state); 18323 } 18324 NK_API int 18325 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type, 18326 struct nk_image img, const char *title, enum nk_collapse_states *state) 18327 { 18328 return nk_tree_state_base(ctx, type, &img, title, state); 18329 } 18330 NK_API void 18331 nk_tree_state_pop(struct nk_context *ctx) 18332 { 18333 struct nk_window *win = 0; 18334 struct nk_panel *layout = 0; 18335 18336 NK_ASSERT(ctx); 18337 NK_ASSERT(ctx->current); 18338 NK_ASSERT(ctx->current->layout); 18339 if (!ctx || !ctx->current || !ctx->current->layout) 18340 return; 18341 18342 win = ctx->current; 18343 layout = win->layout; 18344 layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x; 18345 layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x; 18346 NK_ASSERT(layout->row.tree_depth); 18347 layout->row.tree_depth--; 18348 } 18349 NK_API int 18350 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18351 const char *title, enum nk_collapse_states initial_state, 18352 const char *hash, int len, int line) 18353 { 18354 return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line); 18355 } 18356 NK_API int 18357 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18358 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 18359 const char *hash, int len,int seed) 18360 { 18361 return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed); 18362 } 18363 NK_API void 18364 nk_tree_pop(struct nk_context *ctx) 18365 { 18366 nk_tree_state_pop(ctx); 18367 } 18368 NK_INTERN int 18369 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type, 18370 struct nk_image *img, const char *title, int title_len, 18371 enum nk_collapse_states *state, int *selected) 18372 { 18373 struct nk_window *win; 18374 struct nk_panel *layout; 18375 const struct nk_style *style; 18376 struct nk_command_buffer *out; 18377 const struct nk_input *in; 18378 const struct nk_style_button *button; 18379 enum nk_symbol_type symbol; 18380 float row_height; 18381 struct nk_vec2 padding; 18382 18383 int text_len; 18384 float text_width; 18385 18386 struct nk_vec2 item_spacing; 18387 struct nk_rect header = {0,0,0,0}; 18388 struct nk_rect sym = {0,0,0,0}; 18389 struct nk_text text; 18390 18391 nk_flags ws = 0; 18392 enum nk_widget_layout_states widget_state; 18393 18394 NK_ASSERT(ctx); 18395 NK_ASSERT(ctx->current); 18396 NK_ASSERT(ctx->current->layout); 18397 if (!ctx || !ctx->current || !ctx->current->layout) 18398 return 0; 18399 18400 /* cache some data */ 18401 win = ctx->current; 18402 layout = win->layout; 18403 out = &win->buffer; 18404 style = &ctx->style; 18405 item_spacing = style->window.spacing; 18406 padding = style->selectable.padding; 18407 18408 /* calculate header bounds and draw background */ 18409 row_height = style->font->height + 2 * style->tab.padding.y; 18410 nk_layout_set_min_row_height(ctx, row_height); 18411 nk_layout_row_dynamic(ctx, row_height, 1); 18412 nk_layout_reset_min_row_height(ctx); 18413 18414 widget_state = nk_widget(&header, ctx); 18415 if (type == NK_TREE_TAB) { 18416 const struct nk_style_item *background = &style->tab.background; 18417 if (background->type == NK_STYLE_ITEM_IMAGE) { 18418 nk_draw_image(out, header, &background->data.image, nk_white); 18419 text.background = nk_rgba(0,0,0,0); 18420 } else { 18421 text.background = background->data.color; 18422 nk_fill_rect(out, header, 0, style->tab.border_color); 18423 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 18424 style->tab.rounding, background->data.color); 18425 } 18426 } else text.background = style->window.background; 18427 18428 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 18429 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 18430 18431 /* select correct button style */ 18432 if (*state == NK_MAXIMIZED) { 18433 symbol = style->tab.sym_maximize; 18434 if (type == NK_TREE_TAB) 18435 button = &style->tab.tab_maximize_button; 18436 else button = &style->tab.node_maximize_button; 18437 } else { 18438 symbol = style->tab.sym_minimize; 18439 if (type == NK_TREE_TAB) 18440 button = &style->tab.tab_minimize_button; 18441 else button = &style->tab.node_minimize_button; 18442 } 18443 {/* draw triangle button */ 18444 sym.w = sym.h = style->font->height; 18445 sym.y = header.y + style->tab.padding.y; 18446 sym.x = header.x + style->tab.padding.x; 18447 if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font)) 18448 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;} 18449 18450 /* draw label */ 18451 {nk_flags dummy = 0; 18452 struct nk_rect label; 18453 /* calculate size of the text and tooltip */ 18454 text_len = nk_strlen(title); 18455 text_width = style->font->width(style->font->userdata, style->font->height, title, text_len); 18456 text_width += (4 * padding.x); 18457 18458 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 18459 label.x = sym.x + sym.w + item_spacing.x; 18460 label.y = sym.y; 18461 label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width); 18462 label.h = style->font->height; 18463 18464 if (img) { 18465 nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 18466 selected, img, &style->selectable, in, style->font); 18467 } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 18468 selected, &style->selectable, in, style->font); 18469 } 18470 /* increase x-axis cursor widget position pointer */ 18471 if (*state == NK_MAXIMIZED) { 18472 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 18473 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 18474 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 18475 layout->row.tree_depth++; 18476 return nk_true; 18477 } else return nk_false; 18478 } 18479 NK_INTERN int 18480 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type, 18481 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 18482 int *selected, const char *hash, int len, int line) 18483 { 18484 struct nk_window *win = ctx->current; 18485 int title_len = 0; 18486 nk_hash tree_hash = 0; 18487 nk_uint *state = 0; 18488 18489 /* retrieve tree state from internal widget state tables */ 18490 if (!hash) { 18491 title_len = (int)nk_strlen(title); 18492 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 18493 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 18494 state = nk_find_value(win, tree_hash); 18495 if (!state) { 18496 state = nk_add_value(ctx, win, tree_hash, 0); 18497 *state = initial_state; 18498 } return nk_tree_element_image_push_hashed_base(ctx, type, img, title, 18499 nk_strlen(title), (enum nk_collapse_states*)state, selected); 18500 } 18501 NK_API int 18502 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18503 const char *title, enum nk_collapse_states initial_state, 18504 int *selected, const char *hash, int len, int seed) 18505 { 18506 return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed); 18507 } 18508 NK_API int 18509 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18510 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 18511 int *selected, const char *hash, int len,int seed) 18512 { 18513 return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed); 18514 } 18515 NK_API void 18516 nk_tree_element_pop(struct nk_context *ctx) 18517 { 18518 nk_tree_state_pop(ctx); 18519 } 18520 18521 18522 18523 18524 18525 /* =============================================================== 18526 * 18527 * GROUP 18528 * 18529 * ===============================================================*/ 18530 NK_API int 18531 nk_group_scrolled_offset_begin(struct nk_context *ctx, 18532 nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags) 18533 { 18534 struct nk_rect bounds; 18535 struct nk_window panel; 18536 struct nk_window *win; 18537 18538 win = ctx->current; 18539 nk_panel_alloc_space(&bounds, ctx); 18540 {const struct nk_rect *c = &win->layout->clip; 18541 if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) && 18542 !(flags & NK_WINDOW_MOVABLE)) { 18543 return 0; 18544 }} 18545 if (win->flags & NK_WINDOW_ROM) 18546 flags |= NK_WINDOW_ROM; 18547 18548 /* initialize a fake window to create the panel from */ 18549 nk_zero(&panel, sizeof(panel)); 18550 panel.bounds = bounds; 18551 panel.flags = flags; 18552 panel.scrollbar.x = *x_offset; 18553 panel.scrollbar.y = *y_offset; 18554 panel.buffer = win->buffer; 18555 panel.layout = (struct nk_panel*)nk_create_panel(ctx); 18556 ctx->current = &panel; 18557 nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP); 18558 18559 win->buffer = panel.buffer; 18560 win->buffer.clip = panel.layout->clip; 18561 panel.layout->offset_x = x_offset; 18562 panel.layout->offset_y = y_offset; 18563 panel.layout->parent = win->layout; 18564 win->layout = panel.layout; 18565 18566 ctx->current = win; 18567 if ((panel.layout->flags & NK_WINDOW_CLOSED) || 18568 (panel.layout->flags & NK_WINDOW_MINIMIZED)) 18569 { 18570 nk_flags f = panel.layout->flags; 18571 nk_group_scrolled_end(ctx); 18572 if (f & NK_WINDOW_CLOSED) 18573 return NK_WINDOW_CLOSED; 18574 if (f & NK_WINDOW_MINIMIZED) 18575 return NK_WINDOW_MINIMIZED; 18576 } 18577 return 1; 18578 } 18579 NK_API void 18580 nk_group_scrolled_end(struct nk_context *ctx) 18581 { 18582 struct nk_window *win; 18583 struct nk_panel *parent; 18584 struct nk_panel *g; 18585 18586 struct nk_rect clip; 18587 struct nk_window pan; 18588 struct nk_vec2 panel_padding; 18589 18590 NK_ASSERT(ctx); 18591 NK_ASSERT(ctx->current); 18592 if (!ctx || !ctx->current) 18593 return; 18594 18595 /* make sure nk_group_begin was called correctly */ 18596 NK_ASSERT(ctx->current); 18597 win = ctx->current; 18598 NK_ASSERT(win->layout); 18599 g = win->layout; 18600 NK_ASSERT(g->parent); 18601 parent = g->parent; 18602 18603 /* dummy window */ 18604 nk_zero_struct(pan); 18605 panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP); 18606 pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h); 18607 pan.bounds.x = g->bounds.x - panel_padding.x; 18608 pan.bounds.w = g->bounds.w + 2 * panel_padding.x; 18609 pan.bounds.h = g->bounds.h + g->header_height + g->menu.h; 18610 if (g->flags & NK_WINDOW_BORDER) { 18611 pan.bounds.x -= g->border; 18612 pan.bounds.y -= g->border; 18613 pan.bounds.w += 2*g->border; 18614 pan.bounds.h += 2*g->border; 18615 } 18616 if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) { 18617 pan.bounds.w += ctx->style.window.scrollbar_size.x; 18618 pan.bounds.h += ctx->style.window.scrollbar_size.y; 18619 } 18620 pan.scrollbar.x = *g->offset_x; 18621 pan.scrollbar.y = *g->offset_y; 18622 pan.flags = g->flags; 18623 pan.buffer = win->buffer; 18624 pan.layout = g; 18625 pan.parent = win; 18626 ctx->current = &pan; 18627 18628 /* make sure group has correct clipping rectangle */ 18629 nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y, 18630 pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x); 18631 nk_push_scissor(&pan.buffer, clip); 18632 nk_end(ctx); 18633 18634 win->buffer = pan.buffer; 18635 nk_push_scissor(&win->buffer, parent->clip); 18636 ctx->current = win; 18637 win->layout = parent; 18638 g->bounds = pan.bounds; 18639 return; 18640 } 18641 NK_API int 18642 nk_group_scrolled_begin(struct nk_context *ctx, 18643 struct nk_scroll *scroll, const char *title, nk_flags flags) 18644 { 18645 return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags); 18646 } 18647 NK_API int 18648 nk_group_begin_titled(struct nk_context *ctx, const char *id, 18649 const char *title, nk_flags flags) 18650 { 18651 int id_len; 18652 nk_hash id_hash; 18653 struct nk_window *win; 18654 nk_uint *x_offset; 18655 nk_uint *y_offset; 18656 18657 NK_ASSERT(ctx); 18658 NK_ASSERT(id); 18659 NK_ASSERT(ctx->current); 18660 NK_ASSERT(ctx->current->layout); 18661 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18662 return 0; 18663 18664 /* find persistent group scrollbar value */ 18665 win = ctx->current; 18666 id_len = (int)nk_strlen(id); 18667 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18668 x_offset = nk_find_value(win, id_hash); 18669 if (!x_offset) { 18670 x_offset = nk_add_value(ctx, win, id_hash, 0); 18671 y_offset = nk_add_value(ctx, win, id_hash+1, 0); 18672 18673 NK_ASSERT(x_offset); 18674 NK_ASSERT(y_offset); 18675 if (!x_offset || !y_offset) return 0; 18676 *x_offset = *y_offset = 0; 18677 } else y_offset = nk_find_value(win, id_hash+1); 18678 return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 18679 } 18680 NK_API int 18681 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags) 18682 { 18683 return nk_group_begin_titled(ctx, title, title, flags); 18684 } 18685 NK_API void 18686 nk_group_end(struct nk_context *ctx) 18687 { 18688 nk_group_scrolled_end(ctx); 18689 } 18690 18691 18692 18693 18694 18695 /* =============================================================== 18696 * 18697 * LIST VIEW 18698 * 18699 * ===============================================================*/ 18700 NK_API int 18701 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view, 18702 const char *title, nk_flags flags, int row_height, int row_count) 18703 { 18704 int title_len; 18705 nk_hash title_hash; 18706 nk_uint *x_offset; 18707 nk_uint *y_offset; 18708 18709 int result; 18710 struct nk_window *win; 18711 struct nk_panel *layout; 18712 const struct nk_style *style; 18713 struct nk_vec2 item_spacing; 18714 18715 NK_ASSERT(ctx); 18716 NK_ASSERT(view); 18717 NK_ASSERT(title); 18718 if (!ctx || !view || !title) return 0; 18719 18720 win = ctx->current; 18721 style = &ctx->style; 18722 item_spacing = style->window.spacing; 18723 row_height += NK_MAX(0, (int)item_spacing.y); 18724 18725 /* find persistent list view scrollbar offset */ 18726 title_len = (int)nk_strlen(title); 18727 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); 18728 x_offset = nk_find_value(win, title_hash); 18729 if (!x_offset) { 18730 x_offset = nk_add_value(ctx, win, title_hash, 0); 18731 y_offset = nk_add_value(ctx, win, title_hash+1, 0); 18732 18733 NK_ASSERT(x_offset); 18734 NK_ASSERT(y_offset); 18735 if (!x_offset || !y_offset) return 0; 18736 *x_offset = *y_offset = 0; 18737 } else y_offset = nk_find_value(win, title_hash+1); 18738 view->scroll_value = *y_offset; 18739 view->scroll_pointer = y_offset; 18740 18741 *y_offset = 0; 18742 result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 18743 win = ctx->current; 18744 layout = win->layout; 18745 18746 view->total_height = row_height * NK_MAX(row_count,1); 18747 view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f); 18748 view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0); 18749 view->count = NK_MIN(view->count, row_count - view->begin); 18750 view->end = view->begin + view->count; 18751 view->ctx = ctx; 18752 return result; 18753 } 18754 NK_API void 18755 nk_list_view_end(struct nk_list_view *view) 18756 { 18757 struct nk_context *ctx; 18758 struct nk_window *win; 18759 struct nk_panel *layout; 18760 18761 NK_ASSERT(view); 18762 NK_ASSERT(view->ctx); 18763 NK_ASSERT(view->scroll_pointer); 18764 if (!view || !view->ctx) return; 18765 18766 ctx = view->ctx; 18767 win = ctx->current; 18768 layout = win->layout; 18769 layout->at_y = layout->bounds.y + (float)view->total_height; 18770 *view->scroll_pointer = *view->scroll_pointer + view->scroll_value; 18771 nk_group_end(view->ctx); 18772 } 18773 18774 18775 18776 18777 18778 /* =============================================================== 18779 * 18780 * WIDGET 18781 * 18782 * ===============================================================*/ 18783 NK_API struct nk_rect 18784 nk_widget_bounds(struct nk_context *ctx) 18785 { 18786 struct nk_rect bounds; 18787 NK_ASSERT(ctx); 18788 NK_ASSERT(ctx->current); 18789 if (!ctx || !ctx->current) 18790 return nk_rect(0,0,0,0); 18791 nk_layout_peek(&bounds, ctx); 18792 return bounds; 18793 } 18794 NK_API struct nk_vec2 18795 nk_widget_position(struct nk_context *ctx) 18796 { 18797 struct nk_rect bounds; 18798 NK_ASSERT(ctx); 18799 NK_ASSERT(ctx->current); 18800 if (!ctx || !ctx->current) 18801 return nk_vec2(0,0); 18802 18803 nk_layout_peek(&bounds, ctx); 18804 return nk_vec2(bounds.x, bounds.y); 18805 } 18806 NK_API struct nk_vec2 18807 nk_widget_size(struct nk_context *ctx) 18808 { 18809 struct nk_rect bounds; 18810 NK_ASSERT(ctx); 18811 NK_ASSERT(ctx->current); 18812 if (!ctx || !ctx->current) 18813 return nk_vec2(0,0); 18814 18815 nk_layout_peek(&bounds, ctx); 18816 return nk_vec2(bounds.w, bounds.h); 18817 } 18818 NK_API float 18819 nk_widget_width(struct nk_context *ctx) 18820 { 18821 struct nk_rect bounds; 18822 NK_ASSERT(ctx); 18823 NK_ASSERT(ctx->current); 18824 if (!ctx || !ctx->current) 18825 return 0; 18826 18827 nk_layout_peek(&bounds, ctx); 18828 return bounds.w; 18829 } 18830 NK_API float 18831 nk_widget_height(struct nk_context *ctx) 18832 { 18833 struct nk_rect bounds; 18834 NK_ASSERT(ctx); 18835 NK_ASSERT(ctx->current); 18836 if (!ctx || !ctx->current) 18837 return 0; 18838 18839 nk_layout_peek(&bounds, ctx); 18840 return bounds.h; 18841 } 18842 NK_API int 18843 nk_widget_is_hovered(struct nk_context *ctx) 18844 { 18845 struct nk_rect c, v; 18846 struct nk_rect bounds; 18847 NK_ASSERT(ctx); 18848 NK_ASSERT(ctx->current); 18849 if (!ctx || !ctx->current || ctx->active != ctx->current) 18850 return 0; 18851 18852 c = ctx->current->layout->clip; 18853 c.x = (float)((int)c.x); 18854 c.y = (float)((int)c.y); 18855 c.w = (float)((int)c.w); 18856 c.h = (float)((int)c.h); 18857 18858 nk_layout_peek(&bounds, ctx); 18859 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 18860 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 18861 return 0; 18862 return nk_input_is_mouse_hovering_rect(&ctx->input, bounds); 18863 } 18864 NK_API int 18865 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn) 18866 { 18867 struct nk_rect c, v; 18868 struct nk_rect bounds; 18869 NK_ASSERT(ctx); 18870 NK_ASSERT(ctx->current); 18871 if (!ctx || !ctx->current || ctx->active != ctx->current) 18872 return 0; 18873 18874 c = ctx->current->layout->clip; 18875 c.x = (float)((int)c.x); 18876 c.y = (float)((int)c.y); 18877 c.w = (float)((int)c.w); 18878 c.h = (float)((int)c.h); 18879 18880 nk_layout_peek(&bounds, ctx); 18881 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 18882 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 18883 return 0; 18884 return nk_input_mouse_clicked(&ctx->input, btn, bounds); 18885 } 18886 NK_API int 18887 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down) 18888 { 18889 struct nk_rect c, v; 18890 struct nk_rect bounds; 18891 NK_ASSERT(ctx); 18892 NK_ASSERT(ctx->current); 18893 if (!ctx || !ctx->current || ctx->active != ctx->current) 18894 return 0; 18895 18896 c = ctx->current->layout->clip; 18897 c.x = (float)((int)c.x); 18898 c.y = (float)((int)c.y); 18899 c.w = (float)((int)c.w); 18900 c.h = (float)((int)c.h); 18901 18902 nk_layout_peek(&bounds, ctx); 18903 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 18904 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 18905 return 0; 18906 return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down); 18907 } 18908 NK_API enum nk_widget_layout_states 18909 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx) 18910 { 18911 struct nk_rect c, v; 18912 struct nk_window *win; 18913 struct nk_panel *layout; 18914 const struct nk_input *in; 18915 18916 NK_ASSERT(ctx); 18917 NK_ASSERT(ctx->current); 18918 NK_ASSERT(ctx->current->layout); 18919 if (!ctx || !ctx->current || !ctx->current->layout) 18920 return NK_WIDGET_INVALID; 18921 18922 /* allocate space and check if the widget needs to be updated and drawn */ 18923 nk_panel_alloc_space(bounds, ctx); 18924 win = ctx->current; 18925 layout = win->layout; 18926 in = &ctx->input; 18927 c = layout->clip; 18928 18929 /* if one of these triggers you forgot to add an `if` condition around either 18930 a window, group, popup, combobox or contextual menu `begin` and `end` block. 18931 Example: 18932 if (nk_begin(...) {...} nk_end(...); or 18933 if (nk_group_begin(...) { nk_group_end(...);} */ 18934 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 18935 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 18936 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 18937 18938 /* need to convert to int here to remove floating point errors */ 18939 bounds->x = (float)((int)bounds->x); 18940 bounds->y = (float)((int)bounds->y); 18941 bounds->w = (float)((int)bounds->w); 18942 bounds->h = (float)((int)bounds->h); 18943 18944 c.x = (float)((int)c.x); 18945 c.y = (float)((int)c.y); 18946 c.w = (float)((int)c.w); 18947 c.h = (float)((int)c.h); 18948 18949 nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h); 18950 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h)) 18951 return NK_WIDGET_INVALID; 18952 if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h)) 18953 return NK_WIDGET_ROM; 18954 return NK_WIDGET_VALID; 18955 } 18956 NK_API enum nk_widget_layout_states 18957 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx, 18958 struct nk_vec2 item_padding) 18959 { 18960 /* update the bounds to stand without padding */ 18961 struct nk_window *win; 18962 struct nk_style *style; 18963 struct nk_panel *layout; 18964 enum nk_widget_layout_states state; 18965 struct nk_vec2 panel_padding; 18966 18967 NK_ASSERT(ctx); 18968 NK_ASSERT(ctx->current); 18969 NK_ASSERT(ctx->current->layout); 18970 if (!ctx || !ctx->current || !ctx->current->layout) 18971 return NK_WIDGET_INVALID; 18972 18973 win = ctx->current; 18974 style = &ctx->style; 18975 layout = win->layout; 18976 state = nk_widget(bounds, ctx); 18977 18978 panel_padding = nk_panel_get_padding(style, layout->type); 18979 if (layout->row.index == 1) { 18980 bounds->w += panel_padding.x; 18981 bounds->x -= panel_padding.x; 18982 } else bounds->x -= item_padding.x; 18983 18984 if (layout->row.index == layout->row.columns) 18985 bounds->w += panel_padding.x; 18986 else bounds->w += item_padding.x; 18987 return state; 18988 } 18989 NK_API void 18990 nk_spacing(struct nk_context *ctx, int cols) 18991 { 18992 struct nk_window *win; 18993 struct nk_panel *layout; 18994 struct nk_rect none; 18995 int i, index, rows; 18996 18997 NK_ASSERT(ctx); 18998 NK_ASSERT(ctx->current); 18999 NK_ASSERT(ctx->current->layout); 19000 if (!ctx || !ctx->current || !ctx->current->layout) 19001 return; 19002 19003 /* spacing over row boundaries */ 19004 win = ctx->current; 19005 layout = win->layout; 19006 index = (layout->row.index + cols) % layout->row.columns; 19007 rows = (layout->row.index + cols) / layout->row.columns; 19008 if (rows) { 19009 for (i = 0; i < rows; ++i) 19010 nk_panel_alloc_row(ctx, win); 19011 cols = index; 19012 } 19013 /* non table layout need to allocate space */ 19014 if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED && 19015 layout->row.type != NK_LAYOUT_STATIC_FIXED) { 19016 for (i = 0; i < cols; ++i) 19017 nk_panel_alloc_space(&none, ctx); 19018 } layout->row.index = index; 19019 } 19020 19021 19022 19023 19024 19025 /* =============================================================== 19026 * 19027 * TEXT 19028 * 19029 * ===============================================================*/ 19030 NK_LIB void 19031 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, 19032 const char *string, int len, const struct nk_text *t, 19033 nk_flags a, const struct nk_user_font *f) 19034 { 19035 struct nk_rect label; 19036 float text_width; 19037 19038 NK_ASSERT(o); 19039 NK_ASSERT(t); 19040 if (!o || !t) return; 19041 19042 b.h = NK_MAX(b.h, 2 * t->padding.y); 19043 label.x = 0; label.w = 0; 19044 label.y = b.y + t->padding.y; 19045 label.h = NK_MIN(f->height, b.h - 2 * t->padding.y); 19046 19047 text_width = f->width(f->userdata, f->height, (const char*)string, len); 19048 text_width += (2.0f * t->padding.x); 19049 19050 /* align in x-axis */ 19051 if (a & NK_TEXT_ALIGN_LEFT) { 19052 label.x = b.x + t->padding.x; 19053 label.w = NK_MAX(0, b.w - 2 * t->padding.x); 19054 } else if (a & NK_TEXT_ALIGN_CENTERED) { 19055 label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width); 19056 label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); 19057 label.x = NK_MAX(b.x + t->padding.x, label.x); 19058 label.w = NK_MIN(b.x + b.w, label.x + label.w); 19059 if (label.w >= label.x) label.w -= label.x; 19060 } else if (a & NK_TEXT_ALIGN_RIGHT) { 19061 label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); 19062 label.w = (float)text_width + 2 * t->padding.x; 19063 } else return; 19064 19065 /* align in y-axis */ 19066 if (a & NK_TEXT_ALIGN_MIDDLE) { 19067 label.y = b.y + b.h/2.0f - (float)f->height/2.0f; 19068 label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f)); 19069 } else if (a & NK_TEXT_ALIGN_BOTTOM) { 19070 label.y = b.y + b.h - f->height; 19071 label.h = f->height; 19072 } 19073 nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text); 19074 } 19075 NK_LIB void 19076 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, 19077 const char *string, int len, const struct nk_text *t, 19078 const struct nk_user_font *f) 19079 { 19080 float width; 19081 int glyphs = 0; 19082 int fitting = 0; 19083 int done = 0; 19084 struct nk_rect line; 19085 struct nk_text text; 19086 NK_INTERN nk_rune seperator[] = {' '}; 19087 19088 NK_ASSERT(o); 19089 NK_ASSERT(t); 19090 if (!o || !t) return; 19091 19092 text.padding = nk_vec2(0,0); 19093 text.background = t->background; 19094 text.text = t->text; 19095 19096 b.w = NK_MAX(b.w, 2 * t->padding.x); 19097 b.h = NK_MAX(b.h, 2 * t->padding.y); 19098 b.h = b.h - 2 * t->padding.y; 19099 19100 line.x = b.x + t->padding.x; 19101 line.y = b.y + t->padding.y; 19102 line.w = b.w - 2 * t->padding.x; 19103 line.h = 2 * t->padding.y + f->height; 19104 19105 fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 19106 while (done < len) { 19107 if (!fitting || line.y + line.h >= (b.y + b.h)) break; 19108 nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f); 19109 done += fitting; 19110 line.y += f->height + 2 * t->padding.y; 19111 fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 19112 } 19113 } 19114 NK_API void 19115 nk_text_colored(struct nk_context *ctx, const char *str, int len, 19116 nk_flags alignment, struct nk_color color) 19117 { 19118 struct nk_window *win; 19119 const struct nk_style *style; 19120 19121 struct nk_vec2 item_padding; 19122 struct nk_rect bounds; 19123 struct nk_text text; 19124 19125 NK_ASSERT(ctx); 19126 NK_ASSERT(ctx->current); 19127 NK_ASSERT(ctx->current->layout); 19128 if (!ctx || !ctx->current || !ctx->current->layout) return; 19129 19130 win = ctx->current; 19131 style = &ctx->style; 19132 nk_panel_alloc_space(&bounds, ctx); 19133 item_padding = style->text.padding; 19134 19135 text.padding.x = item_padding.x; 19136 text.padding.y = item_padding.y; 19137 text.background = style->window.background; 19138 text.text = color; 19139 nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font); 19140 } 19141 NK_API void 19142 nk_text_wrap_colored(struct nk_context *ctx, const char *str, 19143 int len, struct nk_color color) 19144 { 19145 struct nk_window *win; 19146 const struct nk_style *style; 19147 19148 struct nk_vec2 item_padding; 19149 struct nk_rect bounds; 19150 struct nk_text text; 19151 19152 NK_ASSERT(ctx); 19153 NK_ASSERT(ctx->current); 19154 NK_ASSERT(ctx->current->layout); 19155 if (!ctx || !ctx->current || !ctx->current->layout) return; 19156 19157 win = ctx->current; 19158 style = &ctx->style; 19159 nk_panel_alloc_space(&bounds, ctx); 19160 item_padding = style->text.padding; 19161 19162 text.padding.x = item_padding.x; 19163 text.padding.y = item_padding.y; 19164 text.background = style->window.background; 19165 text.text = color; 19166 nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font); 19167 } 19168 #ifdef NK_INCLUDE_STANDARD_VARARGS 19169 NK_API void 19170 nk_labelf_colored(struct nk_context *ctx, nk_flags flags, 19171 struct nk_color color, const char *fmt, ...) 19172 { 19173 va_list args; 19174 va_start(args, fmt); 19175 nk_labelfv_colored(ctx, flags, color, fmt, args); 19176 va_end(args); 19177 } 19178 NK_API void 19179 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color, 19180 const char *fmt, ...) 19181 { 19182 va_list args; 19183 va_start(args, fmt); 19184 nk_labelfv_colored_wrap(ctx, color, fmt, args); 19185 va_end(args); 19186 } 19187 NK_API void 19188 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...) 19189 { 19190 va_list args; 19191 va_start(args, fmt); 19192 nk_labelfv(ctx, flags, fmt, args); 19193 va_end(args); 19194 } 19195 NK_API void 19196 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...) 19197 { 19198 va_list args; 19199 va_start(args, fmt); 19200 nk_labelfv_wrap(ctx, fmt, args); 19201 va_end(args); 19202 } 19203 NK_API void 19204 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags, 19205 struct nk_color color, const char *fmt, va_list args) 19206 { 19207 char buf[256]; 19208 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19209 nk_label_colored(ctx, buf, flags, color); 19210 } 19211 19212 NK_API void 19213 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color, 19214 const char *fmt, va_list args) 19215 { 19216 char buf[256]; 19217 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19218 nk_label_colored_wrap(ctx, buf, color); 19219 } 19220 19221 NK_API void 19222 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args) 19223 { 19224 char buf[256]; 19225 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19226 nk_label(ctx, buf, flags); 19227 } 19228 19229 NK_API void 19230 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args) 19231 { 19232 char buf[256]; 19233 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19234 nk_label_wrap(ctx, buf); 19235 } 19236 19237 NK_API void 19238 nk_value_bool(struct nk_context *ctx, const char *prefix, int value) 19239 { 19240 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false")); 19241 } 19242 NK_API void 19243 nk_value_int(struct nk_context *ctx, const char *prefix, int value) 19244 { 19245 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value); 19246 } 19247 NK_API void 19248 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value) 19249 { 19250 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value); 19251 } 19252 NK_API void 19253 nk_value_float(struct nk_context *ctx, const char *prefix, float value) 19254 { 19255 double double_value = (double)value; 19256 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value); 19257 } 19258 NK_API void 19259 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c) 19260 { 19261 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a); 19262 } 19263 NK_API void 19264 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color) 19265 { 19266 double c[4]; nk_color_dv(c, color); 19267 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)", 19268 p, c[0], c[1], c[2], c[3]); 19269 } 19270 NK_API void 19271 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color) 19272 { 19273 char hex[16]; 19274 nk_color_hex_rgba(hex, color); 19275 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex); 19276 } 19277 #endif 19278 NK_API void 19279 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment) 19280 { 19281 NK_ASSERT(ctx); 19282 if (!ctx) return; 19283 nk_text_colored(ctx, str, len, alignment, ctx->style.text.color); 19284 } 19285 NK_API void 19286 nk_text_wrap(struct nk_context *ctx, const char *str, int len) 19287 { 19288 NK_ASSERT(ctx); 19289 if (!ctx) return; 19290 nk_text_wrap_colored(ctx, str, len, ctx->style.text.color); 19291 } 19292 NK_API void 19293 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment) 19294 { 19295 nk_text(ctx, str, nk_strlen(str), alignment); 19296 } 19297 NK_API void 19298 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align, 19299 struct nk_color color) 19300 { 19301 nk_text_colored(ctx, str, nk_strlen(str), align, color); 19302 } 19303 NK_API void 19304 nk_label_wrap(struct nk_context *ctx, const char *str) 19305 { 19306 nk_text_wrap(ctx, str, nk_strlen(str)); 19307 } 19308 NK_API void 19309 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color) 19310 { 19311 nk_text_wrap_colored(ctx, str, nk_strlen(str), color); 19312 } 19313 19314 19315 19316 19317 19318 /* =============================================================== 19319 * 19320 * IMAGE 19321 * 19322 * ===============================================================*/ 19323 NK_API nk_handle 19324 nk_handle_ptr(void *ptr) 19325 { 19326 nk_handle handle = {0}; 19327 handle.ptr = ptr; 19328 return handle; 19329 } 19330 NK_API nk_handle 19331 nk_handle_id(int id) 19332 { 19333 nk_handle handle; 19334 nk_zero_struct(handle); 19335 handle.id = id; 19336 return handle; 19337 } 19338 NK_API struct nk_image 19339 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r) 19340 { 19341 struct nk_image s; 19342 nk_zero(&s, sizeof(s)); 19343 s.handle.ptr = ptr; 19344 s.w = w; s.h = h; 19345 s.region[0] = (unsigned short)r.x; 19346 s.region[1] = (unsigned short)r.y; 19347 s.region[2] = (unsigned short)r.w; 19348 s.region[3] = (unsigned short)r.h; 19349 return s; 19350 } 19351 NK_API struct nk_image 19352 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r) 19353 { 19354 struct nk_image s; 19355 nk_zero(&s, sizeof(s)); 19356 s.handle.id = id; 19357 s.w = w; s.h = h; 19358 s.region[0] = (unsigned short)r.x; 19359 s.region[1] = (unsigned short)r.y; 19360 s.region[2] = (unsigned short)r.w; 19361 s.region[3] = (unsigned short)r.h; 19362 return s; 19363 } 19364 NK_API struct nk_image 19365 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h, 19366 struct nk_rect r) 19367 { 19368 struct nk_image s; 19369 nk_zero(&s, sizeof(s)); 19370 s.handle = handle; 19371 s.w = w; s.h = h; 19372 s.region[0] = (unsigned short)r.x; 19373 s.region[1] = (unsigned short)r.y; 19374 s.region[2] = (unsigned short)r.w; 19375 s.region[3] = (unsigned short)r.h; 19376 return s; 19377 } 19378 NK_API struct nk_image 19379 nk_image_handle(nk_handle handle) 19380 { 19381 struct nk_image s; 19382 nk_zero(&s, sizeof(s)); 19383 s.handle = handle; 19384 s.w = 0; s.h = 0; 19385 s.region[0] = 0; 19386 s.region[1] = 0; 19387 s.region[2] = 0; 19388 s.region[3] = 0; 19389 return s; 19390 } 19391 NK_API struct nk_image 19392 nk_image_ptr(void *ptr) 19393 { 19394 struct nk_image s; 19395 nk_zero(&s, sizeof(s)); 19396 NK_ASSERT(ptr); 19397 s.handle.ptr = ptr; 19398 s.w = 0; s.h = 0; 19399 s.region[0] = 0; 19400 s.region[1] = 0; 19401 s.region[2] = 0; 19402 s.region[3] = 0; 19403 return s; 19404 } 19405 NK_API struct nk_image 19406 nk_image_id(int id) 19407 { 19408 struct nk_image s; 19409 nk_zero(&s, sizeof(s)); 19410 s.handle.id = id; 19411 s.w = 0; s.h = 0; 19412 s.region[0] = 0; 19413 s.region[1] = 0; 19414 s.region[2] = 0; 19415 s.region[3] = 0; 19416 return s; 19417 } 19418 NK_API int 19419 nk_image_is_subimage(const struct nk_image* img) 19420 { 19421 NK_ASSERT(img); 19422 return !(img->w == 0 && img->h == 0); 19423 } 19424 NK_API void 19425 nk_image(struct nk_context *ctx, struct nk_image img) 19426 { 19427 struct nk_window *win; 19428 struct nk_rect bounds; 19429 19430 NK_ASSERT(ctx); 19431 NK_ASSERT(ctx->current); 19432 NK_ASSERT(ctx->current->layout); 19433 if (!ctx || !ctx->current || !ctx->current->layout) return; 19434 19435 win = ctx->current; 19436 if (!nk_widget(&bounds, ctx)) return; 19437 nk_draw_image(&win->buffer, bounds, &img, nk_white); 19438 } 19439 NK_API void 19440 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col) 19441 { 19442 struct nk_window *win; 19443 struct nk_rect bounds; 19444 19445 NK_ASSERT(ctx); 19446 NK_ASSERT(ctx->current); 19447 NK_ASSERT(ctx->current->layout); 19448 if (!ctx || !ctx->current || !ctx->current->layout) return; 19449 19450 win = ctx->current; 19451 if (!nk_widget(&bounds, ctx)) return; 19452 nk_draw_image(&win->buffer, bounds, &img, col); 19453 } 19454 19455 19456 19457 19458 19459 /* ============================================================== 19460 * 19461 * BUTTON 19462 * 19463 * ===============================================================*/ 19464 NK_LIB void 19465 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, 19466 struct nk_rect content, struct nk_color background, struct nk_color foreground, 19467 float border_width, const struct nk_user_font *font) 19468 { 19469 switch (type) { 19470 case NK_SYMBOL_X: 19471 case NK_SYMBOL_UNDERSCORE: 19472 case NK_SYMBOL_PLUS: 19473 case NK_SYMBOL_MINUS: { 19474 /* single character text symbol */ 19475 const char *X = (type == NK_SYMBOL_X) ? "x": 19476 (type == NK_SYMBOL_UNDERSCORE) ? "_": 19477 (type == NK_SYMBOL_PLUS) ? "+": "-"; 19478 struct nk_text text; 19479 text.padding = nk_vec2(0,0); 19480 text.background = background; 19481 text.text = foreground; 19482 nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font); 19483 } break; 19484 case NK_SYMBOL_CIRCLE_SOLID: 19485 case NK_SYMBOL_CIRCLE_OUTLINE: 19486 case NK_SYMBOL_RECT_SOLID: 19487 case NK_SYMBOL_RECT_OUTLINE: { 19488 /* simple empty/filled shapes */ 19489 if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) { 19490 nk_fill_rect(out, content, 0, foreground); 19491 if (type == NK_SYMBOL_RECT_OUTLINE) 19492 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background); 19493 } else { 19494 nk_fill_circle(out, content, foreground); 19495 if (type == NK_SYMBOL_CIRCLE_OUTLINE) 19496 nk_fill_circle(out, nk_shrink_rect(content, 1), background); 19497 } 19498 } break; 19499 case NK_SYMBOL_TRIANGLE_UP: 19500 case NK_SYMBOL_TRIANGLE_DOWN: 19501 case NK_SYMBOL_TRIANGLE_LEFT: 19502 case NK_SYMBOL_TRIANGLE_RIGHT: { 19503 enum nk_heading heading; 19504 struct nk_vec2 points[3]; 19505 heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT : 19506 (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT: 19507 (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN; 19508 nk_triangle_from_direction(points, content, 0, 0, heading); 19509 nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, 19510 points[2].x, points[2].y, foreground); 19511 } break; 19512 default: 19513 case NK_SYMBOL_NONE: 19514 case NK_SYMBOL_MAX: break; 19515 } 19516 } 19517 NK_LIB int 19518 nk_button_behavior(nk_flags *state, struct nk_rect r, 19519 const struct nk_input *i, enum nk_button_behavior behavior) 19520 { 19521 int ret = 0; 19522 nk_widget_state_reset(state); 19523 if (!i) return 0; 19524 if (nk_input_is_mouse_hovering_rect(i, r)) { 19525 *state = NK_WIDGET_STATE_HOVERED; 19526 if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT)) 19527 *state = NK_WIDGET_STATE_ACTIVE; 19528 if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) { 19529 ret = (behavior != NK_BUTTON_DEFAULT) ? 19530 nk_input_is_mouse_down(i, NK_BUTTON_LEFT): 19531 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 19532 nk_input_is_mouse_released(i, NK_BUTTON_LEFT); 19533 #else 19534 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT); 19535 #endif 19536 } 19537 } 19538 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r)) 19539 *state |= NK_WIDGET_STATE_ENTERED; 19540 else if (nk_input_is_mouse_prev_hovering_rect(i, r)) 19541 *state |= NK_WIDGET_STATE_LEFT; 19542 return ret; 19543 } 19544 NK_LIB const struct nk_style_item* 19545 nk_draw_button(struct nk_command_buffer *out, 19546 const struct nk_rect *bounds, nk_flags state, 19547 const struct nk_style_button *style) 19548 { 19549 const struct nk_style_item *background; 19550 if (state & NK_WIDGET_STATE_HOVER) 19551 background = &style->hover; 19552 else if (state & NK_WIDGET_STATE_ACTIVED) 19553 background = &style->active; 19554 else background = &style->normal; 19555 19556 if (background->type == NK_STYLE_ITEM_IMAGE) { 19557 nk_draw_image(out, *bounds, &background->data.image, nk_white); 19558 } else { 19559 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 19560 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 19561 } 19562 return background; 19563 } 19564 NK_LIB int 19565 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, 19566 const struct nk_style_button *style, const struct nk_input *in, 19567 enum nk_button_behavior behavior, struct nk_rect *content) 19568 { 19569 struct nk_rect bounds; 19570 NK_ASSERT(style); 19571 NK_ASSERT(state); 19572 NK_ASSERT(out); 19573 if (!out || !style) 19574 return nk_false; 19575 19576 /* calculate button content space */ 19577 content->x = r.x + style->padding.x + style->border + style->rounding; 19578 content->y = r.y + style->padding.y + style->border + style->rounding; 19579 content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2); 19580 content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2); 19581 19582 /* execute button behavior */ 19583 bounds.x = r.x - style->touch_padding.x; 19584 bounds.y = r.y - style->touch_padding.y; 19585 bounds.w = r.w + 2 * style->touch_padding.x; 19586 bounds.h = r.h + 2 * style->touch_padding.y; 19587 return nk_button_behavior(state, bounds, in, behavior); 19588 } 19589 NK_LIB void 19590 nk_draw_button_text(struct nk_command_buffer *out, 19591 const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, 19592 const struct nk_style_button *style, const char *txt, int len, 19593 nk_flags text_alignment, const struct nk_user_font *font) 19594 { 19595 struct nk_text text; 19596 const struct nk_style_item *background; 19597 background = nk_draw_button(out, bounds, state, style); 19598 19599 /* select correct colors/images */ 19600 if (background->type == NK_STYLE_ITEM_COLOR) 19601 text.background = background->data.color; 19602 else text.background = style->text_background; 19603 if (state & NK_WIDGET_STATE_HOVER) 19604 text.text = style->text_hover; 19605 else if (state & NK_WIDGET_STATE_ACTIVED) 19606 text.text = style->text_active; 19607 else text.text = style->text_normal; 19608 19609 text.padding = nk_vec2(0,0); 19610 nk_widget_text(out, *content, txt, len, &text, text_alignment, font); 19611 } 19612 NK_LIB int 19613 nk_do_button_text(nk_flags *state, 19614 struct nk_command_buffer *out, struct nk_rect bounds, 19615 const char *string, int len, nk_flags align, enum nk_button_behavior behavior, 19616 const struct nk_style_button *style, const struct nk_input *in, 19617 const struct nk_user_font *font) 19618 { 19619 struct nk_rect content; 19620 int ret = nk_false; 19621 19622 NK_ASSERT(state); 19623 NK_ASSERT(style); 19624 NK_ASSERT(out); 19625 NK_ASSERT(string); 19626 NK_ASSERT(font); 19627 if (!out || !style || !font || !string) 19628 return nk_false; 19629 19630 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19631 if (style->draw_begin) style->draw_begin(out, style->userdata); 19632 nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font); 19633 if (style->draw_end) style->draw_end(out, style->userdata); 19634 return ret; 19635 } 19636 NK_LIB void 19637 nk_draw_button_symbol(struct nk_command_buffer *out, 19638 const struct nk_rect *bounds, const struct nk_rect *content, 19639 nk_flags state, const struct nk_style_button *style, 19640 enum nk_symbol_type type, const struct nk_user_font *font) 19641 { 19642 struct nk_color sym, bg; 19643 const struct nk_style_item *background; 19644 19645 /* select correct colors/images */ 19646 background = nk_draw_button(out, bounds, state, style); 19647 if (background->type == NK_STYLE_ITEM_COLOR) 19648 bg = background->data.color; 19649 else bg = style->text_background; 19650 19651 if (state & NK_WIDGET_STATE_HOVER) 19652 sym = style->text_hover; 19653 else if (state & NK_WIDGET_STATE_ACTIVED) 19654 sym = style->text_active; 19655 else sym = style->text_normal; 19656 nk_draw_symbol(out, type, *content, bg, sym, 1, font); 19657 } 19658 NK_LIB int 19659 nk_do_button_symbol(nk_flags *state, 19660 struct nk_command_buffer *out, struct nk_rect bounds, 19661 enum nk_symbol_type symbol, enum nk_button_behavior behavior, 19662 const struct nk_style_button *style, const struct nk_input *in, 19663 const struct nk_user_font *font) 19664 { 19665 int ret; 19666 struct nk_rect content; 19667 19668 NK_ASSERT(state); 19669 NK_ASSERT(style); 19670 NK_ASSERT(font); 19671 NK_ASSERT(out); 19672 if (!out || !style || !font || !state) 19673 return nk_false; 19674 19675 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19676 if (style->draw_begin) style->draw_begin(out, style->userdata); 19677 nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); 19678 if (style->draw_end) style->draw_end(out, style->userdata); 19679 return ret; 19680 } 19681 NK_LIB void 19682 nk_draw_button_image(struct nk_command_buffer *out, 19683 const struct nk_rect *bounds, const struct nk_rect *content, 19684 nk_flags state, const struct nk_style_button *style, const struct nk_image *img) 19685 { 19686 nk_draw_button(out, bounds, state, style); 19687 nk_draw_image(out, *content, img, nk_white); 19688 } 19689 NK_LIB int 19690 nk_do_button_image(nk_flags *state, 19691 struct nk_command_buffer *out, struct nk_rect bounds, 19692 struct nk_image img, enum nk_button_behavior b, 19693 const struct nk_style_button *style, const struct nk_input *in) 19694 { 19695 int ret; 19696 struct nk_rect content; 19697 19698 NK_ASSERT(state); 19699 NK_ASSERT(style); 19700 NK_ASSERT(out); 19701 if (!out || !style || !state) 19702 return nk_false; 19703 19704 ret = nk_do_button(state, out, bounds, style, in, b, &content); 19705 content.x += style->image_padding.x; 19706 content.y += style->image_padding.y; 19707 content.w -= 2 * style->image_padding.x; 19708 content.h -= 2 * style->image_padding.y; 19709 19710 if (style->draw_begin) style->draw_begin(out, style->userdata); 19711 nk_draw_button_image(out, &bounds, &content, *state, style, &img); 19712 if (style->draw_end) style->draw_end(out, style->userdata); 19713 return ret; 19714 } 19715 NK_LIB void 19716 nk_draw_button_text_symbol(struct nk_command_buffer *out, 19717 const struct nk_rect *bounds, const struct nk_rect *label, 19718 const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, 19719 const char *str, int len, enum nk_symbol_type type, 19720 const struct nk_user_font *font) 19721 { 19722 struct nk_color sym; 19723 struct nk_text text; 19724 const struct nk_style_item *background; 19725 19726 /* select correct background colors/images */ 19727 background = nk_draw_button(out, bounds, state, style); 19728 if (background->type == NK_STYLE_ITEM_COLOR) 19729 text.background = background->data.color; 19730 else text.background = style->text_background; 19731 19732 /* select correct text colors */ 19733 if (state & NK_WIDGET_STATE_HOVER) { 19734 sym = style->text_hover; 19735 text.text = style->text_hover; 19736 } else if (state & NK_WIDGET_STATE_ACTIVED) { 19737 sym = style->text_active; 19738 text.text = style->text_active; 19739 } else { 19740 sym = style->text_normal; 19741 text.text = style->text_normal; 19742 } 19743 19744 text.padding = nk_vec2(0,0); 19745 nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); 19746 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 19747 } 19748 NK_LIB int 19749 nk_do_button_text_symbol(nk_flags *state, 19750 struct nk_command_buffer *out, struct nk_rect bounds, 19751 enum nk_symbol_type symbol, const char *str, int len, nk_flags align, 19752 enum nk_button_behavior behavior, const struct nk_style_button *style, 19753 const struct nk_user_font *font, const struct nk_input *in) 19754 { 19755 int ret; 19756 struct nk_rect tri = {0,0,0,0}; 19757 struct nk_rect content; 19758 19759 NK_ASSERT(style); 19760 NK_ASSERT(out); 19761 NK_ASSERT(font); 19762 if (!out || !style || !font) 19763 return nk_false; 19764 19765 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19766 tri.y = content.y + (content.h/2) - font->height/2; 19767 tri.w = font->height; tri.h = font->height; 19768 if (align & NK_TEXT_ALIGN_LEFT) { 19769 tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); 19770 tri.x = NK_MAX(tri.x, 0); 19771 } else tri.x = content.x + 2 * style->padding.x; 19772 19773 /* draw button */ 19774 if (style->draw_begin) style->draw_begin(out, style->userdata); 19775 nk_draw_button_text_symbol(out, &bounds, &content, &tri, 19776 *state, style, str, len, symbol, font); 19777 if (style->draw_end) style->draw_end(out, style->userdata); 19778 return ret; 19779 } 19780 NK_LIB void 19781 nk_draw_button_text_image(struct nk_command_buffer *out, 19782 const struct nk_rect *bounds, const struct nk_rect *label, 19783 const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, 19784 const char *str, int len, const struct nk_user_font *font, 19785 const struct nk_image *img) 19786 { 19787 struct nk_text text; 19788 const struct nk_style_item *background; 19789 background = nk_draw_button(out, bounds, state, style); 19790 19791 /* select correct colors */ 19792 if (background->type == NK_STYLE_ITEM_COLOR) 19793 text.background = background->data.color; 19794 else text.background = style->text_background; 19795 if (state & NK_WIDGET_STATE_HOVER) 19796 text.text = style->text_hover; 19797 else if (state & NK_WIDGET_STATE_ACTIVED) 19798 text.text = style->text_active; 19799 else text.text = style->text_normal; 19800 19801 text.padding = nk_vec2(0,0); 19802 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 19803 nk_draw_image(out, *image, img, nk_white); 19804 } 19805 NK_LIB int 19806 nk_do_button_text_image(nk_flags *state, 19807 struct nk_command_buffer *out, struct nk_rect bounds, 19808 struct nk_image img, const char* str, int len, nk_flags align, 19809 enum nk_button_behavior behavior, const struct nk_style_button *style, 19810 const struct nk_user_font *font, const struct nk_input *in) 19811 { 19812 int ret; 19813 struct nk_rect icon; 19814 struct nk_rect content; 19815 19816 NK_ASSERT(style); 19817 NK_ASSERT(state); 19818 NK_ASSERT(font); 19819 NK_ASSERT(out); 19820 if (!out || !font || !style || !str) 19821 return nk_false; 19822 19823 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19824 icon.y = bounds.y + style->padding.y; 19825 icon.w = icon.h = bounds.h - 2 * style->padding.y; 19826 if (align & NK_TEXT_ALIGN_LEFT) { 19827 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 19828 icon.x = NK_MAX(icon.x, 0); 19829 } else icon.x = bounds.x + 2 * style->padding.x; 19830 19831 icon.x += style->image_padding.x; 19832 icon.y += style->image_padding.y; 19833 icon.w -= 2 * style->image_padding.x; 19834 icon.h -= 2 * style->image_padding.y; 19835 19836 if (style->draw_begin) style->draw_begin(out, style->userdata); 19837 nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img); 19838 if (style->draw_end) style->draw_end(out, style->userdata); 19839 return ret; 19840 } 19841 NK_API void 19842 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 19843 { 19844 NK_ASSERT(ctx); 19845 if (!ctx) return; 19846 ctx->button_behavior = behavior; 19847 } 19848 NK_API int 19849 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 19850 { 19851 struct nk_config_stack_button_behavior *button_stack; 19852 struct nk_config_stack_button_behavior_element *element; 19853 19854 NK_ASSERT(ctx); 19855 if (!ctx) return 0; 19856 19857 button_stack = &ctx->stacks.button_behaviors; 19858 NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements)); 19859 if (button_stack->head >= (int)NK_LEN(button_stack->elements)) 19860 return 0; 19861 19862 element = &button_stack->elements[button_stack->head++]; 19863 element->address = &ctx->button_behavior; 19864 element->old_value = ctx->button_behavior; 19865 ctx->button_behavior = behavior; 19866 return 1; 19867 } 19868 NK_API int 19869 nk_button_pop_behavior(struct nk_context *ctx) 19870 { 19871 struct nk_config_stack_button_behavior *button_stack; 19872 struct nk_config_stack_button_behavior_element *element; 19873 19874 NK_ASSERT(ctx); 19875 if (!ctx) return 0; 19876 19877 button_stack = &ctx->stacks.button_behaviors; 19878 NK_ASSERT(button_stack->head > 0); 19879 if (button_stack->head < 1) 19880 return 0; 19881 19882 element = &button_stack->elements[--button_stack->head]; 19883 *element->address = element->old_value; 19884 return 1; 19885 } 19886 NK_API int 19887 nk_button_text_styled(struct nk_context *ctx, 19888 const struct nk_style_button *style, const char *title, int len) 19889 { 19890 struct nk_window *win; 19891 struct nk_panel *layout; 19892 const struct nk_input *in; 19893 19894 struct nk_rect bounds; 19895 enum nk_widget_layout_states state; 19896 19897 NK_ASSERT(ctx); 19898 NK_ASSERT(style); 19899 NK_ASSERT(ctx->current); 19900 NK_ASSERT(ctx->current->layout); 19901 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0; 19902 19903 win = ctx->current; 19904 layout = win->layout; 19905 state = nk_widget(&bounds, ctx); 19906 19907 if (!state) return 0; 19908 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 19909 return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 19910 title, len, style->text_alignment, ctx->button_behavior, 19911 style, in, ctx->style.font); 19912 } 19913 NK_API int 19914 nk_button_text(struct nk_context *ctx, const char *title, int len) 19915 { 19916 NK_ASSERT(ctx); 19917 if (!ctx) return 0; 19918 return nk_button_text_styled(ctx, &ctx->style.button, title, len); 19919 } 19920 NK_API int nk_button_label_styled(struct nk_context *ctx, 19921 const struct nk_style_button *style, const char *title) 19922 { 19923 return nk_button_text_styled(ctx, style, title, nk_strlen(title)); 19924 } 19925 NK_API int nk_button_label(struct nk_context *ctx, const char *title) 19926 { 19927 return nk_button_text(ctx, title, nk_strlen(title)); 19928 } 19929 NK_API int 19930 nk_button_color(struct nk_context *ctx, struct nk_color color) 19931 { 19932 struct nk_window *win; 19933 struct nk_panel *layout; 19934 const struct nk_input *in; 19935 struct nk_style_button button; 19936 19937 int ret = 0; 19938 struct nk_rect bounds; 19939 struct nk_rect content; 19940 enum nk_widget_layout_states state; 19941 19942 NK_ASSERT(ctx); 19943 NK_ASSERT(ctx->current); 19944 NK_ASSERT(ctx->current->layout); 19945 if (!ctx || !ctx->current || !ctx->current->layout) 19946 return 0; 19947 19948 win = ctx->current; 19949 layout = win->layout; 19950 19951 state = nk_widget(&bounds, ctx); 19952 if (!state) return 0; 19953 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 19954 19955 button = ctx->style.button; 19956 button.normal = nk_style_item_color(color); 19957 button.hover = nk_style_item_color(color); 19958 button.active = nk_style_item_color(color); 19959 ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds, 19960 &button, in, ctx->button_behavior, &content); 19961 nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); 19962 return ret; 19963 } 19964 NK_API int 19965 nk_button_symbol_styled(struct nk_context *ctx, 19966 const struct nk_style_button *style, enum nk_symbol_type symbol) 19967 { 19968 struct nk_window *win; 19969 struct nk_panel *layout; 19970 const struct nk_input *in; 19971 19972 struct nk_rect bounds; 19973 enum nk_widget_layout_states state; 19974 19975 NK_ASSERT(ctx); 19976 NK_ASSERT(ctx->current); 19977 NK_ASSERT(ctx->current->layout); 19978 if (!ctx || !ctx->current || !ctx->current->layout) 19979 return 0; 19980 19981 win = ctx->current; 19982 layout = win->layout; 19983 state = nk_widget(&bounds, ctx); 19984 if (!state) return 0; 19985 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 19986 return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, 19987 symbol, ctx->button_behavior, style, in, ctx->style.font); 19988 } 19989 NK_API int 19990 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol) 19991 { 19992 NK_ASSERT(ctx); 19993 if (!ctx) return 0; 19994 return nk_button_symbol_styled(ctx, &ctx->style.button, symbol); 19995 } 19996 NK_API int 19997 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style, 19998 struct nk_image img) 19999 { 20000 struct nk_window *win; 20001 struct nk_panel *layout; 20002 const struct nk_input *in; 20003 20004 struct nk_rect bounds; 20005 enum nk_widget_layout_states state; 20006 20007 NK_ASSERT(ctx); 20008 NK_ASSERT(ctx->current); 20009 NK_ASSERT(ctx->current->layout); 20010 if (!ctx || !ctx->current || !ctx->current->layout) 20011 return 0; 20012 20013 win = ctx->current; 20014 layout = win->layout; 20015 20016 state = nk_widget(&bounds, ctx); 20017 if (!state) return 0; 20018 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20019 return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, 20020 img, ctx->button_behavior, style, in); 20021 } 20022 NK_API int 20023 nk_button_image(struct nk_context *ctx, struct nk_image img) 20024 { 20025 NK_ASSERT(ctx); 20026 if (!ctx) return 0; 20027 return nk_button_image_styled(ctx, &ctx->style.button, img); 20028 } 20029 NK_API int 20030 nk_button_symbol_text_styled(struct nk_context *ctx, 20031 const struct nk_style_button *style, enum nk_symbol_type symbol, 20032 const char *text, int len, nk_flags align) 20033 { 20034 struct nk_window *win; 20035 struct nk_panel *layout; 20036 const struct nk_input *in; 20037 20038 struct nk_rect bounds; 20039 enum nk_widget_layout_states state; 20040 20041 NK_ASSERT(ctx); 20042 NK_ASSERT(ctx->current); 20043 NK_ASSERT(ctx->current->layout); 20044 if (!ctx || !ctx->current || !ctx->current->layout) 20045 return 0; 20046 20047 win = ctx->current; 20048 layout = win->layout; 20049 20050 state = nk_widget(&bounds, ctx); 20051 if (!state) return 0; 20052 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20053 return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20054 symbol, text, len, align, ctx->button_behavior, 20055 style, ctx->style.font, in); 20056 } 20057 NK_API int 20058 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 20059 const char* text, int len, nk_flags align) 20060 { 20061 NK_ASSERT(ctx); 20062 if (!ctx) return 0; 20063 return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align); 20064 } 20065 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 20066 const char *label, nk_flags align) 20067 { 20068 return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align); 20069 } 20070 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, 20071 const struct nk_style_button *style, enum nk_symbol_type symbol, 20072 const char *title, nk_flags align) 20073 { 20074 return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align); 20075 } 20076 NK_API int 20077 nk_button_image_text_styled(struct nk_context *ctx, 20078 const struct nk_style_button *style, struct nk_image img, const char *text, 20079 int len, nk_flags align) 20080 { 20081 struct nk_window *win; 20082 struct nk_panel *layout; 20083 const struct nk_input *in; 20084 20085 struct nk_rect bounds; 20086 enum nk_widget_layout_states state; 20087 20088 NK_ASSERT(ctx); 20089 NK_ASSERT(ctx->current); 20090 NK_ASSERT(ctx->current->layout); 20091 if (!ctx || !ctx->current || !ctx->current->layout) 20092 return 0; 20093 20094 win = ctx->current; 20095 layout = win->layout; 20096 20097 state = nk_widget(&bounds, ctx); 20098 if (!state) return 0; 20099 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20100 return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 20101 bounds, img, text, len, align, ctx->button_behavior, 20102 style, ctx->style.font, in); 20103 } 20104 NK_API int 20105 nk_button_image_text(struct nk_context *ctx, struct nk_image img, 20106 const char *text, int len, nk_flags align) 20107 { 20108 return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align); 20109 } 20110 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img, 20111 const char *label, nk_flags align) 20112 { 20113 return nk_button_image_text(ctx, img, label, nk_strlen(label), align); 20114 } 20115 NK_API int nk_button_image_label_styled(struct nk_context *ctx, 20116 const struct nk_style_button *style, struct nk_image img, 20117 const char *label, nk_flags text_alignment) 20118 { 20119 return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment); 20120 } 20121 20122 20123 20124 20125 20126 /* =============================================================== 20127 * 20128 * TOGGLE 20129 * 20130 * ===============================================================*/ 20131 NK_LIB int 20132 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, 20133 nk_flags *state, int active) 20134 { 20135 nk_widget_state_reset(state); 20136 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) { 20137 *state = NK_WIDGET_STATE_ACTIVE; 20138 active = !active; 20139 } 20140 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select)) 20141 *state |= NK_WIDGET_STATE_ENTERED; 20142 else if (nk_input_is_mouse_prev_hovering_rect(in, select)) 20143 *state |= NK_WIDGET_STATE_LEFT; 20144 return active; 20145 } 20146 NK_LIB void 20147 nk_draw_checkbox(struct nk_command_buffer *out, 20148 nk_flags state, const struct nk_style_toggle *style, int active, 20149 const struct nk_rect *label, const struct nk_rect *selector, 20150 const struct nk_rect *cursors, const char *string, int len, 20151 const struct nk_user_font *font) 20152 { 20153 const struct nk_style_item *background; 20154 const struct nk_style_item *cursor; 20155 struct nk_text text; 20156 20157 /* select correct colors/images */ 20158 if (state & NK_WIDGET_STATE_HOVER) { 20159 background = &style->hover; 20160 cursor = &style->cursor_hover; 20161 text.text = style->text_hover; 20162 } else if (state & NK_WIDGET_STATE_ACTIVED) { 20163 background = &style->hover; 20164 cursor = &style->cursor_hover; 20165 text.text = style->text_active; 20166 } else { 20167 background = &style->normal; 20168 cursor = &style->cursor_normal; 20169 text.text = style->text_normal; 20170 } 20171 20172 /* draw background and cursor */ 20173 if (background->type == NK_STYLE_ITEM_COLOR) { 20174 nk_fill_rect(out, *selector, 0, style->border_color); 20175 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color); 20176 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 20177 if (active) { 20178 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20179 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 20180 else nk_fill_rect(out, *cursors, 0, cursor->data.color); 20181 } 20182 20183 text.padding.x = 0; 20184 text.padding.y = 0; 20185 text.background = style->text_background; 20186 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 20187 } 20188 NK_LIB void 20189 nk_draw_option(struct nk_command_buffer *out, 20190 nk_flags state, const struct nk_style_toggle *style, int active, 20191 const struct nk_rect *label, const struct nk_rect *selector, 20192 const struct nk_rect *cursors, const char *string, int len, 20193 const struct nk_user_font *font) 20194 { 20195 const struct nk_style_item *background; 20196 const struct nk_style_item *cursor; 20197 struct nk_text text; 20198 20199 /* select correct colors/images */ 20200 if (state & NK_WIDGET_STATE_HOVER) { 20201 background = &style->hover; 20202 cursor = &style->cursor_hover; 20203 text.text = style->text_hover; 20204 } else if (state & NK_WIDGET_STATE_ACTIVED) { 20205 background = &style->hover; 20206 cursor = &style->cursor_hover; 20207 text.text = style->text_active; 20208 } else { 20209 background = &style->normal; 20210 cursor = &style->cursor_normal; 20211 text.text = style->text_normal; 20212 } 20213 20214 /* draw background and cursor */ 20215 if (background->type == NK_STYLE_ITEM_COLOR) { 20216 nk_fill_circle(out, *selector, style->border_color); 20217 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color); 20218 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 20219 if (active) { 20220 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20221 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 20222 else nk_fill_circle(out, *cursors, cursor->data.color); 20223 } 20224 20225 text.padding.x = 0; 20226 text.padding.y = 0; 20227 text.background = style->text_background; 20228 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 20229 } 20230 NK_LIB int 20231 nk_do_toggle(nk_flags *state, 20232 struct nk_command_buffer *out, struct nk_rect r, 20233 int *active, const char *str, int len, enum nk_toggle_type type, 20234 const struct nk_style_toggle *style, const struct nk_input *in, 20235 const struct nk_user_font *font) 20236 { 20237 int was_active; 20238 struct nk_rect bounds; 20239 struct nk_rect select; 20240 struct nk_rect cursor; 20241 struct nk_rect label; 20242 20243 NK_ASSERT(style); 20244 NK_ASSERT(out); 20245 NK_ASSERT(font); 20246 if (!out || !style || !font || !active) 20247 return 0; 20248 20249 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x); 20250 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y); 20251 20252 /* add additional touch padding for touch screen devices */ 20253 bounds.x = r.x - style->touch_padding.x; 20254 bounds.y = r.y - style->touch_padding.y; 20255 bounds.w = r.w + 2 * style->touch_padding.x; 20256 bounds.h = r.h + 2 * style->touch_padding.y; 20257 20258 /* calculate the selector space */ 20259 select.w = font->height; 20260 select.h = select.w; 20261 select.y = r.y + r.h/2.0f - select.h/2.0f; 20262 select.x = r.x; 20263 20264 /* calculate the bounds of the cursor inside the selector */ 20265 cursor.x = select.x + style->padding.x + style->border; 20266 cursor.y = select.y + style->padding.y + style->border; 20267 cursor.w = select.w - (2 * style->padding.x + 2 * style->border); 20268 cursor.h = select.h - (2 * style->padding.y + 2 * style->border); 20269 20270 /* label behind the selector */ 20271 label.x = select.x + select.w + style->spacing; 20272 label.y = select.y; 20273 label.w = NK_MAX(r.x + r.w, label.x) - label.x; 20274 label.h = select.w; 20275 20276 /* update selector */ 20277 was_active = *active; 20278 *active = nk_toggle_behavior(in, bounds, state, *active); 20279 20280 /* draw selector */ 20281 if (style->draw_begin) 20282 style->draw_begin(out, style->userdata); 20283 if (type == NK_TOGGLE_CHECK) { 20284 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font); 20285 } else { 20286 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font); 20287 } 20288 if (style->draw_end) 20289 style->draw_end(out, style->userdata); 20290 return (was_active != *active); 20291 } 20292 /*---------------------------------------------------------------- 20293 * 20294 * CHECKBOX 20295 * 20296 * --------------------------------------------------------------*/ 20297 NK_API int 20298 nk_check_text(struct nk_context *ctx, const char *text, int len, int active) 20299 { 20300 struct nk_window *win; 20301 struct nk_panel *layout; 20302 const struct nk_input *in; 20303 const struct nk_style *style; 20304 20305 struct nk_rect bounds; 20306 enum nk_widget_layout_states state; 20307 20308 NK_ASSERT(ctx); 20309 NK_ASSERT(ctx->current); 20310 NK_ASSERT(ctx->current->layout); 20311 if (!ctx || !ctx->current || !ctx->current->layout) 20312 return active; 20313 20314 win = ctx->current; 20315 style = &ctx->style; 20316 layout = win->layout; 20317 20318 state = nk_widget(&bounds, ctx); 20319 if (!state) return active; 20320 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20321 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, 20322 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font); 20323 return active; 20324 } 20325 NK_API unsigned int 20326 nk_check_flags_text(struct nk_context *ctx, const char *text, int len, 20327 unsigned int flags, unsigned int value) 20328 { 20329 int old_active; 20330 NK_ASSERT(ctx); 20331 NK_ASSERT(text); 20332 if (!ctx || !text) return flags; 20333 old_active = (int)((flags & value) & value); 20334 if (nk_check_text(ctx, text, len, old_active)) 20335 flags |= value; 20336 else flags &= ~value; 20337 return flags; 20338 } 20339 NK_API int 20340 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active) 20341 { 20342 int old_val; 20343 NK_ASSERT(ctx); 20344 NK_ASSERT(text); 20345 NK_ASSERT(active); 20346 if (!ctx || !text || !active) return 0; 20347 old_val = *active; 20348 *active = nk_check_text(ctx, text, len, *active); 20349 return old_val != *active; 20350 } 20351 NK_API int 20352 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len, 20353 unsigned int *flags, unsigned int value) 20354 { 20355 int active; 20356 NK_ASSERT(ctx); 20357 NK_ASSERT(text); 20358 NK_ASSERT(flags); 20359 if (!ctx || !text || !flags) return 0; 20360 20361 active = (int)((*flags & value) & value); 20362 if (nk_checkbox_text(ctx, text, len, &active)) { 20363 if (active) *flags |= value; 20364 else *flags &= ~value; 20365 return 1; 20366 } 20367 return 0; 20368 } 20369 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active) 20370 { 20371 return nk_check_text(ctx, label, nk_strlen(label), active); 20372 } 20373 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label, 20374 unsigned int flags, unsigned int value) 20375 { 20376 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value); 20377 } 20378 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active) 20379 { 20380 return nk_checkbox_text(ctx, label, nk_strlen(label), active); 20381 } 20382 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label, 20383 unsigned int *flags, unsigned int value) 20384 { 20385 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value); 20386 } 20387 /*---------------------------------------------------------------- 20388 * 20389 * OPTION 20390 * 20391 * --------------------------------------------------------------*/ 20392 NK_API int 20393 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active) 20394 { 20395 struct nk_window *win; 20396 struct nk_panel *layout; 20397 const struct nk_input *in; 20398 const struct nk_style *style; 20399 20400 struct nk_rect bounds; 20401 enum nk_widget_layout_states state; 20402 20403 NK_ASSERT(ctx); 20404 NK_ASSERT(ctx->current); 20405 NK_ASSERT(ctx->current->layout); 20406 if (!ctx || !ctx->current || !ctx->current->layout) 20407 return is_active; 20408 20409 win = ctx->current; 20410 style = &ctx->style; 20411 layout = win->layout; 20412 20413 state = nk_widget(&bounds, ctx); 20414 if (!state) return (int)state; 20415 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20416 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, 20417 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font); 20418 return is_active; 20419 } 20420 NK_API int 20421 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active) 20422 { 20423 int old_value; 20424 NK_ASSERT(ctx); 20425 NK_ASSERT(text); 20426 NK_ASSERT(active); 20427 if (!ctx || !text || !active) return 0; 20428 old_value = *active; 20429 *active = nk_option_text(ctx, text, len, old_value); 20430 return old_value != *active; 20431 } 20432 NK_API int 20433 nk_option_label(struct nk_context *ctx, const char *label, int active) 20434 { 20435 return nk_option_text(ctx, label, nk_strlen(label), active); 20436 } 20437 NK_API int 20438 nk_radio_label(struct nk_context *ctx, const char *label, int *active) 20439 { 20440 return nk_radio_text(ctx, label, nk_strlen(label), active); 20441 } 20442 20443 20444 20445 20446 20447 /* =============================================================== 20448 * 20449 * SELECTABLE 20450 * 20451 * ===============================================================*/ 20452 NK_LIB void 20453 nk_draw_selectable(struct nk_command_buffer *out, 20454 nk_flags state, const struct nk_style_selectable *style, int active, 20455 const struct nk_rect *bounds, 20456 const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, 20457 const char *string, int len, nk_flags align, const struct nk_user_font *font) 20458 { 20459 const struct nk_style_item *background; 20460 struct nk_text text; 20461 text.padding = style->padding; 20462 20463 /* select correct colors/images */ 20464 if (!active) { 20465 if (state & NK_WIDGET_STATE_ACTIVED) { 20466 background = &style->pressed; 20467 text.text = style->text_pressed; 20468 } else if (state & NK_WIDGET_STATE_HOVER) { 20469 background = &style->hover; 20470 text.text = style->text_hover; 20471 } else { 20472 background = &style->normal; 20473 text.text = style->text_normal; 20474 } 20475 } else { 20476 if (state & NK_WIDGET_STATE_ACTIVED) { 20477 background = &style->pressed_active; 20478 text.text = style->text_pressed_active; 20479 } else if (state & NK_WIDGET_STATE_HOVER) { 20480 background = &style->hover_active; 20481 text.text = style->text_hover_active; 20482 } else { 20483 background = &style->normal_active; 20484 text.text = style->text_normal_active; 20485 } 20486 } 20487 /* draw selectable background and text */ 20488 if (background->type == NK_STYLE_ITEM_IMAGE) { 20489 nk_draw_image(out, *bounds, &background->data.image, nk_white); 20490 text.background = nk_rgba(0,0,0,0); 20491 } else { 20492 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 20493 text.background = background->data.color; 20494 } 20495 if (icon) { 20496 if (img) nk_draw_image(out, *icon, img, nk_white); 20497 else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font); 20498 } 20499 nk_widget_text(out, *bounds, string, len, &text, align, font); 20500 } 20501 NK_LIB int 20502 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, 20503 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20504 const struct nk_style_selectable *style, const struct nk_input *in, 20505 const struct nk_user_font *font) 20506 { 20507 int old_value; 20508 struct nk_rect touch; 20509 20510 NK_ASSERT(state); 20511 NK_ASSERT(out); 20512 NK_ASSERT(str); 20513 NK_ASSERT(len); 20514 NK_ASSERT(value); 20515 NK_ASSERT(style); 20516 NK_ASSERT(font); 20517 20518 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20519 old_value = *value; 20520 20521 /* remove padding */ 20522 touch.x = bounds.x - style->touch_padding.x; 20523 touch.y = bounds.y - style->touch_padding.y; 20524 touch.w = bounds.w + style->touch_padding.x * 2; 20525 touch.h = bounds.h + style->touch_padding.y * 2; 20526 20527 /* update button */ 20528 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20529 *value = !(*value); 20530 20531 /* draw selectable */ 20532 if (style->draw_begin) style->draw_begin(out, style->userdata); 20533 nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font); 20534 if (style->draw_end) style->draw_end(out, style->userdata); 20535 return old_value != *value; 20536 } 20537 NK_LIB int 20538 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, 20539 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20540 const struct nk_image *img, const struct nk_style_selectable *style, 20541 const struct nk_input *in, const struct nk_user_font *font) 20542 { 20543 int old_value; 20544 struct nk_rect touch; 20545 struct nk_rect icon; 20546 20547 NK_ASSERT(state); 20548 NK_ASSERT(out); 20549 NK_ASSERT(str); 20550 NK_ASSERT(len); 20551 NK_ASSERT(value); 20552 NK_ASSERT(style); 20553 NK_ASSERT(font); 20554 20555 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20556 old_value = *value; 20557 20558 /* toggle behavior */ 20559 touch.x = bounds.x - style->touch_padding.x; 20560 touch.y = bounds.y - style->touch_padding.y; 20561 touch.w = bounds.w + style->touch_padding.x * 2; 20562 touch.h = bounds.h + style->touch_padding.y * 2; 20563 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20564 *value = !(*value); 20565 20566 icon.y = bounds.y + style->padding.y; 20567 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20568 if (align & NK_TEXT_ALIGN_LEFT) { 20569 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20570 icon.x = NK_MAX(icon.x, 0); 20571 } else icon.x = bounds.x + 2 * style->padding.x; 20572 20573 icon.x += style->image_padding.x; 20574 icon.y += style->image_padding.y; 20575 icon.w -= 2 * style->image_padding.x; 20576 icon.h -= 2 * style->image_padding.y; 20577 20578 /* draw selectable */ 20579 if (style->draw_begin) style->draw_begin(out, style->userdata); 20580 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font); 20581 if (style->draw_end) style->draw_end(out, style->userdata); 20582 return old_value != *value; 20583 } 20584 NK_LIB int 20585 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out, 20586 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20587 enum nk_symbol_type sym, const struct nk_style_selectable *style, 20588 const struct nk_input *in, const struct nk_user_font *font) 20589 { 20590 int old_value; 20591 struct nk_rect touch; 20592 struct nk_rect icon; 20593 20594 NK_ASSERT(state); 20595 NK_ASSERT(out); 20596 NK_ASSERT(str); 20597 NK_ASSERT(len); 20598 NK_ASSERT(value); 20599 NK_ASSERT(style); 20600 NK_ASSERT(font); 20601 20602 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20603 old_value = *value; 20604 20605 /* toggle behavior */ 20606 touch.x = bounds.x - style->touch_padding.x; 20607 touch.y = bounds.y - style->touch_padding.y; 20608 touch.w = bounds.w + style->touch_padding.x * 2; 20609 touch.h = bounds.h + style->touch_padding.y * 2; 20610 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20611 *value = !(*value); 20612 20613 icon.y = bounds.y + style->padding.y; 20614 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20615 if (align & NK_TEXT_ALIGN_LEFT) { 20616 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20617 icon.x = NK_MAX(icon.x, 0); 20618 } else icon.x = bounds.x + 2 * style->padding.x; 20619 20620 icon.x += style->image_padding.x; 20621 icon.y += style->image_padding.y; 20622 icon.w -= 2 * style->image_padding.x; 20623 icon.h -= 2 * style->image_padding.y; 20624 20625 /* draw selectable */ 20626 if (style->draw_begin) style->draw_begin(out, style->userdata); 20627 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font); 20628 if (style->draw_end) style->draw_end(out, style->userdata); 20629 return old_value != *value; 20630 } 20631 20632 NK_API int 20633 nk_selectable_text(struct nk_context *ctx, const char *str, int len, 20634 nk_flags align, int *value) 20635 { 20636 struct nk_window *win; 20637 struct nk_panel *layout; 20638 const struct nk_input *in; 20639 const struct nk_style *style; 20640 20641 enum nk_widget_layout_states state; 20642 struct nk_rect bounds; 20643 20644 NK_ASSERT(ctx); 20645 NK_ASSERT(value); 20646 NK_ASSERT(ctx->current); 20647 NK_ASSERT(ctx->current->layout); 20648 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20649 return 0; 20650 20651 win = ctx->current; 20652 layout = win->layout; 20653 style = &ctx->style; 20654 20655 state = nk_widget(&bounds, ctx); 20656 if (!state) return 0; 20657 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20658 return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, 20659 str, len, align, value, &style->selectable, in, style->font); 20660 } 20661 NK_API int 20662 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img, 20663 const char *str, int len, nk_flags align, int *value) 20664 { 20665 struct nk_window *win; 20666 struct nk_panel *layout; 20667 const struct nk_input *in; 20668 const struct nk_style *style; 20669 20670 enum nk_widget_layout_states state; 20671 struct nk_rect bounds; 20672 20673 NK_ASSERT(ctx); 20674 NK_ASSERT(value); 20675 NK_ASSERT(ctx->current); 20676 NK_ASSERT(ctx->current->layout); 20677 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20678 return 0; 20679 20680 win = ctx->current; 20681 layout = win->layout; 20682 style = &ctx->style; 20683 20684 state = nk_widget(&bounds, ctx); 20685 if (!state) return 0; 20686 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20687 return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds, 20688 str, len, align, value, &img, &style->selectable, in, style->font); 20689 } 20690 NK_API int 20691 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 20692 const char *str, int len, nk_flags align, int *value) 20693 { 20694 struct nk_window *win; 20695 struct nk_panel *layout; 20696 const struct nk_input *in; 20697 const struct nk_style *style; 20698 20699 enum nk_widget_layout_states state; 20700 struct nk_rect bounds; 20701 20702 NK_ASSERT(ctx); 20703 NK_ASSERT(value); 20704 NK_ASSERT(ctx->current); 20705 NK_ASSERT(ctx->current->layout); 20706 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20707 return 0; 20708 20709 win = ctx->current; 20710 layout = win->layout; 20711 style = &ctx->style; 20712 20713 state = nk_widget(&bounds, ctx); 20714 if (!state) return 0; 20715 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20716 return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20717 str, len, align, value, sym, &style->selectable, in, style->font); 20718 } 20719 NK_API int 20720 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 20721 const char *title, nk_flags align, int *value) 20722 { 20723 return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 20724 } 20725 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len, 20726 nk_flags align, int value) 20727 { 20728 nk_selectable_text(ctx, str, len, align, &value);return value; 20729 } 20730 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value) 20731 { 20732 return nk_selectable_text(ctx, str, nk_strlen(str), align, value); 20733 } 20734 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img, 20735 const char *str, nk_flags align, int *value) 20736 { 20737 return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value); 20738 } 20739 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value) 20740 { 20741 nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value; 20742 } 20743 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img, 20744 const char *str, nk_flags align, int value) 20745 { 20746 nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value; 20747 } 20748 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img, 20749 const char *str, int len, nk_flags align, int value) 20750 { 20751 nk_selectable_image_text(ctx, img, str, len, align, &value);return value; 20752 } 20753 NK_API int 20754 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 20755 const char *title, int title_len, nk_flags align, int value) 20756 { 20757 nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value; 20758 } 20759 NK_API int 20760 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 20761 const char *title, nk_flags align, int value) 20762 { 20763 return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 20764 } 20765 20766 20767 20768 20769 20770 /* =============================================================== 20771 * 20772 * SLIDER 20773 * 20774 * ===============================================================*/ 20775 NK_LIB float 20776 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, 20777 struct nk_rect *visual_cursor, struct nk_input *in, 20778 struct nk_rect bounds, float slider_min, float slider_max, float slider_value, 20779 float slider_step, float slider_steps) 20780 { 20781 int left_mouse_down; 20782 int left_mouse_click_in_cursor; 20783 20784 /* check if visual cursor is being dragged */ 20785 nk_widget_state_reset(state); 20786 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 20787 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 20788 NK_BUTTON_LEFT, *visual_cursor, nk_true); 20789 20790 if (left_mouse_down && left_mouse_click_in_cursor) { 20791 float ratio = 0; 20792 const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f); 20793 const float pxstep = bounds.w / slider_steps; 20794 20795 /* only update value if the next slider step is reached */ 20796 *state = NK_WIDGET_STATE_ACTIVE; 20797 if (NK_ABS(d) >= pxstep) { 20798 const float steps = (float)((int)(NK_ABS(d) / pxstep)); 20799 slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); 20800 slider_value = NK_CLAMP(slider_min, slider_value, slider_max); 20801 ratio = (slider_value - slider_min)/slider_step; 20802 logical_cursor->x = bounds.x + (logical_cursor->w * ratio); 20803 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x; 20804 } 20805 } 20806 20807 /* slider widget state */ 20808 if (nk_input_is_mouse_hovering_rect(in, bounds)) 20809 *state = NK_WIDGET_STATE_HOVERED; 20810 if (*state & NK_WIDGET_STATE_HOVER && 20811 !nk_input_is_mouse_prev_hovering_rect(in, bounds)) 20812 *state |= NK_WIDGET_STATE_ENTERED; 20813 else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) 20814 *state |= NK_WIDGET_STATE_LEFT; 20815 return slider_value; 20816 } 20817 NK_LIB void 20818 nk_draw_slider(struct nk_command_buffer *out, nk_flags state, 20819 const struct nk_style_slider *style, const struct nk_rect *bounds, 20820 const struct nk_rect *visual_cursor, float min, float value, float max) 20821 { 20822 struct nk_rect fill; 20823 struct nk_rect bar; 20824 const struct nk_style_item *background; 20825 20826 /* select correct slider images/colors */ 20827 struct nk_color bar_color; 20828 const struct nk_style_item *cursor; 20829 20830 NK_UNUSED(min); 20831 NK_UNUSED(max); 20832 NK_UNUSED(value); 20833 20834 if (state & NK_WIDGET_STATE_ACTIVED) { 20835 background = &style->active; 20836 bar_color = style->bar_active; 20837 cursor = &style->cursor_active; 20838 } else if (state & NK_WIDGET_STATE_HOVER) { 20839 background = &style->hover; 20840 bar_color = style->bar_hover; 20841 cursor = &style->cursor_hover; 20842 } else { 20843 background = &style->normal; 20844 bar_color = style->bar_normal; 20845 cursor = &style->cursor_normal; 20846 } 20847 /* calculate slider background bar */ 20848 bar.x = bounds->x; 20849 bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12; 20850 bar.w = bounds->w; 20851 bar.h = bounds->h/6; 20852 20853 /* filled background bar style */ 20854 fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x; 20855 fill.x = bar.x; 20856 fill.y = bar.y; 20857 fill.h = bar.h; 20858 20859 /* draw background */ 20860 if (background->type == NK_STYLE_ITEM_IMAGE) { 20861 nk_draw_image(out, *bounds, &background->data.image, nk_white); 20862 } else { 20863 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 20864 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 20865 } 20866 20867 /* draw slider bar */ 20868 nk_fill_rect(out, bar, style->rounding, bar_color); 20869 nk_fill_rect(out, fill, style->rounding, style->bar_filled); 20870 20871 /* draw cursor */ 20872 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20873 nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white); 20874 else nk_fill_circle(out, *visual_cursor, cursor->data.color); 20875 } 20876 NK_LIB float 20877 nk_do_slider(nk_flags *state, 20878 struct nk_command_buffer *out, struct nk_rect bounds, 20879 float min, float val, float max, float step, 20880 const struct nk_style_slider *style, struct nk_input *in, 20881 const struct nk_user_font *font) 20882 { 20883 float slider_range; 20884 float slider_min; 20885 float slider_max; 20886 float slider_value; 20887 float slider_steps; 20888 float cursor_offset; 20889 20890 struct nk_rect visual_cursor; 20891 struct nk_rect logical_cursor; 20892 20893 NK_ASSERT(style); 20894 NK_ASSERT(out); 20895 if (!out || !style) 20896 return 0; 20897 20898 /* remove padding from slider bounds */ 20899 bounds.x = bounds.x + style->padding.x; 20900 bounds.y = bounds.y + style->padding.y; 20901 bounds.h = NK_MAX(bounds.h, 2*style->padding.y); 20902 bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x); 20903 bounds.w -= 2 * style->padding.x; 20904 bounds.h -= 2 * style->padding.y; 20905 20906 /* optional buttons */ 20907 if (style->show_buttons) { 20908 nk_flags ws; 20909 struct nk_rect button; 20910 button.y = bounds.y; 20911 button.w = bounds.h; 20912 button.h = bounds.h; 20913 20914 /* decrement button */ 20915 button.x = bounds.x; 20916 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT, 20917 &style->dec_button, in, font)) 20918 val -= step; 20919 20920 /* increment button */ 20921 button.x = (bounds.x + bounds.w) - button.w; 20922 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT, 20923 &style->inc_button, in, font)) 20924 val += step; 20925 20926 bounds.x = bounds.x + button.w + style->spacing.x; 20927 bounds.w = bounds.w - (2*button.w + 2*style->spacing.x); 20928 } 20929 20930 /* remove one cursor size to support visual cursor */ 20931 bounds.x += style->cursor_size.x*0.5f; 20932 bounds.w -= style->cursor_size.x; 20933 20934 /* make sure the provided values are correct */ 20935 slider_max = NK_MAX(min, max); 20936 slider_min = NK_MIN(min, max); 20937 slider_value = NK_CLAMP(slider_min, val, slider_max); 20938 slider_range = slider_max - slider_min; 20939 slider_steps = slider_range / step; 20940 cursor_offset = (slider_value - slider_min) / step; 20941 20942 /* calculate cursor 20943 Basically you have two cursors. One for visual representation and interaction 20944 and one for updating the actual cursor value. */ 20945 logical_cursor.h = bounds.h; 20946 logical_cursor.w = bounds.w / slider_steps; 20947 logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset); 20948 logical_cursor.y = bounds.y; 20949 20950 visual_cursor.h = style->cursor_size.y; 20951 visual_cursor.w = style->cursor_size.x; 20952 visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f; 20953 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 20954 20955 slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor, 20956 in, bounds, slider_min, slider_max, slider_value, step, slider_steps); 20957 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 20958 20959 /* draw slider */ 20960 if (style->draw_begin) style->draw_begin(out, style->userdata); 20961 nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max); 20962 if (style->draw_end) style->draw_end(out, style->userdata); 20963 return slider_value; 20964 } 20965 NK_API int 20966 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value, 20967 float value_step) 20968 { 20969 struct nk_window *win; 20970 struct nk_panel *layout; 20971 struct nk_input *in; 20972 const struct nk_style *style; 20973 20974 int ret = 0; 20975 float old_value; 20976 struct nk_rect bounds; 20977 enum nk_widget_layout_states state; 20978 20979 NK_ASSERT(ctx); 20980 NK_ASSERT(ctx->current); 20981 NK_ASSERT(ctx->current->layout); 20982 NK_ASSERT(value); 20983 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20984 return ret; 20985 20986 win = ctx->current; 20987 style = &ctx->style; 20988 layout = win->layout; 20989 20990 state = nk_widget(&bounds, ctx); 20991 if (!state) return ret; 20992 in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20993 20994 old_value = *value; 20995 *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, 20996 old_value, max_value, value_step, &style->slider, in, style->font); 20997 return (old_value > *value || old_value < *value); 20998 } 20999 NK_API float 21000 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step) 21001 { 21002 nk_slider_float(ctx, min, &val, max, step); return val; 21003 } 21004 NK_API int 21005 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step) 21006 { 21007 float value = (float)val; 21008 nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 21009 return (int)value; 21010 } 21011 NK_API int 21012 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) 21013 { 21014 int ret; 21015 float value = (float)*val; 21016 ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 21017 *val = (int)value; 21018 return ret; 21019 } 21020 21021 21022 21023 21024 21025 /* =============================================================== 21026 * 21027 * PROGRESS 21028 * 21029 * ===============================================================*/ 21030 NK_LIB nk_size 21031 nk_progress_behavior(nk_flags *state, struct nk_input *in, 21032 struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable) 21033 { 21034 int left_mouse_down = 0; 21035 int left_mouse_click_in_cursor = 0; 21036 21037 nk_widget_state_reset(state); 21038 if (!in || !modifiable) return value; 21039 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 21040 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 21041 NK_BUTTON_LEFT, cursor, nk_true); 21042 if (nk_input_is_mouse_hovering_rect(in, r)) 21043 *state = NK_WIDGET_STATE_HOVERED; 21044 21045 if (in && left_mouse_down && left_mouse_click_in_cursor) { 21046 if (left_mouse_down && left_mouse_click_in_cursor) { 21047 float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w; 21048 value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max); 21049 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f; 21050 *state |= NK_WIDGET_STATE_ACTIVE; 21051 } 21052 } 21053 /* set progressbar widget state */ 21054 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r)) 21055 *state |= NK_WIDGET_STATE_ENTERED; 21056 else if (nk_input_is_mouse_prev_hovering_rect(in, r)) 21057 *state |= NK_WIDGET_STATE_LEFT; 21058 return value; 21059 } 21060 NK_LIB void 21061 nk_draw_progress(struct nk_command_buffer *out, nk_flags state, 21062 const struct nk_style_progress *style, const struct nk_rect *bounds, 21063 const struct nk_rect *scursor, nk_size value, nk_size max) 21064 { 21065 const struct nk_style_item *background; 21066 const struct nk_style_item *cursor; 21067 21068 NK_UNUSED(max); 21069 NK_UNUSED(value); 21070 21071 /* select correct colors/images to draw */ 21072 if (state & NK_WIDGET_STATE_ACTIVED) { 21073 background = &style->active; 21074 cursor = &style->cursor_active; 21075 } else if (state & NK_WIDGET_STATE_HOVER){ 21076 background = &style->hover; 21077 cursor = &style->cursor_hover; 21078 } else { 21079 background = &style->normal; 21080 cursor = &style->cursor_normal; 21081 } 21082 21083 /* draw background */ 21084 if (background->type == NK_STYLE_ITEM_COLOR) { 21085 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21086 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21087 } else nk_draw_image(out, *bounds, &background->data.image, nk_white); 21088 21089 /* draw cursor */ 21090 if (cursor->type == NK_STYLE_ITEM_COLOR) { 21091 nk_fill_rect(out, *scursor, style->rounding, cursor->data.color); 21092 nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color); 21093 } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white); 21094 } 21095 NK_LIB nk_size 21096 nk_do_progress(nk_flags *state, 21097 struct nk_command_buffer *out, struct nk_rect bounds, 21098 nk_size value, nk_size max, int modifiable, 21099 const struct nk_style_progress *style, struct nk_input *in) 21100 { 21101 float prog_scale; 21102 nk_size prog_value; 21103 struct nk_rect cursor; 21104 21105 NK_ASSERT(style); 21106 NK_ASSERT(out); 21107 if (!out || !style) return 0; 21108 21109 /* calculate progressbar cursor */ 21110 cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); 21111 cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border); 21112 cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border)); 21113 prog_scale = (float)value / (float)max; 21114 21115 /* update progressbar */ 21116 prog_value = NK_MIN(value, max); 21117 prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable); 21118 cursor.w = cursor.w * prog_scale; 21119 21120 /* draw progressbar */ 21121 if (style->draw_begin) style->draw_begin(out, style->userdata); 21122 nk_draw_progress(out, *state, style, &bounds, &cursor, value, max); 21123 if (style->draw_end) style->draw_end(out, style->userdata); 21124 return prog_value; 21125 } 21126 NK_API int 21127 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable) 21128 { 21129 struct nk_window *win; 21130 struct nk_panel *layout; 21131 const struct nk_style *style; 21132 struct nk_input *in; 21133 21134 struct nk_rect bounds; 21135 enum nk_widget_layout_states state; 21136 nk_size old_value; 21137 21138 NK_ASSERT(ctx); 21139 NK_ASSERT(cur); 21140 NK_ASSERT(ctx->current); 21141 NK_ASSERT(ctx->current->layout); 21142 if (!ctx || !ctx->current || !ctx->current->layout || !cur) 21143 return 0; 21144 21145 win = ctx->current; 21146 style = &ctx->style; 21147 layout = win->layout; 21148 state = nk_widget(&bounds, ctx); 21149 if (!state) return 0; 21150 21151 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21152 old_value = *cur; 21153 *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds, 21154 *cur, max, is_modifyable, &style->progress, in); 21155 return (*cur != old_value); 21156 } 21157 NK_API nk_size 21158 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable) 21159 { 21160 nk_progress(ctx, &cur, max, modifyable); 21161 return cur; 21162 } 21163 21164 21165 21166 21167 21168 /* =============================================================== 21169 * 21170 * SCROLLBAR 21171 * 21172 * ===============================================================*/ 21173 NK_LIB float 21174 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, 21175 int has_scrolling, const struct nk_rect *scroll, 21176 const struct nk_rect *cursor, const struct nk_rect *empty0, 21177 const struct nk_rect *empty1, float scroll_offset, 21178 float target, float scroll_step, enum nk_orientation o) 21179 { 21180 nk_flags ws = 0; 21181 int left_mouse_down; 21182 int left_mouse_click_in_cursor; 21183 float scroll_delta; 21184 21185 nk_widget_state_reset(state); 21186 if (!in) return scroll_offset; 21187 21188 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 21189 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 21190 NK_BUTTON_LEFT, *cursor, nk_true); 21191 if (nk_input_is_mouse_hovering_rect(in, *scroll)) 21192 *state = NK_WIDGET_STATE_HOVERED; 21193 21194 scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; 21195 if (left_mouse_down && left_mouse_click_in_cursor) { 21196 /* update cursor by mouse dragging */ 21197 float pixel, delta; 21198 *state = NK_WIDGET_STATE_ACTIVE; 21199 if (o == NK_VERTICAL) { 21200 float cursor_y; 21201 pixel = in->mouse.delta.y; 21202 delta = (pixel / scroll->h) * target; 21203 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); 21204 cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); 21205 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; 21206 } else { 21207 float cursor_x; 21208 pixel = in->mouse.delta.x; 21209 delta = (pixel / scroll->w) * target; 21210 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); 21211 cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); 21212 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; 21213 } 21214 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| 21215 nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { 21216 /* scroll page up by click on empty space or shortcut */ 21217 if (o == NK_VERTICAL) 21218 scroll_offset = NK_MAX(0, scroll_offset - scroll->h); 21219 else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); 21220 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || 21221 nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { 21222 /* scroll page down by click on empty space or shortcut */ 21223 if (o == NK_VERTICAL) 21224 scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); 21225 else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); 21226 } else if (has_scrolling) { 21227 if ((scroll_delta < 0 || (scroll_delta > 0))) { 21228 /* update cursor by mouse scrolling */ 21229 scroll_offset = scroll_offset + scroll_step * (-scroll_delta); 21230 if (o == NK_VERTICAL) 21231 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); 21232 else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); 21233 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { 21234 /* update cursor to the beginning */ 21235 if (o == NK_VERTICAL) scroll_offset = 0; 21236 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { 21237 /* update cursor to the end */ 21238 if (o == NK_VERTICAL) scroll_offset = target - scroll->h; 21239 } 21240 } 21241 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 21242 *state |= NK_WIDGET_STATE_ENTERED; 21243 else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 21244 *state |= NK_WIDGET_STATE_LEFT; 21245 return scroll_offset; 21246 } 21247 NK_LIB void 21248 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, 21249 const struct nk_style_scrollbar *style, const struct nk_rect *bounds, 21250 const struct nk_rect *scroll) 21251 { 21252 const struct nk_style_item *background; 21253 const struct nk_style_item *cursor; 21254 21255 /* select correct colors/images to draw */ 21256 if (state & NK_WIDGET_STATE_ACTIVED) { 21257 background = &style->active; 21258 cursor = &style->cursor_active; 21259 } else if (state & NK_WIDGET_STATE_HOVER) { 21260 background = &style->hover; 21261 cursor = &style->cursor_hover; 21262 } else { 21263 background = &style->normal; 21264 cursor = &style->cursor_normal; 21265 } 21266 21267 /* draw background */ 21268 if (background->type == NK_STYLE_ITEM_COLOR) { 21269 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21270 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21271 } else { 21272 nk_draw_image(out, *bounds, &background->data.image, nk_white); 21273 } 21274 21275 /* draw cursor */ 21276 if (cursor->type == NK_STYLE_ITEM_COLOR) { 21277 nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); 21278 nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); 21279 } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white); 21280 } 21281 NK_LIB float 21282 nk_do_scrollbarv(nk_flags *state, 21283 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 21284 float offset, float target, float step, float button_pixel_inc, 21285 const struct nk_style_scrollbar *style, struct nk_input *in, 21286 const struct nk_user_font *font) 21287 { 21288 struct nk_rect empty_north; 21289 struct nk_rect empty_south; 21290 struct nk_rect cursor; 21291 21292 float scroll_step; 21293 float scroll_offset; 21294 float scroll_off; 21295 float scroll_ratio; 21296 21297 NK_ASSERT(out); 21298 NK_ASSERT(style); 21299 NK_ASSERT(state); 21300 if (!out || !style) return 0; 21301 21302 scroll.w = NK_MAX(scroll.w, 1); 21303 scroll.h = NK_MAX(scroll.h, 0); 21304 if (target <= scroll.h) return 0; 21305 21306 /* optional scrollbar buttons */ 21307 if (style->show_buttons) { 21308 nk_flags ws; 21309 float scroll_h; 21310 struct nk_rect button; 21311 21312 button.x = scroll.x; 21313 button.w = scroll.w; 21314 button.h = scroll.w; 21315 21316 scroll_h = NK_MAX(scroll.h - 2 * button.h,0); 21317 scroll_step = NK_MIN(step, button_pixel_inc); 21318 21319 /* decrement button */ 21320 button.y = scroll.y; 21321 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 21322 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 21323 offset = offset - scroll_step; 21324 21325 /* increment button */ 21326 button.y = scroll.y + scroll.h - button.h; 21327 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 21328 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 21329 offset = offset + scroll_step; 21330 21331 scroll.y = scroll.y + button.h; 21332 scroll.h = scroll_h; 21333 } 21334 21335 /* calculate scrollbar constants */ 21336 scroll_step = NK_MIN(step, scroll.h); 21337 scroll_offset = NK_CLAMP(0, offset, target - scroll.h); 21338 scroll_ratio = scroll.h / target; 21339 scroll_off = scroll_offset / target; 21340 21341 /* calculate scrollbar cursor bounds */ 21342 cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0); 21343 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y; 21344 cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x); 21345 cursor.x = scroll.x + style->border + style->padding.x; 21346 21347 /* calculate empty space around cursor */ 21348 empty_north.x = scroll.x; 21349 empty_north.y = scroll.y; 21350 empty_north.w = scroll.w; 21351 empty_north.h = NK_MAX(cursor.y - scroll.y, 0); 21352 21353 empty_south.x = scroll.x; 21354 empty_south.y = cursor.y + cursor.h; 21355 empty_south.w = scroll.w; 21356 empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0); 21357 21358 /* update scrollbar */ 21359 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 21360 &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL); 21361 scroll_off = scroll_offset / target; 21362 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y; 21363 21364 /* draw scrollbar */ 21365 if (style->draw_begin) style->draw_begin(out, style->userdata); 21366 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 21367 if (style->draw_end) style->draw_end(out, style->userdata); 21368 return scroll_offset; 21369 } 21370 NK_LIB float 21371 nk_do_scrollbarh(nk_flags *state, 21372 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 21373 float offset, float target, float step, float button_pixel_inc, 21374 const struct nk_style_scrollbar *style, struct nk_input *in, 21375 const struct nk_user_font *font) 21376 { 21377 struct nk_rect cursor; 21378 struct nk_rect empty_west; 21379 struct nk_rect empty_east; 21380 21381 float scroll_step; 21382 float scroll_offset; 21383 float scroll_off; 21384 float scroll_ratio; 21385 21386 NK_ASSERT(out); 21387 NK_ASSERT(style); 21388 if (!out || !style) return 0; 21389 21390 /* scrollbar background */ 21391 scroll.h = NK_MAX(scroll.h, 1); 21392 scroll.w = NK_MAX(scroll.w, 2 * scroll.h); 21393 if (target <= scroll.w) return 0; 21394 21395 /* optional scrollbar buttons */ 21396 if (style->show_buttons) { 21397 nk_flags ws; 21398 float scroll_w; 21399 struct nk_rect button; 21400 button.y = scroll.y; 21401 button.w = scroll.h; 21402 button.h = scroll.h; 21403 21404 scroll_w = scroll.w - 2 * button.w; 21405 scroll_step = NK_MIN(step, button_pixel_inc); 21406 21407 /* decrement button */ 21408 button.x = scroll.x; 21409 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 21410 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 21411 offset = offset - scroll_step; 21412 21413 /* increment button */ 21414 button.x = scroll.x + scroll.w - button.w; 21415 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 21416 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 21417 offset = offset + scroll_step; 21418 21419 scroll.x = scroll.x + button.w; 21420 scroll.w = scroll_w; 21421 } 21422 21423 /* calculate scrollbar constants */ 21424 scroll_step = NK_MIN(step, scroll.w); 21425 scroll_offset = NK_CLAMP(0, offset, target - scroll.w); 21426 scroll_ratio = scroll.w / target; 21427 scroll_off = scroll_offset / target; 21428 21429 /* calculate cursor bounds */ 21430 cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); 21431 cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; 21432 cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); 21433 cursor.y = scroll.y + style->border + style->padding.y; 21434 21435 /* calculate empty space around cursor */ 21436 empty_west.x = scroll.x; 21437 empty_west.y = scroll.y; 21438 empty_west.w = cursor.x - scroll.x; 21439 empty_west.h = scroll.h; 21440 21441 empty_east.x = cursor.x + cursor.w; 21442 empty_east.y = scroll.y; 21443 empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); 21444 empty_east.h = scroll.h; 21445 21446 /* update scrollbar */ 21447 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 21448 &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); 21449 scroll_off = scroll_offset / target; 21450 cursor.x = scroll.x + (scroll_off * scroll.w); 21451 21452 /* draw scrollbar */ 21453 if (style->draw_begin) style->draw_begin(out, style->userdata); 21454 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 21455 if (style->draw_end) style->draw_end(out, style->userdata); 21456 return scroll_offset; 21457 } 21458 21459 21460 21461 21462 21463 /* =============================================================== 21464 * 21465 * TEXT EDITOR 21466 * 21467 * ===============================================================*/ 21468 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */ 21469 struct nk_text_find { 21470 float x,y; /* position of n'th character */ 21471 float height; /* height of line */ 21472 int first_char, length; /* first char of row, and length */ 21473 int prev_first; /*_ first char of previous row */ 21474 }; 21475 21476 struct nk_text_edit_row { 21477 float x0,x1; 21478 /* starting x location, end x location (allows for align=right, etc) */ 21479 float baseline_y_delta; 21480 /* position of baseline relative to previous row's baseline*/ 21481 float ymin,ymax; 21482 /* height of row above and below baseline */ 21483 int num_chars; 21484 }; 21485 21486 /* forward declarations */ 21487 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int); 21488 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int); 21489 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int); 21490 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) 21491 21492 NK_INTERN float 21493 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id, 21494 const struct nk_user_font *font) 21495 { 21496 int len = 0; 21497 nk_rune unicode = 0; 21498 const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len); 21499 return font->width(font->userdata, font->height, str, len); 21500 } 21501 NK_INTERN void 21502 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit, 21503 int line_start_id, float row_height, const struct nk_user_font *font) 21504 { 21505 int l; 21506 int glyphs = 0; 21507 nk_rune unicode; 21508 const char *remaining; 21509 int len = nk_str_len_char(&edit->string); 21510 const char *end = nk_str_get_const(&edit->string) + len; 21511 const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l); 21512 const struct nk_vec2 size = nk_text_calculate_text_bounds(font, 21513 text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE); 21514 21515 r->x0 = 0.0f; 21516 r->x1 = size.x; 21517 r->baseline_y_delta = size.y; 21518 r->ymin = 0.0f; 21519 r->ymax = size.y; 21520 r->num_chars = glyphs; 21521 } 21522 NK_INTERN int 21523 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y, 21524 const struct nk_user_font *font, float row_height) 21525 { 21526 struct nk_text_edit_row r; 21527 int n = edit->string.len; 21528 float base_y = 0, prev_x; 21529 int i=0, k; 21530 21531 r.x0 = r.x1 = 0; 21532 r.ymin = r.ymax = 0; 21533 r.num_chars = 0; 21534 21535 /* search rows to find one that straddles 'y' */ 21536 while (i < n) { 21537 nk_textedit_layout_row(&r, edit, i, row_height, font); 21538 if (r.num_chars <= 0) 21539 return n; 21540 21541 if (i==0 && y < base_y + r.ymin) 21542 return 0; 21543 21544 if (y < base_y + r.ymax) 21545 break; 21546 21547 i += r.num_chars; 21548 base_y += r.baseline_y_delta; 21549 } 21550 21551 /* below all text, return 'after' last character */ 21552 if (i >= n) 21553 return n; 21554 21555 /* check if it's before the beginning of the line */ 21556 if (x < r.x0) 21557 return i; 21558 21559 /* check if it's before the end of the line */ 21560 if (x < r.x1) { 21561 /* search characters in row for one that straddles 'x' */ 21562 k = i; 21563 prev_x = r.x0; 21564 for (i=0; i < r.num_chars; ++i) { 21565 float w = nk_textedit_get_width(edit, k, i, font); 21566 if (x < prev_x+w) { 21567 if (x < prev_x+w/2) 21568 return k+i; 21569 else return k+i+1; 21570 } 21571 prev_x += w; 21572 } 21573 /* shouldn't happen, but if it does, fall through to end-of-line case */ 21574 } 21575 21576 /* if the last character is a newline, return that. 21577 * otherwise return 'after' the last character */ 21578 if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n') 21579 return i+r.num_chars-1; 21580 else return i+r.num_chars; 21581 } 21582 NK_LIB void 21583 nk_textedit_click(struct nk_text_edit *state, float x, float y, 21584 const struct nk_user_font *font, float row_height) 21585 { 21586 /* API click: on mouse down, move the cursor to the clicked location, 21587 * and reset the selection */ 21588 state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height); 21589 state->select_start = state->cursor; 21590 state->select_end = state->cursor; 21591 state->has_preferred_x = 0; 21592 } 21593 NK_LIB void 21594 nk_textedit_drag(struct nk_text_edit *state, float x, float y, 21595 const struct nk_user_font *font, float row_height) 21596 { 21597 /* API drag: on mouse drag, move the cursor and selection endpoint 21598 * to the clicked location */ 21599 int p = nk_textedit_locate_coord(state, x, y, font, row_height); 21600 if (state->select_start == state->select_end) 21601 state->select_start = state->cursor; 21602 state->cursor = state->select_end = p; 21603 } 21604 NK_INTERN void 21605 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state, 21606 int n, int single_line, const struct nk_user_font *font, float row_height) 21607 { 21608 /* find the x/y location of a character, and remember info about the previous 21609 * row in case we get a move-up event (for page up, we'll have to rescan) */ 21610 struct nk_text_edit_row r; 21611 int prev_start = 0; 21612 int z = state->string.len; 21613 int i=0, first; 21614 21615 nk_zero_struct(r); 21616 if (n == z) { 21617 /* if it's at the end, then find the last line -- simpler than trying to 21618 explicitly handle this case in the regular code */ 21619 nk_textedit_layout_row(&r, state, 0, row_height, font); 21620 if (single_line) { 21621 find->first_char = 0; 21622 find->length = z; 21623 } else { 21624 while (i < z) { 21625 prev_start = i; 21626 i += r.num_chars; 21627 nk_textedit_layout_row(&r, state, i, row_height, font); 21628 } 21629 21630 find->first_char = i; 21631 find->length = r.num_chars; 21632 } 21633 find->x = r.x1; 21634 find->y = r.ymin; 21635 find->height = r.ymax - r.ymin; 21636 find->prev_first = prev_start; 21637 return; 21638 } 21639 21640 /* search rows to find the one that straddles character n */ 21641 find->y = 0; 21642 21643 for(;;) { 21644 nk_textedit_layout_row(&r, state, i, row_height, font); 21645 if (n < i + r.num_chars) break; 21646 prev_start = i; 21647 i += r.num_chars; 21648 find->y += r.baseline_y_delta; 21649 } 21650 21651 find->first_char = first = i; 21652 find->length = r.num_chars; 21653 find->height = r.ymax - r.ymin; 21654 find->prev_first = prev_start; 21655 21656 /* now scan to find xpos */ 21657 find->x = r.x0; 21658 for (i=0; first+i < n; ++i) 21659 find->x += nk_textedit_get_width(state, first, i, font); 21660 } 21661 NK_INTERN void 21662 nk_textedit_clamp(struct nk_text_edit *state) 21663 { 21664 /* make the selection/cursor state valid if client altered the string */ 21665 int n = state->string.len; 21666 if (NK_TEXT_HAS_SELECTION(state)) { 21667 if (state->select_start > n) state->select_start = n; 21668 if (state->select_end > n) state->select_end = n; 21669 /* if clamping forced them to be equal, move the cursor to match */ 21670 if (state->select_start == state->select_end) 21671 state->cursor = state->select_start; 21672 } 21673 if (state->cursor > n) state->cursor = n; 21674 } 21675 NK_API void 21676 nk_textedit_delete(struct nk_text_edit *state, int where, int len) 21677 { 21678 /* delete characters while updating undo */ 21679 nk_textedit_makeundo_delete(state, where, len); 21680 nk_str_delete_runes(&state->string, where, len); 21681 state->has_preferred_x = 0; 21682 } 21683 NK_API void 21684 nk_textedit_delete_selection(struct nk_text_edit *state) 21685 { 21686 /* delete the section */ 21687 nk_textedit_clamp(state); 21688 if (NK_TEXT_HAS_SELECTION(state)) { 21689 if (state->select_start < state->select_end) { 21690 nk_textedit_delete(state, state->select_start, 21691 state->select_end - state->select_start); 21692 state->select_end = state->cursor = state->select_start; 21693 } else { 21694 nk_textedit_delete(state, state->select_end, 21695 state->select_start - state->select_end); 21696 state->select_start = state->cursor = state->select_end; 21697 } 21698 state->has_preferred_x = 0; 21699 } 21700 } 21701 NK_INTERN void 21702 nk_textedit_sortselection(struct nk_text_edit *state) 21703 { 21704 /* canonicalize the selection so start <= end */ 21705 if (state->select_end < state->select_start) { 21706 int temp = state->select_end; 21707 state->select_end = state->select_start; 21708 state->select_start = temp; 21709 } 21710 } 21711 NK_INTERN void 21712 nk_textedit_move_to_first(struct nk_text_edit *state) 21713 { 21714 /* move cursor to first character of selection */ 21715 if (NK_TEXT_HAS_SELECTION(state)) { 21716 nk_textedit_sortselection(state); 21717 state->cursor = state->select_start; 21718 state->select_end = state->select_start; 21719 state->has_preferred_x = 0; 21720 } 21721 } 21722 NK_INTERN void 21723 nk_textedit_move_to_last(struct nk_text_edit *state) 21724 { 21725 /* move cursor to last character of selection */ 21726 if (NK_TEXT_HAS_SELECTION(state)) { 21727 nk_textedit_sortselection(state); 21728 nk_textedit_clamp(state); 21729 state->cursor = state->select_end; 21730 state->select_start = state->select_end; 21731 state->has_preferred_x = 0; 21732 } 21733 } 21734 NK_INTERN int 21735 nk_is_word_boundary( struct nk_text_edit *state, int idx) 21736 { 21737 int len; 21738 nk_rune c; 21739 if (idx <= 0) return 1; 21740 if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1; 21741 return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' || 21742 c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || 21743 c == '|'); 21744 } 21745 NK_INTERN int 21746 nk_textedit_move_to_word_previous(struct nk_text_edit *state) 21747 { 21748 int c = state->cursor - 1; 21749 while( c >= 0 && !nk_is_word_boundary(state, c)) 21750 --c; 21751 21752 if( c < 0 ) 21753 c = 0; 21754 21755 return c; 21756 } 21757 NK_INTERN int 21758 nk_textedit_move_to_word_next(struct nk_text_edit *state) 21759 { 21760 const int len = state->string.len; 21761 int c = state->cursor+1; 21762 while( c < len && !nk_is_word_boundary(state, c)) 21763 ++c; 21764 21765 if( c > len ) 21766 c = len; 21767 21768 return c; 21769 } 21770 NK_INTERN void 21771 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state) 21772 { 21773 /* update selection and cursor to match each other */ 21774 if (!NK_TEXT_HAS_SELECTION(state)) 21775 state->select_start = state->select_end = state->cursor; 21776 else state->cursor = state->select_end; 21777 } 21778 NK_API int 21779 nk_textedit_cut(struct nk_text_edit *state) 21780 { 21781 /* API cut: delete selection */ 21782 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 21783 return 0; 21784 if (NK_TEXT_HAS_SELECTION(state)) { 21785 nk_textedit_delete_selection(state); /* implicitly clamps */ 21786 state->has_preferred_x = 0; 21787 return 1; 21788 } 21789 return 0; 21790 } 21791 NK_API int 21792 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len) 21793 { 21794 /* API paste: replace existing selection with passed-in text */ 21795 int glyphs; 21796 const char *text = (const char *) ctext; 21797 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0; 21798 21799 /* if there's a selection, the paste should delete it */ 21800 nk_textedit_clamp(state); 21801 nk_textedit_delete_selection(state); 21802 21803 /* try to insert the characters */ 21804 glyphs = nk_utf_len(ctext, len); 21805 if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) { 21806 nk_textedit_makeundo_insert(state, state->cursor, glyphs); 21807 state->cursor += len; 21808 state->has_preferred_x = 0; 21809 return 1; 21810 } 21811 /* remove the undo since we didn't actually insert the characters */ 21812 if (state->undo.undo_point) 21813 --state->undo.undo_point; 21814 return 0; 21815 } 21816 NK_API void 21817 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len) 21818 { 21819 nk_rune unicode; 21820 int glyph_len; 21821 int text_len = 0; 21822 21823 NK_ASSERT(state); 21824 NK_ASSERT(text); 21825 if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return; 21826 21827 glyph_len = nk_utf_decode(text, &unicode, total_len); 21828 while ((text_len < total_len) && glyph_len) 21829 { 21830 /* don't insert a backward delete, just process the event */ 21831 if (unicode == 127) goto next; 21832 /* can't add newline in single-line mode */ 21833 if (unicode == '\n' && state->single_line) goto next; 21834 /* filter incoming text */ 21835 if (state->filter && !state->filter(state, unicode)) goto next; 21836 21837 if (!NK_TEXT_HAS_SELECTION(state) && 21838 state->cursor < state->string.len) 21839 { 21840 if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) { 21841 nk_textedit_makeundo_replace(state, state->cursor, 1, 1); 21842 nk_str_delete_runes(&state->string, state->cursor, 1); 21843 } 21844 if (nk_str_insert_text_utf8(&state->string, state->cursor, 21845 text+text_len, 1)) 21846 { 21847 ++state->cursor; 21848 state->has_preferred_x = 0; 21849 } 21850 } else { 21851 nk_textedit_delete_selection(state); /* implicitly clamps */ 21852 if (nk_str_insert_text_utf8(&state->string, state->cursor, 21853 text+text_len, 1)) 21854 { 21855 nk_textedit_makeundo_insert(state, state->cursor, 1); 21856 ++state->cursor; 21857 state->has_preferred_x = 0; 21858 } 21859 } 21860 next: 21861 text_len += glyph_len; 21862 glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); 21863 } 21864 } 21865 NK_LIB void 21866 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, 21867 const struct nk_user_font *font, float row_height) 21868 { 21869 retry: 21870 switch (key) 21871 { 21872 case NK_KEY_NONE: 21873 case NK_KEY_CTRL: 21874 case NK_KEY_ENTER: 21875 case NK_KEY_SHIFT: 21876 case NK_KEY_TAB: 21877 case NK_KEY_COPY: 21878 case NK_KEY_CUT: 21879 case NK_KEY_PASTE: 21880 case NK_KEY_MAX: 21881 default: break; 21882 case NK_KEY_TEXT_UNDO: 21883 nk_textedit_undo(state); 21884 state->has_preferred_x = 0; 21885 break; 21886 21887 case NK_KEY_TEXT_REDO: 21888 nk_textedit_redo(state); 21889 state->has_preferred_x = 0; 21890 break; 21891 21892 case NK_KEY_TEXT_SELECT_ALL: 21893 nk_textedit_select_all(state); 21894 state->has_preferred_x = 0; 21895 break; 21896 21897 case NK_KEY_TEXT_INSERT_MODE: 21898 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 21899 state->mode = NK_TEXT_EDIT_MODE_INSERT; 21900 break; 21901 case NK_KEY_TEXT_REPLACE_MODE: 21902 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 21903 state->mode = NK_TEXT_EDIT_MODE_REPLACE; 21904 break; 21905 case NK_KEY_TEXT_RESET_MODE: 21906 if (state->mode == NK_TEXT_EDIT_MODE_INSERT || 21907 state->mode == NK_TEXT_EDIT_MODE_REPLACE) 21908 state->mode = NK_TEXT_EDIT_MODE_VIEW; 21909 break; 21910 21911 case NK_KEY_LEFT: 21912 if (shift_mod) { 21913 nk_textedit_clamp(state); 21914 nk_textedit_prep_selection_at_cursor(state); 21915 /* move selection left */ 21916 if (state->select_end > 0) 21917 --state->select_end; 21918 state->cursor = state->select_end; 21919 state->has_preferred_x = 0; 21920 } else { 21921 /* if currently there's a selection, 21922 * move cursor to start of selection */ 21923 if (NK_TEXT_HAS_SELECTION(state)) 21924 nk_textedit_move_to_first(state); 21925 else if (state->cursor > 0) 21926 --state->cursor; 21927 state->has_preferred_x = 0; 21928 } break; 21929 21930 case NK_KEY_RIGHT: 21931 if (shift_mod) { 21932 nk_textedit_prep_selection_at_cursor(state); 21933 /* move selection right */ 21934 ++state->select_end; 21935 nk_textedit_clamp(state); 21936 state->cursor = state->select_end; 21937 state->has_preferred_x = 0; 21938 } else { 21939 /* if currently there's a selection, 21940 * move cursor to end of selection */ 21941 if (NK_TEXT_HAS_SELECTION(state)) 21942 nk_textedit_move_to_last(state); 21943 else ++state->cursor; 21944 nk_textedit_clamp(state); 21945 state->has_preferred_x = 0; 21946 } break; 21947 21948 case NK_KEY_TEXT_WORD_LEFT: 21949 if (shift_mod) { 21950 if( !NK_TEXT_HAS_SELECTION( state ) ) 21951 nk_textedit_prep_selection_at_cursor(state); 21952 state->cursor = nk_textedit_move_to_word_previous(state); 21953 state->select_end = state->cursor; 21954 nk_textedit_clamp(state ); 21955 } else { 21956 if (NK_TEXT_HAS_SELECTION(state)) 21957 nk_textedit_move_to_first(state); 21958 else { 21959 state->cursor = nk_textedit_move_to_word_previous(state); 21960 nk_textedit_clamp(state ); 21961 } 21962 } break; 21963 21964 case NK_KEY_TEXT_WORD_RIGHT: 21965 if (shift_mod) { 21966 if( !NK_TEXT_HAS_SELECTION( state ) ) 21967 nk_textedit_prep_selection_at_cursor(state); 21968 state->cursor = nk_textedit_move_to_word_next(state); 21969 state->select_end = state->cursor; 21970 nk_textedit_clamp(state); 21971 } else { 21972 if (NK_TEXT_HAS_SELECTION(state)) 21973 nk_textedit_move_to_last(state); 21974 else { 21975 state->cursor = nk_textedit_move_to_word_next(state); 21976 nk_textedit_clamp(state ); 21977 } 21978 } break; 21979 21980 case NK_KEY_DOWN: { 21981 struct nk_text_find find; 21982 struct nk_text_edit_row row; 21983 int i, sel = shift_mod; 21984 21985 if (state->single_line) { 21986 /* on windows, up&down in single-line behave like left&right */ 21987 key = NK_KEY_RIGHT; 21988 goto retry; 21989 } 21990 21991 if (sel) 21992 nk_textedit_prep_selection_at_cursor(state); 21993 else if (NK_TEXT_HAS_SELECTION(state)) 21994 nk_textedit_move_to_last(state); 21995 21996 /* compute current position of cursor point */ 21997 nk_textedit_clamp(state); 21998 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 21999 font, row_height); 22000 22001 /* now find character position down a row */ 22002 if (find.length) 22003 { 22004 float x; 22005 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 22006 int start = find.first_char + find.length; 22007 22008 state->cursor = start; 22009 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 22010 x = row.x0; 22011 22012 for (i=0; i < row.num_chars && x < row.x1; ++i) { 22013 float dx = nk_textedit_get_width(state, start, i, font); 22014 x += dx; 22015 if (x > goal_x) 22016 break; 22017 ++state->cursor; 22018 } 22019 nk_textedit_clamp(state); 22020 22021 state->has_preferred_x = 1; 22022 state->preferred_x = goal_x; 22023 if (sel) 22024 state->select_end = state->cursor; 22025 } 22026 } break; 22027 22028 case NK_KEY_UP: { 22029 struct nk_text_find find; 22030 struct nk_text_edit_row row; 22031 int i, sel = shift_mod; 22032 22033 if (state->single_line) { 22034 /* on windows, up&down become left&right */ 22035 key = NK_KEY_LEFT; 22036 goto retry; 22037 } 22038 22039 if (sel) 22040 nk_textedit_prep_selection_at_cursor(state); 22041 else if (NK_TEXT_HAS_SELECTION(state)) 22042 nk_textedit_move_to_first(state); 22043 22044 /* compute current position of cursor point */ 22045 nk_textedit_clamp(state); 22046 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22047 font, row_height); 22048 22049 /* can only go up if there's a previous row */ 22050 if (find.prev_first != find.first_char) { 22051 /* now find character position up a row */ 22052 float x; 22053 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 22054 22055 state->cursor = find.prev_first; 22056 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 22057 x = row.x0; 22058 22059 for (i=0; i < row.num_chars && x < row.x1; ++i) { 22060 float dx = nk_textedit_get_width(state, find.prev_first, i, font); 22061 x += dx; 22062 if (x > goal_x) 22063 break; 22064 ++state->cursor; 22065 } 22066 nk_textedit_clamp(state); 22067 22068 state->has_preferred_x = 1; 22069 state->preferred_x = goal_x; 22070 if (sel) state->select_end = state->cursor; 22071 } 22072 } break; 22073 22074 case NK_KEY_DEL: 22075 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22076 break; 22077 if (NK_TEXT_HAS_SELECTION(state)) 22078 nk_textedit_delete_selection(state); 22079 else { 22080 int n = state->string.len; 22081 if (state->cursor < n) 22082 nk_textedit_delete(state, state->cursor, 1); 22083 } 22084 state->has_preferred_x = 0; 22085 break; 22086 22087 case NK_KEY_BACKSPACE: 22088 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22089 break; 22090 if (NK_TEXT_HAS_SELECTION(state)) 22091 nk_textedit_delete_selection(state); 22092 else { 22093 nk_textedit_clamp(state); 22094 if (state->cursor > 0) { 22095 nk_textedit_delete(state, state->cursor-1, 1); 22096 --state->cursor; 22097 } 22098 } 22099 state->has_preferred_x = 0; 22100 break; 22101 22102 case NK_KEY_TEXT_START: 22103 if (shift_mod) { 22104 nk_textedit_prep_selection_at_cursor(state); 22105 state->cursor = state->select_end = 0; 22106 state->has_preferred_x = 0; 22107 } else { 22108 state->cursor = state->select_start = state->select_end = 0; 22109 state->has_preferred_x = 0; 22110 } 22111 break; 22112 22113 case NK_KEY_TEXT_END: 22114 if (shift_mod) { 22115 nk_textedit_prep_selection_at_cursor(state); 22116 state->cursor = state->select_end = state->string.len; 22117 state->has_preferred_x = 0; 22118 } else { 22119 state->cursor = state->string.len; 22120 state->select_start = state->select_end = 0; 22121 state->has_preferred_x = 0; 22122 } 22123 break; 22124 22125 case NK_KEY_TEXT_LINE_START: { 22126 if (shift_mod) { 22127 struct nk_text_find find; 22128 nk_textedit_clamp(state); 22129 nk_textedit_prep_selection_at_cursor(state); 22130 if (state->string.len && state->cursor == state->string.len) 22131 --state->cursor; 22132 nk_textedit_find_charpos(&find, state,state->cursor, state->single_line, 22133 font, row_height); 22134 state->cursor = state->select_end = find.first_char; 22135 state->has_preferred_x = 0; 22136 } else { 22137 struct nk_text_find find; 22138 if (state->string.len && state->cursor == state->string.len) 22139 --state->cursor; 22140 nk_textedit_clamp(state); 22141 nk_textedit_move_to_first(state); 22142 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22143 font, row_height); 22144 state->cursor = find.first_char; 22145 state->has_preferred_x = 0; 22146 } 22147 } break; 22148 22149 case NK_KEY_TEXT_LINE_END: { 22150 if (shift_mod) { 22151 struct nk_text_find find; 22152 nk_textedit_clamp(state); 22153 nk_textedit_prep_selection_at_cursor(state); 22154 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22155 font, row_height); 22156 state->has_preferred_x = 0; 22157 state->cursor = find.first_char + find.length; 22158 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 22159 --state->cursor; 22160 state->select_end = state->cursor; 22161 } else { 22162 struct nk_text_find find; 22163 nk_textedit_clamp(state); 22164 nk_textedit_move_to_first(state); 22165 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22166 font, row_height); 22167 22168 state->has_preferred_x = 0; 22169 state->cursor = find.first_char + find.length; 22170 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 22171 --state->cursor; 22172 }} break; 22173 } 22174 } 22175 NK_INTERN void 22176 nk_textedit_flush_redo(struct nk_text_undo_state *state) 22177 { 22178 state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 22179 state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 22180 } 22181 NK_INTERN void 22182 nk_textedit_discard_undo(struct nk_text_undo_state *state) 22183 { 22184 /* discard the oldest entry in the undo list */ 22185 if (state->undo_point > 0) { 22186 /* if the 0th undo state has characters, clean those up */ 22187 if (state->undo_rec[0].char_storage >= 0) { 22188 int n = state->undo_rec[0].insert_length, i; 22189 /* delete n characters from all other records */ 22190 state->undo_char_point = (short)(state->undo_char_point - n); 22191 NK_MEMCPY(state->undo_char, state->undo_char + n, 22192 (nk_size)state->undo_char_point*sizeof(nk_rune)); 22193 for (i=0; i < state->undo_point; ++i) { 22194 if (state->undo_rec[i].char_storage >= 0) 22195 state->undo_rec[i].char_storage = (short) 22196 (state->undo_rec[i].char_storage - n); 22197 } 22198 } 22199 --state->undo_point; 22200 NK_MEMCPY(state->undo_rec, state->undo_rec+1, 22201 (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0]))); 22202 } 22203 } 22204 NK_INTERN void 22205 nk_textedit_discard_redo(struct nk_text_undo_state *state) 22206 { 22207 /* discard the oldest entry in the redo list--it's bad if this 22208 ever happens, but because undo & redo have to store the actual 22209 characters in different cases, the redo character buffer can 22210 fill up even though the undo buffer didn't */ 22211 nk_size num; 22212 int k = NK_TEXTEDIT_UNDOSTATECOUNT-1; 22213 if (state->redo_point <= k) { 22214 /* if the k'th undo state has characters, clean those up */ 22215 if (state->undo_rec[k].char_storage >= 0) { 22216 int n = state->undo_rec[k].insert_length, i; 22217 /* delete n characters from all other records */ 22218 state->redo_char_point = (short)(state->redo_char_point + n); 22219 num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point); 22220 NK_MEMCPY(state->undo_char + state->redo_char_point, 22221 state->undo_char + state->redo_char_point-n, num * sizeof(char)); 22222 for (i = state->redo_point; i < k; ++i) { 22223 if (state->undo_rec[i].char_storage >= 0) { 22224 state->undo_rec[i].char_storage = (short) 22225 (state->undo_rec[i].char_storage + n); 22226 } 22227 } 22228 } 22229 ++state->redo_point; 22230 num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point); 22231 if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1, 22232 state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0])); 22233 } 22234 } 22235 NK_INTERN struct nk_text_undo_record* 22236 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars) 22237 { 22238 /* any time we create a new undo record, we discard redo*/ 22239 nk_textedit_flush_redo(state); 22240 22241 /* if we have no free records, we have to make room, 22242 * by sliding the existing records down */ 22243 if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22244 nk_textedit_discard_undo(state); 22245 22246 /* if the characters to store won't possibly fit in the buffer, 22247 * we can't undo */ 22248 if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) { 22249 state->undo_point = 0; 22250 state->undo_char_point = 0; 22251 return 0; 22252 } 22253 22254 /* if we don't have enough free characters in the buffer, 22255 * we have to make room */ 22256 while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT) 22257 nk_textedit_discard_undo(state); 22258 return &state->undo_rec[state->undo_point++]; 22259 } 22260 NK_INTERN nk_rune* 22261 nk_textedit_createundo(struct nk_text_undo_state *state, int pos, 22262 int insert_len, int delete_len) 22263 { 22264 struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len); 22265 if (r == 0) 22266 return 0; 22267 22268 r->where = pos; 22269 r->insert_length = (short) insert_len; 22270 r->delete_length = (short) delete_len; 22271 22272 if (insert_len == 0) { 22273 r->char_storage = -1; 22274 return 0; 22275 } else { 22276 r->char_storage = state->undo_char_point; 22277 state->undo_char_point = (short)(state->undo_char_point + insert_len); 22278 return &state->undo_char[r->char_storage]; 22279 } 22280 } 22281 NK_API void 22282 nk_textedit_undo(struct nk_text_edit *state) 22283 { 22284 struct nk_text_undo_state *s = &state->undo; 22285 struct nk_text_undo_record u, *r; 22286 if (s->undo_point == 0) 22287 return; 22288 22289 /* we need to do two things: apply the undo record, and create a redo record */ 22290 u = s->undo_rec[s->undo_point-1]; 22291 r = &s->undo_rec[s->redo_point-1]; 22292 r->char_storage = -1; 22293 22294 r->insert_length = u.delete_length; 22295 r->delete_length = u.insert_length; 22296 r->where = u.where; 22297 22298 if (u.delete_length) 22299 { 22300 /* if the undo record says to delete characters, then the redo record will 22301 need to re-insert the characters that get deleted, so we need to store 22302 them. 22303 there are three cases: 22304 - there's enough room to store the characters 22305 - characters stored for *redoing* don't leave room for redo 22306 - characters stored for *undoing* don't leave room for redo 22307 if the last is true, we have to bail */ 22308 if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) { 22309 /* the undo records take up too much character space; there's no space 22310 * to store the redo characters */ 22311 r->insert_length = 0; 22312 } else { 22313 int i; 22314 /* there's definitely room to store the characters eventually */ 22315 while (s->undo_char_point + u.delete_length > s->redo_char_point) { 22316 /* there's currently not enough room, so discard a redo record */ 22317 nk_textedit_discard_redo(s); 22318 /* should never happen: */ 22319 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22320 return; 22321 } 22322 22323 r = &s->undo_rec[s->redo_point-1]; 22324 r->char_storage = (short)(s->redo_char_point - u.delete_length); 22325 s->redo_char_point = (short)(s->redo_char_point - u.delete_length); 22326 22327 /* now save the characters */ 22328 for (i=0; i < u.delete_length; ++i) 22329 s->undo_char[r->char_storage + i] = 22330 nk_str_rune_at(&state->string, u.where + i); 22331 } 22332 /* now we can carry out the deletion */ 22333 nk_str_delete_runes(&state->string, u.where, u.delete_length); 22334 } 22335 22336 /* check type of recorded action: */ 22337 if (u.insert_length) { 22338 /* easy case: was a deletion, so we need to insert n characters */ 22339 nk_str_insert_text_runes(&state->string, u.where, 22340 &s->undo_char[u.char_storage], u.insert_length); 22341 s->undo_char_point = (short)(s->undo_char_point - u.insert_length); 22342 } 22343 state->cursor = (short)(u.where + u.insert_length); 22344 22345 s->undo_point--; 22346 s->redo_point--; 22347 } 22348 NK_API void 22349 nk_textedit_redo(struct nk_text_edit *state) 22350 { 22351 struct nk_text_undo_state *s = &state->undo; 22352 struct nk_text_undo_record *u, r; 22353 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22354 return; 22355 22356 /* we need to do two things: apply the redo record, and create an undo record */ 22357 u = &s->undo_rec[s->undo_point]; 22358 r = s->undo_rec[s->redo_point]; 22359 22360 /* we KNOW there must be room for the undo record, because the redo record 22361 was derived from an undo record */ 22362 u->delete_length = r.insert_length; 22363 u->insert_length = r.delete_length; 22364 u->where = r.where; 22365 u->char_storage = -1; 22366 22367 if (r.delete_length) { 22368 /* the redo record requires us to delete characters, so the undo record 22369 needs to store the characters */ 22370 if (s->undo_char_point + u->insert_length > s->redo_char_point) { 22371 u->insert_length = 0; 22372 u->delete_length = 0; 22373 } else { 22374 int i; 22375 u->char_storage = s->undo_char_point; 22376 s->undo_char_point = (short)(s->undo_char_point + u->insert_length); 22377 22378 /* now save the characters */ 22379 for (i=0; i < u->insert_length; ++i) { 22380 s->undo_char[u->char_storage + i] = 22381 nk_str_rune_at(&state->string, u->where + i); 22382 } 22383 } 22384 nk_str_delete_runes(&state->string, r.where, r.delete_length); 22385 } 22386 22387 if (r.insert_length) { 22388 /* easy case: need to insert n characters */ 22389 nk_str_insert_text_runes(&state->string, r.where, 22390 &s->undo_char[r.char_storage], r.insert_length); 22391 } 22392 state->cursor = r.where + r.insert_length; 22393 22394 s->undo_point++; 22395 s->redo_point++; 22396 } 22397 NK_INTERN void 22398 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length) 22399 { 22400 nk_textedit_createundo(&state->undo, where, 0, length); 22401 } 22402 NK_INTERN void 22403 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length) 22404 { 22405 int i; 22406 nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0); 22407 if (p) { 22408 for (i=0; i < length; ++i) 22409 p[i] = nk_str_rune_at(&state->string, where+i); 22410 } 22411 } 22412 NK_INTERN void 22413 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where, 22414 int old_length, int new_length) 22415 { 22416 int i; 22417 nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length); 22418 if (p) { 22419 for (i=0; i < old_length; ++i) 22420 p[i] = nk_str_rune_at(&state->string, where+i); 22421 } 22422 } 22423 NK_LIB void 22424 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, 22425 nk_plugin_filter filter) 22426 { 22427 /* reset the state to default */ 22428 state->undo.undo_point = 0; 22429 state->undo.undo_char_point = 0; 22430 state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 22431 state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 22432 state->select_end = state->select_start = 0; 22433 state->cursor = 0; 22434 state->has_preferred_x = 0; 22435 state->preferred_x = 0; 22436 state->cursor_at_end_of_line = 0; 22437 state->initialized = 1; 22438 state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE); 22439 state->mode = NK_TEXT_EDIT_MODE_VIEW; 22440 state->filter = filter; 22441 state->scrollbar = nk_vec2(0,0); 22442 } 22443 NK_API void 22444 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size) 22445 { 22446 NK_ASSERT(state); 22447 NK_ASSERT(memory); 22448 if (!state || !memory || !size) return; 22449 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22450 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22451 nk_str_init_fixed(&state->string, memory, size); 22452 } 22453 NK_API void 22454 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size) 22455 { 22456 NK_ASSERT(state); 22457 NK_ASSERT(alloc); 22458 if (!state || !alloc) return; 22459 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22460 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22461 nk_str_init(&state->string, alloc, size); 22462 } 22463 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 22464 NK_API void 22465 nk_textedit_init_default(struct nk_text_edit *state) 22466 { 22467 NK_ASSERT(state); 22468 if (!state) return; 22469 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22470 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22471 nk_str_init_default(&state->string); 22472 } 22473 #endif 22474 NK_API void 22475 nk_textedit_select_all(struct nk_text_edit *state) 22476 { 22477 NK_ASSERT(state); 22478 state->select_start = 0; 22479 state->select_end = state->string.len; 22480 } 22481 NK_API void 22482 nk_textedit_free(struct nk_text_edit *state) 22483 { 22484 NK_ASSERT(state); 22485 if (!state) return; 22486 nk_str_free(&state->string); 22487 } 22488 22489 22490 22491 22492 22493 /* =============================================================== 22494 * 22495 * FILTER 22496 * 22497 * ===============================================================*/ 22498 NK_API int 22499 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode) 22500 { 22501 NK_UNUSED(unicode); 22502 NK_UNUSED(box); 22503 return nk_true; 22504 } 22505 NK_API int 22506 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode) 22507 { 22508 NK_UNUSED(box); 22509 if (unicode > 128) return nk_false; 22510 else return nk_true; 22511 } 22512 NK_API int 22513 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode) 22514 { 22515 NK_UNUSED(box); 22516 if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') 22517 return nk_false; 22518 else return nk_true; 22519 } 22520 NK_API int 22521 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode) 22522 { 22523 NK_UNUSED(box); 22524 if ((unicode < '0' || unicode > '9') && unicode != '-') 22525 return nk_false; 22526 else return nk_true; 22527 } 22528 NK_API int 22529 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode) 22530 { 22531 NK_UNUSED(box); 22532 if ((unicode < '0' || unicode > '9') && 22533 (unicode < 'a' || unicode > 'f') && 22534 (unicode < 'A' || unicode > 'F')) 22535 return nk_false; 22536 else return nk_true; 22537 } 22538 NK_API int 22539 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode) 22540 { 22541 NK_UNUSED(box); 22542 if (unicode < '0' || unicode > '7') 22543 return nk_false; 22544 else return nk_true; 22545 } 22546 NK_API int 22547 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode) 22548 { 22549 NK_UNUSED(box); 22550 if (unicode != '0' && unicode != '1') 22551 return nk_false; 22552 else return nk_true; 22553 } 22554 22555 /* =============================================================== 22556 * 22557 * EDIT 22558 * 22559 * ===============================================================*/ 22560 NK_LIB void 22561 nk_edit_draw_text(struct nk_command_buffer *out, 22562 const struct nk_style_edit *style, float pos_x, float pos_y, 22563 float x_offset, const char *text, int byte_len, float row_height, 22564 const struct nk_user_font *font, struct nk_color background, 22565 struct nk_color foreground, int is_selected) 22566 { 22567 NK_ASSERT(out); 22568 NK_ASSERT(font); 22569 NK_ASSERT(style); 22570 if (!text || !byte_len || !out || !style) return; 22571 22572 {int glyph_len = 0; 22573 nk_rune unicode = 0; 22574 int text_len = 0; 22575 float line_width = 0; 22576 float glyph_width; 22577 const char *line = text; 22578 float line_offset = 0; 22579 int line_count = 0; 22580 22581 struct nk_text txt; 22582 txt.padding = nk_vec2(0,0); 22583 txt.background = background; 22584 txt.text = foreground; 22585 22586 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len); 22587 if (!glyph_len) return; 22588 while ((text_len < byte_len) && glyph_len) 22589 { 22590 if (unicode == '\n') { 22591 /* new line separator so draw previous line */ 22592 struct nk_rect label; 22593 label.y = pos_y + line_offset; 22594 label.h = row_height; 22595 label.w = line_width; 22596 label.x = pos_x; 22597 if (!line_count) 22598 label.x += x_offset; 22599 22600 if (is_selected) /* selection needs to draw different background color */ 22601 nk_fill_rect(out, label, 0, background); 22602 nk_widget_text(out, label, line, (int)((text + text_len) - line), 22603 &txt, NK_TEXT_CENTERED, font); 22604 22605 text_len++; 22606 line_count++; 22607 line_width = 0; 22608 line = text + text_len; 22609 line_offset += row_height; 22610 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len)); 22611 continue; 22612 } 22613 if (unicode == '\r') { 22614 text_len++; 22615 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 22616 continue; 22617 } 22618 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 22619 line_width += (float)glyph_width; 22620 text_len += glyph_len; 22621 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 22622 continue; 22623 } 22624 if (line_width > 0) { 22625 /* draw last line */ 22626 struct nk_rect label; 22627 label.y = pos_y + line_offset; 22628 label.h = row_height; 22629 label.w = line_width; 22630 label.x = pos_x; 22631 if (!line_count) 22632 label.x += x_offset; 22633 22634 if (is_selected) 22635 nk_fill_rect(out, label, 0, background); 22636 nk_widget_text(out, label, line, (int)((text + text_len) - line), 22637 &txt, NK_TEXT_LEFT, font); 22638 }} 22639 } 22640 NK_LIB nk_flags 22641 nk_do_edit(nk_flags *state, struct nk_command_buffer *out, 22642 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, 22643 struct nk_text_edit *edit, const struct nk_style_edit *style, 22644 struct nk_input *in, const struct nk_user_font *font) 22645 { 22646 struct nk_rect area; 22647 nk_flags ret = 0; 22648 float row_height; 22649 char prev_state = 0; 22650 char is_hovered = 0; 22651 char select_all = 0; 22652 char cursor_follow = 0; 22653 struct nk_rect old_clip; 22654 struct nk_rect clip; 22655 22656 NK_ASSERT(state); 22657 NK_ASSERT(out); 22658 NK_ASSERT(style); 22659 if (!state || !out || !style) 22660 return ret; 22661 22662 /* visible text area calculation */ 22663 area.x = bounds.x + style->padding.x + style->border; 22664 area.y = bounds.y + style->padding.y + style->border; 22665 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border); 22666 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border); 22667 if (flags & NK_EDIT_MULTILINE) 22668 area.w = NK_MAX(0, area.w - style->scrollbar_size.x); 22669 row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h; 22670 22671 /* calculate clipping rectangle */ 22672 old_clip = out->clip; 22673 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h); 22674 22675 /* update edit state */ 22676 prev_state = (char)edit->active; 22677 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds); 22678 if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { 22679 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, 22680 bounds.x, bounds.y, bounds.w, bounds.h); 22681 } 22682 22683 /* (de)activate text editor */ 22684 if (!prev_state && edit->active) { 22685 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ? 22686 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE; 22687 nk_textedit_clear_state(edit, type, filter); 22688 if (flags & NK_EDIT_AUTO_SELECT) 22689 select_all = nk_true; 22690 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) { 22691 edit->cursor = edit->string.len; 22692 in = 0; 22693 } 22694 } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW; 22695 if (flags & NK_EDIT_READ_ONLY) 22696 edit->mode = NK_TEXT_EDIT_MODE_VIEW; 22697 else if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 22698 edit->mode = NK_TEXT_EDIT_MODE_INSERT; 22699 22700 ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE; 22701 if (prev_state != edit->active) 22702 ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED; 22703 22704 /* handle user input */ 22705 if (edit->active && in) 22706 { 22707 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down; 22708 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x; 22709 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y; 22710 22711 /* mouse click handler */ 22712 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area); 22713 if (select_all) { 22714 nk_textedit_select_all(edit); 22715 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 22716 in->mouse.buttons[NK_BUTTON_LEFT].clicked) { 22717 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height); 22718 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 22719 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) { 22720 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height); 22721 cursor_follow = nk_true; 22722 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked && 22723 in->mouse.buttons[NK_BUTTON_RIGHT].down) { 22724 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height); 22725 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height); 22726 cursor_follow = nk_true; 22727 } 22728 22729 {int i; /* keyboard input */ 22730 int old_mode = edit->mode; 22731 for (i = 0; i < NK_KEY_MAX; ++i) { 22732 if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */ 22733 if (nk_input_is_key_pressed(in, (enum nk_keys)i)) { 22734 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height); 22735 cursor_follow = nk_true; 22736 } 22737 } 22738 if (old_mode != edit->mode) { 22739 in->keyboard.text_len = 0; 22740 }} 22741 22742 /* text input */ 22743 edit->filter = filter; 22744 if (in->keyboard.text_len) { 22745 nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len); 22746 cursor_follow = nk_true; 22747 in->keyboard.text_len = 0; 22748 } 22749 22750 /* enter key handler */ 22751 if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) { 22752 cursor_follow = nk_true; 22753 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod) 22754 nk_textedit_text(edit, "\n", 1); 22755 else if (flags & NK_EDIT_SIG_ENTER) 22756 ret |= NK_EDIT_COMMITED; 22757 else nk_textedit_text(edit, "\n", 1); 22758 } 22759 22760 /* cut & copy handler */ 22761 {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY); 22762 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT); 22763 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD)) 22764 { 22765 int glyph_len; 22766 nk_rune unicode; 22767 const char *text; 22768 int b = edit->select_start; 22769 int e = edit->select_end; 22770 22771 int begin = NK_MIN(b, e); 22772 int end = NK_MAX(b, e); 22773 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len); 22774 if (edit->clip.copy) 22775 edit->clip.copy(edit->clip.userdata, text, end - begin); 22776 if (cut && !(flags & NK_EDIT_READ_ONLY)){ 22777 nk_textedit_cut(edit); 22778 cursor_follow = nk_true; 22779 } 22780 }} 22781 22782 /* paste handler */ 22783 {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE); 22784 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) { 22785 edit->clip.paste(edit->clip.userdata, edit); 22786 cursor_follow = nk_true; 22787 }} 22788 22789 /* tab handler */ 22790 {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB); 22791 if (tab && (flags & NK_EDIT_ALLOW_TAB)) { 22792 nk_textedit_text(edit, " ", 4); 22793 cursor_follow = nk_true; 22794 }} 22795 } 22796 22797 /* set widget state */ 22798 if (edit->active) 22799 *state = NK_WIDGET_STATE_ACTIVE; 22800 else nk_widget_state_reset(state); 22801 22802 if (is_hovered) 22803 *state |= NK_WIDGET_STATE_HOVERED; 22804 22805 /* DRAW EDIT */ 22806 {const char *text = nk_str_get_const(&edit->string); 22807 int len = nk_str_len_char(&edit->string); 22808 22809 {/* select background colors/images */ 22810 const struct nk_style_item *background; 22811 if (*state & NK_WIDGET_STATE_ACTIVED) 22812 background = &style->active; 22813 else if (*state & NK_WIDGET_STATE_HOVER) 22814 background = &style->hover; 22815 else background = &style->normal; 22816 22817 /* draw background frame */ 22818 if (background->type == NK_STYLE_ITEM_COLOR) { 22819 nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color); 22820 nk_fill_rect(out, bounds, style->rounding, background->data.color); 22821 } else nk_draw_image(out, bounds, &background->data.image, nk_white);} 22822 22823 area.w = NK_MAX(0, area.w - style->cursor_size); 22824 if (edit->active) 22825 { 22826 int total_lines = 1; 22827 struct nk_vec2 text_size = nk_vec2(0,0); 22828 22829 /* text pointer positions */ 22830 const char *cursor_ptr = 0; 22831 const char *select_begin_ptr = 0; 22832 const char *select_end_ptr = 0; 22833 22834 /* 2D pixel positions */ 22835 struct nk_vec2 cursor_pos = nk_vec2(0,0); 22836 struct nk_vec2 selection_offset_start = nk_vec2(0,0); 22837 struct nk_vec2 selection_offset_end = nk_vec2(0,0); 22838 22839 int selection_begin = NK_MIN(edit->select_start, edit->select_end); 22840 int selection_end = NK_MAX(edit->select_start, edit->select_end); 22841 22842 /* calculate total line count + total space + cursor/selection position */ 22843 float line_width = 0.0f; 22844 if (text && len) 22845 { 22846 /* utf8 encoding */ 22847 float glyph_width; 22848 int glyph_len = 0; 22849 nk_rune unicode = 0; 22850 int text_len = 0; 22851 int glyphs = 0; 22852 int row_begin = 0; 22853 22854 glyph_len = nk_utf_decode(text, &unicode, len); 22855 glyph_width = font->width(font->userdata, font->height, text, glyph_len); 22856 line_width = 0; 22857 22858 /* iterate all lines */ 22859 while ((text_len < len) && glyph_len) 22860 { 22861 /* set cursor 2D position and line */ 22862 if (!cursor_ptr && glyphs == edit->cursor) 22863 { 22864 int glyph_offset; 22865 struct nk_vec2 out_offset; 22866 struct nk_vec2 row_size; 22867 const char *remaining; 22868 22869 /* calculate 2d position */ 22870 cursor_pos.y = (float)(total_lines-1) * row_height; 22871 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 22872 text_len-row_begin, row_height, &remaining, 22873 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 22874 cursor_pos.x = row_size.x; 22875 cursor_ptr = text + text_len; 22876 } 22877 22878 /* set start selection 2D position and line */ 22879 if (!select_begin_ptr && edit->select_start != edit->select_end && 22880 glyphs == selection_begin) 22881 { 22882 int glyph_offset; 22883 struct nk_vec2 out_offset; 22884 struct nk_vec2 row_size; 22885 const char *remaining; 22886 22887 /* calculate 2d position */ 22888 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height; 22889 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 22890 text_len-row_begin, row_height, &remaining, 22891 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 22892 selection_offset_start.x = row_size.x; 22893 select_begin_ptr = text + text_len; 22894 } 22895 22896 /* set end selection 2D position and line */ 22897 if (!select_end_ptr && edit->select_start != edit->select_end && 22898 glyphs == selection_end) 22899 { 22900 int glyph_offset; 22901 struct nk_vec2 out_offset; 22902 struct nk_vec2 row_size; 22903 const char *remaining; 22904 22905 /* calculate 2d position */ 22906 selection_offset_end.y = (float)(total_lines-1) * row_height; 22907 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 22908 text_len-row_begin, row_height, &remaining, 22909 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 22910 selection_offset_end.x = row_size.x; 22911 select_end_ptr = text + text_len; 22912 } 22913 if (unicode == '\n') { 22914 text_size.x = NK_MAX(text_size.x, line_width); 22915 total_lines++; 22916 line_width = 0; 22917 text_len++; 22918 glyphs++; 22919 row_begin = text_len; 22920 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 22921 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 22922 continue; 22923 } 22924 22925 glyphs++; 22926 text_len += glyph_len; 22927 line_width += (float)glyph_width; 22928 22929 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 22930 glyph_width = font->width(font->userdata, font->height, 22931 text+text_len, glyph_len); 22932 continue; 22933 } 22934 text_size.y = (float)total_lines * row_height; 22935 22936 /* handle case when cursor is at end of text buffer */ 22937 if (!cursor_ptr && edit->cursor == edit->string.len) { 22938 cursor_pos.x = line_width; 22939 cursor_pos.y = text_size.y - row_height; 22940 } 22941 } 22942 { 22943 /* scrollbar */ 22944 if (cursor_follow) 22945 { 22946 /* update scrollbar to follow cursor */ 22947 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) { 22948 /* horizontal scroll */ 22949 const float scroll_increment = area.w * 0.25f; 22950 if (cursor_pos.x < edit->scrollbar.x) 22951 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment); 22952 if (cursor_pos.x >= edit->scrollbar.x + area.w) 22953 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment); 22954 } else edit->scrollbar.x = 0; 22955 22956 if (flags & NK_EDIT_MULTILINE) { 22957 /* vertical scroll */ 22958 if (cursor_pos.y < edit->scrollbar.y) 22959 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height); 22960 if (cursor_pos.y >= edit->scrollbar.y + area.h) 22961 edit->scrollbar.y = edit->scrollbar.y + row_height; 22962 } else edit->scrollbar.y = 0; 22963 } 22964 22965 /* scrollbar widget */ 22966 if (flags & NK_EDIT_MULTILINE) 22967 { 22968 nk_flags ws; 22969 struct nk_rect scroll; 22970 float scroll_target; 22971 float scroll_offset; 22972 float scroll_step; 22973 float scroll_inc; 22974 22975 scroll = area; 22976 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x; 22977 scroll.w = style->scrollbar_size.x; 22978 22979 scroll_offset = edit->scrollbar.y; 22980 scroll_step = scroll.h * 0.10f; 22981 scroll_inc = scroll.h * 0.01f; 22982 scroll_target = text_size.y; 22983 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0, 22984 scroll_offset, scroll_target, scroll_step, scroll_inc, 22985 &style->scrollbar, in, font); 22986 } 22987 } 22988 22989 /* draw text */ 22990 {struct nk_color background_color; 22991 struct nk_color text_color; 22992 struct nk_color sel_background_color; 22993 struct nk_color sel_text_color; 22994 struct nk_color cursor_color; 22995 struct nk_color cursor_text_color; 22996 const struct nk_style_item *background; 22997 nk_push_scissor(out, clip); 22998 22999 /* select correct colors to draw */ 23000 if (*state & NK_WIDGET_STATE_ACTIVED) { 23001 background = &style->active; 23002 text_color = style->text_active; 23003 sel_text_color = style->selected_text_hover; 23004 sel_background_color = style->selected_hover; 23005 cursor_color = style->cursor_hover; 23006 cursor_text_color = style->cursor_text_hover; 23007 } else if (*state & NK_WIDGET_STATE_HOVER) { 23008 background = &style->hover; 23009 text_color = style->text_hover; 23010 sel_text_color = style->selected_text_hover; 23011 sel_background_color = style->selected_hover; 23012 cursor_text_color = style->cursor_text_hover; 23013 cursor_color = style->cursor_hover; 23014 } else { 23015 background = &style->normal; 23016 text_color = style->text_normal; 23017 sel_text_color = style->selected_text_normal; 23018 sel_background_color = style->selected_normal; 23019 cursor_color = style->cursor_normal; 23020 cursor_text_color = style->cursor_text_normal; 23021 } 23022 if (background->type == NK_STYLE_ITEM_IMAGE) 23023 background_color = nk_rgba(0,0,0,0); 23024 else background_color = background->data.color; 23025 23026 23027 if (edit->select_start == edit->select_end) { 23028 /* no selection so just draw the complete text */ 23029 const char *begin = nk_str_get_const(&edit->string); 23030 int l = nk_str_len_char(&edit->string); 23031 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23032 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 23033 background_color, text_color, nk_false); 23034 } else { 23035 /* edit has selection so draw 1-3 text chunks */ 23036 if (edit->select_start != edit->select_end && selection_begin > 0){ 23037 /* draw unselected text before selection */ 23038 const char *begin = nk_str_get_const(&edit->string); 23039 NK_ASSERT(select_begin_ptr); 23040 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23041 area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin), 23042 row_height, font, background_color, text_color, nk_false); 23043 } 23044 if (edit->select_start != edit->select_end) { 23045 /* draw selected text */ 23046 NK_ASSERT(select_begin_ptr); 23047 if (!select_end_ptr) { 23048 const char *begin = nk_str_get_const(&edit->string); 23049 select_end_ptr = begin + nk_str_len_char(&edit->string); 23050 } 23051 nk_edit_draw_text(out, style, 23052 area.x - edit->scrollbar.x, 23053 area.y + selection_offset_start.y - edit->scrollbar.y, 23054 selection_offset_start.x, 23055 select_begin_ptr, (int)(select_end_ptr - select_begin_ptr), 23056 row_height, font, sel_background_color, sel_text_color, nk_true); 23057 } 23058 if ((edit->select_start != edit->select_end && 23059 selection_end < edit->string.len)) 23060 { 23061 /* draw unselected text after selected text */ 23062 const char *begin = select_end_ptr; 23063 const char *end = nk_str_get_const(&edit->string) + 23064 nk_str_len_char(&edit->string); 23065 NK_ASSERT(select_end_ptr); 23066 nk_edit_draw_text(out, style, 23067 area.x - edit->scrollbar.x, 23068 area.y + selection_offset_end.y - edit->scrollbar.y, 23069 selection_offset_end.x, 23070 begin, (int)(end - begin), row_height, font, 23071 background_color, text_color, nk_true); 23072 } 23073 } 23074 23075 /* cursor */ 23076 if (edit->select_start == edit->select_end) 23077 { 23078 if (edit->cursor >= nk_str_len(&edit->string) || 23079 (cursor_ptr && *cursor_ptr == '\n')) { 23080 /* draw cursor at end of line */ 23081 struct nk_rect cursor; 23082 cursor.w = style->cursor_size; 23083 cursor.h = font->height; 23084 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x; 23085 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f; 23086 cursor.y -= edit->scrollbar.y; 23087 nk_fill_rect(out, cursor, 0, cursor_color); 23088 } else { 23089 /* draw cursor inside text */ 23090 int glyph_len; 23091 struct nk_rect label; 23092 struct nk_text txt; 23093 23094 nk_rune unicode; 23095 NK_ASSERT(cursor_ptr); 23096 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4); 23097 23098 label.x = area.x + cursor_pos.x - edit->scrollbar.x; 23099 label.y = area.y + cursor_pos.y - edit->scrollbar.y; 23100 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len); 23101 label.h = row_height; 23102 23103 txt.padding = nk_vec2(0,0); 23104 txt.background = cursor_color;; 23105 txt.text = cursor_text_color; 23106 nk_fill_rect(out, label, 0, cursor_color); 23107 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font); 23108 } 23109 }} 23110 } else { 23111 /* not active so just draw text */ 23112 int l = nk_str_len_char(&edit->string); 23113 const char *begin = nk_str_get_const(&edit->string); 23114 23115 const struct nk_style_item *background; 23116 struct nk_color background_color; 23117 struct nk_color text_color; 23118 nk_push_scissor(out, clip); 23119 if (*state & NK_WIDGET_STATE_ACTIVED) { 23120 background = &style->active; 23121 text_color = style->text_active; 23122 } else if (*state & NK_WIDGET_STATE_HOVER) { 23123 background = &style->hover; 23124 text_color = style->text_hover; 23125 } else { 23126 background = &style->normal; 23127 text_color = style->text_normal; 23128 } 23129 if (background->type == NK_STYLE_ITEM_IMAGE) 23130 background_color = nk_rgba(0,0,0,0); 23131 else background_color = background->data.color; 23132 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23133 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 23134 background_color, text_color, nk_false); 23135 } 23136 nk_push_scissor(out, old_clip);} 23137 return ret; 23138 } 23139 NK_API void 23140 nk_edit_focus(struct nk_context *ctx, nk_flags flags) 23141 { 23142 nk_hash hash; 23143 struct nk_window *win; 23144 23145 NK_ASSERT(ctx); 23146 NK_ASSERT(ctx->current); 23147 if (!ctx || !ctx->current) return; 23148 23149 win = ctx->current; 23150 hash = win->edit.seq; 23151 win->edit.active = nk_true; 23152 win->edit.name = hash; 23153 if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 23154 win->edit.mode = NK_TEXT_EDIT_MODE_INSERT; 23155 } 23156 NK_API void 23157 nk_edit_unfocus(struct nk_context *ctx) 23158 { 23159 struct nk_window *win; 23160 NK_ASSERT(ctx); 23161 NK_ASSERT(ctx->current); 23162 if (!ctx || !ctx->current) return; 23163 23164 win = ctx->current; 23165 win->edit.active = nk_false; 23166 win->edit.name = 0; 23167 } 23168 NK_API nk_flags 23169 nk_edit_string(struct nk_context *ctx, nk_flags flags, 23170 char *memory, int *len, int max, nk_plugin_filter filter) 23171 { 23172 nk_hash hash; 23173 nk_flags state; 23174 struct nk_text_edit *edit; 23175 struct nk_window *win; 23176 23177 NK_ASSERT(ctx); 23178 NK_ASSERT(memory); 23179 NK_ASSERT(len); 23180 if (!ctx || !memory || !len) 23181 return 0; 23182 23183 filter = (!filter) ? nk_filter_default: filter; 23184 win = ctx->current; 23185 hash = win->edit.seq; 23186 edit = &ctx->text_edit; 23187 nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)? 23188 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter); 23189 23190 if (win->edit.active && hash == win->edit.name) { 23191 if (flags & NK_EDIT_NO_CURSOR) 23192 edit->cursor = nk_utf_len(memory, *len); 23193 else edit->cursor = win->edit.cursor; 23194 if (!(flags & NK_EDIT_SELECTABLE)) { 23195 edit->select_start = win->edit.cursor; 23196 edit->select_end = win->edit.cursor; 23197 } else { 23198 edit->select_start = win->edit.sel_start; 23199 edit->select_end = win->edit.sel_end; 23200 } 23201 edit->mode = win->edit.mode; 23202 edit->scrollbar.x = (float)win->edit.scrollbar.x; 23203 edit->scrollbar.y = (float)win->edit.scrollbar.y; 23204 edit->active = nk_true; 23205 } else edit->active = nk_false; 23206 23207 max = NK_MAX(1, max); 23208 *len = NK_MIN(*len, max-1); 23209 nk_str_init_fixed(&edit->string, memory, (nk_size)max); 23210 edit->string.buffer.allocated = (nk_size)*len; 23211 edit->string.len = nk_utf_len(memory, *len); 23212 state = nk_edit_buffer(ctx, flags, edit, filter); 23213 *len = (int)edit->string.buffer.allocated; 23214 23215 if (edit->active) { 23216 win->edit.cursor = edit->cursor; 23217 win->edit.sel_start = edit->select_start; 23218 win->edit.sel_end = edit->select_end; 23219 win->edit.mode = edit->mode; 23220 win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x; 23221 win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y; 23222 } return state; 23223 } 23224 NK_API nk_flags 23225 nk_edit_buffer(struct nk_context *ctx, nk_flags flags, 23226 struct nk_text_edit *edit, nk_plugin_filter filter) 23227 { 23228 struct nk_window *win; 23229 struct nk_style *style; 23230 struct nk_input *in; 23231 23232 enum nk_widget_layout_states state; 23233 struct nk_rect bounds; 23234 23235 nk_flags ret_flags = 0; 23236 unsigned char prev_state; 23237 nk_hash hash; 23238 23239 /* make sure correct values */ 23240 NK_ASSERT(ctx); 23241 NK_ASSERT(edit); 23242 NK_ASSERT(ctx->current); 23243 NK_ASSERT(ctx->current->layout); 23244 if (!ctx || !ctx->current || !ctx->current->layout) 23245 return 0; 23246 23247 win = ctx->current; 23248 style = &ctx->style; 23249 state = nk_widget(&bounds, ctx); 23250 if (!state) return state; 23251 in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 23252 23253 /* check if edit is currently hot item */ 23254 hash = win->edit.seq++; 23255 if (win->edit.active && hash == win->edit.name) { 23256 if (flags & NK_EDIT_NO_CURSOR) 23257 edit->cursor = edit->string.len; 23258 if (!(flags & NK_EDIT_SELECTABLE)) { 23259 edit->select_start = edit->cursor; 23260 edit->select_end = edit->cursor; 23261 } 23262 if (flags & NK_EDIT_CLIPBOARD) 23263 edit->clip = ctx->clip; 23264 edit->active = (unsigned char)win->edit.active; 23265 } else edit->active = nk_false; 23266 edit->mode = win->edit.mode; 23267 23268 filter = (!filter) ? nk_filter_default: filter; 23269 prev_state = (unsigned char)edit->active; 23270 in = (flags & NK_EDIT_READ_ONLY) ? 0: in; 23271 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags, 23272 filter, edit, &style->edit, in, style->font); 23273 23274 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 23275 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT]; 23276 if (edit->active && prev_state != edit->active) { 23277 /* current edit is now hot */ 23278 win->edit.active = nk_true; 23279 win->edit.name = hash; 23280 } else if (prev_state && !edit->active) { 23281 /* current edit is now cold */ 23282 win->edit.active = nk_false; 23283 } return ret_flags; 23284 } 23285 NK_API nk_flags 23286 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags, 23287 char *buffer, int max, nk_plugin_filter filter) 23288 { 23289 nk_flags result; 23290 int len = nk_strlen(buffer); 23291 result = nk_edit_string(ctx, flags, buffer, &len, max, filter); 23292 buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0'; 23293 return result; 23294 } 23295 23296 23297 23298 23299 23300 /* =============================================================== 23301 * 23302 * PROPERTY 23303 * 23304 * ===============================================================*/ 23305 NK_LIB void 23306 nk_drag_behavior(nk_flags *state, const struct nk_input *in, 23307 struct nk_rect drag, struct nk_property_variant *variant, 23308 float inc_per_pixel) 23309 { 23310 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 23311 int left_mouse_click_in_cursor = in && 23312 nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true); 23313 23314 nk_widget_state_reset(state); 23315 if (nk_input_is_mouse_hovering_rect(in, drag)) 23316 *state = NK_WIDGET_STATE_HOVERED; 23317 23318 if (left_mouse_down && left_mouse_click_in_cursor) { 23319 float delta, pixels; 23320 pixels = in->mouse.delta.x; 23321 delta = pixels * inc_per_pixel; 23322 switch (variant->kind) { 23323 default: break; 23324 case NK_PROPERTY_INT: 23325 variant->value.i = variant->value.i + (int)delta; 23326 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 23327 break; 23328 case NK_PROPERTY_FLOAT: 23329 variant->value.f = variant->value.f + (float)delta; 23330 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 23331 break; 23332 case NK_PROPERTY_DOUBLE: 23333 variant->value.d = variant->value.d + (double)delta; 23334 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 23335 break; 23336 } 23337 *state = NK_WIDGET_STATE_ACTIVE; 23338 } 23339 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag)) 23340 *state |= NK_WIDGET_STATE_ENTERED; 23341 else if (nk_input_is_mouse_prev_hovering_rect(in, drag)) 23342 *state |= NK_WIDGET_STATE_LEFT; 23343 } 23344 NK_LIB void 23345 nk_property_behavior(nk_flags *ws, const struct nk_input *in, 23346 struct nk_rect property, struct nk_rect label, struct nk_rect edit, 23347 struct nk_rect empty, int *state, struct nk_property_variant *variant, 23348 float inc_per_pixel) 23349 { 23350 if (in && *state == NK_PROPERTY_DEFAULT) { 23351 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT)) 23352 *state = NK_PROPERTY_EDIT; 23353 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true)) 23354 *state = NK_PROPERTY_DRAG; 23355 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true)) 23356 *state = NK_PROPERTY_DRAG; 23357 } 23358 if (*state == NK_PROPERTY_DRAG) { 23359 nk_drag_behavior(ws, in, property, variant, inc_per_pixel); 23360 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT; 23361 } 23362 } 23363 NK_LIB void 23364 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, 23365 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, 23366 const char *name, int len, const struct nk_user_font *font) 23367 { 23368 struct nk_text text; 23369 const struct nk_style_item *background; 23370 23371 /* select correct background and text color */ 23372 if (state & NK_WIDGET_STATE_ACTIVED) { 23373 background = &style->active; 23374 text.text = style->label_active; 23375 } else if (state & NK_WIDGET_STATE_HOVER) { 23376 background = &style->hover; 23377 text.text = style->label_hover; 23378 } else { 23379 background = &style->normal; 23380 text.text = style->label_normal; 23381 } 23382 23383 /* draw background */ 23384 if (background->type == NK_STYLE_ITEM_IMAGE) { 23385 nk_draw_image(out, *bounds, &background->data.image, nk_white); 23386 text.background = nk_rgba(0,0,0,0); 23387 } else { 23388 text.background = background->data.color; 23389 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 23390 nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color); 23391 } 23392 23393 /* draw label */ 23394 text.padding = nk_vec2(0,0); 23395 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font); 23396 } 23397 NK_LIB void 23398 nk_do_property(nk_flags *ws, 23399 struct nk_command_buffer *out, struct nk_rect property, 23400 const char *name, struct nk_property_variant *variant, 23401 float inc_per_pixel, char *buffer, int *len, 23402 int *state, int *cursor, int *select_begin, int *select_end, 23403 const struct nk_style_property *style, 23404 enum nk_property_filter filter, struct nk_input *in, 23405 const struct nk_user_font *font, struct nk_text_edit *text_edit, 23406 enum nk_button_behavior behavior) 23407 { 23408 const nk_plugin_filter filters[] = { 23409 nk_filter_decimal, 23410 nk_filter_float 23411 }; 23412 int active, old; 23413 int num_len, name_len; 23414 char string[NK_MAX_NUMBER_BUFFER]; 23415 float size; 23416 23417 char *dst = 0; 23418 int *length; 23419 23420 struct nk_rect left; 23421 struct nk_rect right; 23422 struct nk_rect label; 23423 struct nk_rect edit; 23424 struct nk_rect empty; 23425 23426 /* left decrement button */ 23427 left.h = font->height/2; 23428 left.w = left.h; 23429 left.x = property.x + style->border + style->padding.x; 23430 left.y = property.y + style->border + property.h/2.0f - left.h/2; 23431 23432 /* text label */ 23433 name_len = nk_strlen(name); 23434 size = font->width(font->userdata, font->height, name, name_len); 23435 label.x = left.x + left.w + style->padding.x; 23436 label.w = (float)size + 2 * style->padding.x; 23437 label.y = property.y + style->border + style->padding.y; 23438 label.h = property.h - (2 * style->border + 2 * style->padding.y); 23439 23440 /* right increment button */ 23441 right.y = left.y; 23442 right.w = left.w; 23443 right.h = left.h; 23444 right.x = property.x + property.w - (right.w + style->padding.x); 23445 23446 /* edit */ 23447 if (*state == NK_PROPERTY_EDIT) { 23448 size = font->width(font->userdata, font->height, buffer, *len); 23449 size += style->edit.cursor_size; 23450 length = len; 23451 dst = buffer; 23452 } else { 23453 switch (variant->kind) { 23454 default: break; 23455 case NK_PROPERTY_INT: 23456 nk_itoa(string, variant->value.i); 23457 num_len = nk_strlen(string); 23458 break; 23459 case NK_PROPERTY_FLOAT: 23460 NK_DTOA(string, (double)variant->value.f); 23461 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 23462 break; 23463 case NK_PROPERTY_DOUBLE: 23464 NK_DTOA(string, variant->value.d); 23465 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 23466 break; 23467 } 23468 size = font->width(font->userdata, font->height, string, num_len); 23469 dst = string; 23470 length = &num_len; 23471 } 23472 23473 edit.w = (float)size + 2 * style->padding.x; 23474 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w)); 23475 edit.x = right.x - (edit.w + style->padding.x); 23476 edit.y = property.y + style->border; 23477 edit.h = property.h - (2 * style->border); 23478 23479 /* empty left space activator */ 23480 empty.w = edit.x - (label.x + label.w); 23481 empty.x = label.x + label.w; 23482 empty.y = property.y; 23483 empty.h = property.h; 23484 23485 /* update property */ 23486 old = (*state == NK_PROPERTY_EDIT); 23487 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel); 23488 23489 /* draw property */ 23490 if (style->draw_begin) style->draw_begin(out, style->userdata); 23491 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font); 23492 if (style->draw_end) style->draw_end(out, style->userdata); 23493 23494 /* execute right button */ 23495 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) { 23496 switch (variant->kind) { 23497 default: break; 23498 case NK_PROPERTY_INT: 23499 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break; 23500 case NK_PROPERTY_FLOAT: 23501 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break; 23502 case NK_PROPERTY_DOUBLE: 23503 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break; 23504 } 23505 } 23506 /* execute left button */ 23507 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) { 23508 switch (variant->kind) { 23509 default: break; 23510 case NK_PROPERTY_INT: 23511 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break; 23512 case NK_PROPERTY_FLOAT: 23513 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break; 23514 case NK_PROPERTY_DOUBLE: 23515 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break; 23516 } 23517 } 23518 if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) { 23519 /* property has been activated so setup buffer */ 23520 NK_MEMCPY(buffer, dst, (nk_size)*length); 23521 *cursor = nk_utf_len(buffer, *length); 23522 *len = *length; 23523 length = len; 23524 dst = buffer; 23525 active = 0; 23526 } else active = (*state == NK_PROPERTY_EDIT); 23527 23528 /* execute and run text edit field */ 23529 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]); 23530 text_edit->active = (unsigned char)active; 23531 text_edit->string.len = *length; 23532 text_edit->cursor = NK_CLAMP(0, *cursor, *length); 23533 text_edit->select_start = NK_CLAMP(0,*select_begin, *length); 23534 text_edit->select_end = NK_CLAMP(0,*select_end, *length); 23535 text_edit->string.buffer.allocated = (nk_size)*length; 23536 text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER; 23537 text_edit->string.buffer.memory.ptr = dst; 23538 text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER; 23539 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT; 23540 nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT, 23541 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font); 23542 23543 *length = text_edit->string.len; 23544 *cursor = text_edit->cursor; 23545 *select_begin = text_edit->select_start; 23546 *select_end = text_edit->select_end; 23547 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER)) 23548 text_edit->active = nk_false; 23549 23550 if (active && !text_edit->active) { 23551 /* property is now not active so convert edit text to value*/ 23552 *state = NK_PROPERTY_DEFAULT; 23553 buffer[*len] = '\0'; 23554 switch (variant->kind) { 23555 default: break; 23556 case NK_PROPERTY_INT: 23557 variant->value.i = nk_strtoi(buffer, 0); 23558 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 23559 break; 23560 case NK_PROPERTY_FLOAT: 23561 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 23562 variant->value.f = nk_strtof(buffer, 0); 23563 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 23564 break; 23565 case NK_PROPERTY_DOUBLE: 23566 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 23567 variant->value.d = nk_strtod(buffer, 0); 23568 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 23569 break; 23570 } 23571 } 23572 } 23573 NK_LIB struct nk_property_variant 23574 nk_property_variant_int(int value, int min_value, int max_value, int step) 23575 { 23576 struct nk_property_variant result; 23577 result.kind = NK_PROPERTY_INT; 23578 result.value.i = value; 23579 result.min_value.i = min_value; 23580 result.max_value.i = max_value; 23581 result.step.i = step; 23582 return result; 23583 } 23584 NK_LIB struct nk_property_variant 23585 nk_property_variant_float(float value, float min_value, float max_value, float step) 23586 { 23587 struct nk_property_variant result; 23588 result.kind = NK_PROPERTY_FLOAT; 23589 result.value.f = value; 23590 result.min_value.f = min_value; 23591 result.max_value.f = max_value; 23592 result.step.f = step; 23593 return result; 23594 } 23595 NK_LIB struct nk_property_variant 23596 nk_property_variant_double(double value, double min_value, double max_value, 23597 double step) 23598 { 23599 struct nk_property_variant result; 23600 result.kind = NK_PROPERTY_DOUBLE; 23601 result.value.d = value; 23602 result.min_value.d = min_value; 23603 result.max_value.d = max_value; 23604 result.step.d = step; 23605 return result; 23606 } 23607 NK_LIB void 23608 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, 23609 float inc_per_pixel, const enum nk_property_filter filter) 23610 { 23611 struct nk_window *win; 23612 struct nk_panel *layout; 23613 struct nk_input *in; 23614 const struct nk_style *style; 23615 23616 struct nk_rect bounds; 23617 enum nk_widget_layout_states s; 23618 23619 int *state = 0; 23620 nk_hash hash = 0; 23621 char *buffer = 0; 23622 int *len = 0; 23623 int *cursor = 0; 23624 int *select_begin = 0; 23625 int *select_end = 0; 23626 int old_state; 23627 23628 char dummy_buffer[NK_MAX_NUMBER_BUFFER]; 23629 int dummy_state = NK_PROPERTY_DEFAULT; 23630 int dummy_length = 0; 23631 int dummy_cursor = 0; 23632 int dummy_select_begin = 0; 23633 int dummy_select_end = 0; 23634 23635 NK_ASSERT(ctx); 23636 NK_ASSERT(ctx->current); 23637 NK_ASSERT(ctx->current->layout); 23638 if (!ctx || !ctx->current || !ctx->current->layout) 23639 return; 23640 23641 win = ctx->current; 23642 layout = win->layout; 23643 style = &ctx->style; 23644 s = nk_widget(&bounds, ctx); 23645 if (!s) return; 23646 23647 /* calculate hash from name */ 23648 if (name[0] == '#') { 23649 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++); 23650 name++; /* special number hash */ 23651 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42); 23652 23653 /* check if property is currently hot item */ 23654 if (win->property.active && hash == win->property.name) { 23655 buffer = win->property.buffer; 23656 len = &win->property.length; 23657 cursor = &win->property.cursor; 23658 state = &win->property.state; 23659 select_begin = &win->property.select_start; 23660 select_end = &win->property.select_end; 23661 } else { 23662 buffer = dummy_buffer; 23663 len = &dummy_length; 23664 cursor = &dummy_cursor; 23665 state = &dummy_state; 23666 select_begin = &dummy_select_begin; 23667 select_end = &dummy_select_end; 23668 } 23669 23670 /* execute property widget */ 23671 old_state = *state; 23672 ctx->text_edit.clip = ctx->clip; 23673 in = ((s == NK_WIDGET_ROM && !win->property.active) || 23674 layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 23675 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, 23676 variant, inc_per_pixel, buffer, len, state, cursor, select_begin, 23677 select_end, &style->property, filter, in, style->font, &ctx->text_edit, 23678 ctx->button_behavior); 23679 23680 if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) { 23681 /* current property is now hot */ 23682 win->property.active = 1; 23683 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len); 23684 win->property.length = *len; 23685 win->property.cursor = *cursor; 23686 win->property.state = *state; 23687 win->property.name = hash; 23688 win->property.select_start = *select_begin; 23689 win->property.select_end = *select_end; 23690 if (*state == NK_PROPERTY_DRAG) { 23691 ctx->input.mouse.grab = nk_true; 23692 ctx->input.mouse.grabbed = nk_true; 23693 } 23694 } 23695 /* check if previously active property is now inactive */ 23696 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) { 23697 if (old_state == NK_PROPERTY_DRAG) { 23698 ctx->input.mouse.grab = nk_false; 23699 ctx->input.mouse.grabbed = nk_false; 23700 ctx->input.mouse.ungrab = nk_true; 23701 } 23702 win->property.select_start = 0; 23703 win->property.select_end = 0; 23704 win->property.active = 0; 23705 } 23706 } 23707 NK_API void 23708 nk_property_int(struct nk_context *ctx, const char *name, 23709 int min, int *val, int max, int step, float inc_per_pixel) 23710 { 23711 struct nk_property_variant variant; 23712 NK_ASSERT(ctx); 23713 NK_ASSERT(name); 23714 NK_ASSERT(val); 23715 23716 if (!ctx || !ctx->current || !name || !val) return; 23717 variant = nk_property_variant_int(*val, min, max, step); 23718 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 23719 *val = variant.value.i; 23720 } 23721 NK_API void 23722 nk_property_float(struct nk_context *ctx, const char *name, 23723 float min, float *val, float max, float step, float inc_per_pixel) 23724 { 23725 struct nk_property_variant variant; 23726 NK_ASSERT(ctx); 23727 NK_ASSERT(name); 23728 NK_ASSERT(val); 23729 23730 if (!ctx || !ctx->current || !name || !val) return; 23731 variant = nk_property_variant_float(*val, min, max, step); 23732 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23733 *val = variant.value.f; 23734 } 23735 NK_API void 23736 nk_property_double(struct nk_context *ctx, const char *name, 23737 double min, double *val, double max, double step, float inc_per_pixel) 23738 { 23739 struct nk_property_variant variant; 23740 NK_ASSERT(ctx); 23741 NK_ASSERT(name); 23742 NK_ASSERT(val); 23743 23744 if (!ctx || !ctx->current || !name || !val) return; 23745 variant = nk_property_variant_double(*val, min, max, step); 23746 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23747 *val = variant.value.d; 23748 } 23749 NK_API int 23750 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, 23751 int max, int step, float inc_per_pixel) 23752 { 23753 struct nk_property_variant variant; 23754 NK_ASSERT(ctx); 23755 NK_ASSERT(name); 23756 23757 if (!ctx || !ctx->current || !name) return val; 23758 variant = nk_property_variant_int(val, min, max, step); 23759 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 23760 val = variant.value.i; 23761 return val; 23762 } 23763 NK_API float 23764 nk_propertyf(struct nk_context *ctx, const char *name, float min, 23765 float val, float max, float step, float inc_per_pixel) 23766 { 23767 struct nk_property_variant variant; 23768 NK_ASSERT(ctx); 23769 NK_ASSERT(name); 23770 23771 if (!ctx || !ctx->current || !name) return val; 23772 variant = nk_property_variant_float(val, min, max, step); 23773 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23774 val = variant.value.f; 23775 return val; 23776 } 23777 NK_API double 23778 nk_propertyd(struct nk_context *ctx, const char *name, double min, 23779 double val, double max, double step, float inc_per_pixel) 23780 { 23781 struct nk_property_variant variant; 23782 NK_ASSERT(ctx); 23783 NK_ASSERT(name); 23784 23785 if (!ctx || !ctx->current || !name) return val; 23786 variant = nk_property_variant_double(val, min, max, step); 23787 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23788 val = variant.value.d; 23789 return val; 23790 } 23791 23792 23793 23794 23795 23796 /* ============================================================== 23797 * 23798 * CHART 23799 * 23800 * ===============================================================*/ 23801 NK_API int 23802 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type, 23803 struct nk_color color, struct nk_color highlight, 23804 int count, float min_value, float max_value) 23805 { 23806 struct nk_window *win; 23807 struct nk_chart *chart; 23808 const struct nk_style *config; 23809 const struct nk_style_chart *style; 23810 23811 const struct nk_style_item *background; 23812 struct nk_rect bounds = {0, 0, 0, 0}; 23813 23814 NK_ASSERT(ctx); 23815 NK_ASSERT(ctx->current); 23816 NK_ASSERT(ctx->current->layout); 23817 23818 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 23819 if (!nk_widget(&bounds, ctx)) { 23820 chart = &ctx->current->layout->chart; 23821 nk_zero(chart, sizeof(*chart)); 23822 return 0; 23823 } 23824 23825 win = ctx->current; 23826 config = &ctx->style; 23827 chart = &win->layout->chart; 23828 style = &config->chart; 23829 23830 /* setup basic generic chart */ 23831 nk_zero(chart, sizeof(*chart)); 23832 chart->x = bounds.x + style->padding.x; 23833 chart->y = bounds.y + style->padding.y; 23834 chart->w = bounds.w - 2 * style->padding.x; 23835 chart->h = bounds.h - 2 * style->padding.y; 23836 chart->w = NK_MAX(chart->w, 2 * style->padding.x); 23837 chart->h = NK_MAX(chart->h, 2 * style->padding.y); 23838 23839 /* add first slot into chart */ 23840 {struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 23841 slot->type = type; 23842 slot->count = count; 23843 slot->color = color; 23844 slot->highlight = highlight; 23845 slot->min = NK_MIN(min_value, max_value); 23846 slot->max = NK_MAX(min_value, max_value); 23847 slot->range = slot->max - slot->min;} 23848 23849 /* draw chart background */ 23850 background = &style->background; 23851 if (background->type == NK_STYLE_ITEM_IMAGE) { 23852 nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white); 23853 } else { 23854 nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color); 23855 nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border), 23856 style->rounding, style->background.data.color); 23857 } 23858 return 1; 23859 } 23860 NK_API int 23861 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type, 23862 int count, float min_value, float max_value) 23863 { 23864 return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, 23865 ctx->style.chart.selected_color, count, min_value, max_value); 23866 } 23867 NK_API void 23868 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type, 23869 struct nk_color color, struct nk_color highlight, 23870 int count, float min_value, float max_value) 23871 { 23872 NK_ASSERT(ctx); 23873 NK_ASSERT(ctx->current); 23874 NK_ASSERT(ctx->current->layout); 23875 NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT); 23876 if (!ctx || !ctx->current || !ctx->current->layout) return; 23877 if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return; 23878 23879 /* add another slot into the graph */ 23880 {struct nk_chart *chart = &ctx->current->layout->chart; 23881 struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 23882 slot->type = type; 23883 slot->count = count; 23884 slot->color = color; 23885 slot->highlight = highlight; 23886 slot->min = NK_MIN(min_value, max_value); 23887 slot->max = NK_MAX(min_value, max_value); 23888 slot->range = slot->max - slot->min;} 23889 } 23890 NK_API void 23891 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type, 23892 int count, float min_value, float max_value) 23893 { 23894 nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, 23895 ctx->style.chart.selected_color, count, min_value, max_value); 23896 } 23897 NK_INTERN nk_flags 23898 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win, 23899 struct nk_chart *g, float value, int slot) 23900 { 23901 struct nk_panel *layout = win->layout; 23902 const struct nk_input *i = &ctx->input; 23903 struct nk_command_buffer *out = &win->buffer; 23904 23905 nk_flags ret = 0; 23906 struct nk_vec2 cur; 23907 struct nk_rect bounds; 23908 struct nk_color color; 23909 float step; 23910 float range; 23911 float ratio; 23912 23913 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 23914 step = g->w / (float)g->slots[slot].count; 23915 range = g->slots[slot].max - g->slots[slot].min; 23916 ratio = (value - g->slots[slot].min) / range; 23917 23918 if (g->slots[slot].index == 0) { 23919 /* first data point does not have a connection */ 23920 g->slots[slot].last.x = g->x; 23921 g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h; 23922 23923 bounds.x = g->slots[slot].last.x - 2; 23924 bounds.y = g->slots[slot].last.y - 2; 23925 bounds.w = bounds.h = 4; 23926 23927 color = g->slots[slot].color; 23928 if (!(layout->flags & NK_WINDOW_ROM) && 23929 NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){ 23930 ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0; 23931 ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down && 23932 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 23933 color = g->slots[slot].highlight; 23934 } 23935 nk_fill_rect(out, bounds, 0, color); 23936 g->slots[slot].index += 1; 23937 return ret; 23938 } 23939 23940 /* draw a line between the last data point and the new one */ 23941 color = g->slots[slot].color; 23942 cur.x = g->x + (float)(step * (float)g->slots[slot].index); 23943 cur.y = (g->y + g->h) - (ratio * (float)g->h); 23944 nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color); 23945 23946 bounds.x = cur.x - 3; 23947 bounds.y = cur.y - 3; 23948 bounds.w = bounds.h = 6; 23949 23950 /* user selection of current data point */ 23951 if (!(layout->flags & NK_WINDOW_ROM)) { 23952 if (nk_input_is_mouse_hovering_rect(i, bounds)) { 23953 ret = NK_CHART_HOVERING; 23954 ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down && 23955 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 23956 color = g->slots[slot].highlight; 23957 } 23958 } 23959 nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); 23960 23961 /* save current data point position */ 23962 g->slots[slot].last.x = cur.x; 23963 g->slots[slot].last.y = cur.y; 23964 g->slots[slot].index += 1; 23965 return ret; 23966 } 23967 NK_INTERN nk_flags 23968 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win, 23969 struct nk_chart *chart, float value, int slot) 23970 { 23971 struct nk_command_buffer *out = &win->buffer; 23972 const struct nk_input *in = &ctx->input; 23973 struct nk_panel *layout = win->layout; 23974 23975 float ratio; 23976 nk_flags ret = 0; 23977 struct nk_color color; 23978 struct nk_rect item = {0,0,0,0}; 23979 23980 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 23981 if (chart->slots[slot].index >= chart->slots[slot].count) 23982 return nk_false; 23983 if (chart->slots[slot].count) { 23984 float padding = (float)(chart->slots[slot].count-1); 23985 item.w = (chart->w - padding) / (float)(chart->slots[slot].count); 23986 } 23987 23988 /* calculate bounds of current bar chart entry */ 23989 color = chart->slots[slot].color;; 23990 item.h = chart->h * NK_ABS((value/chart->slots[slot].range)); 23991 if (value >= 0) { 23992 ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range); 23993 item.y = (chart->y + chart->h) - chart->h * ratio; 23994 } else { 23995 ratio = (value - chart->slots[slot].max) / chart->slots[slot].range; 23996 item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h; 23997 } 23998 item.x = chart->x + ((float)chart->slots[slot].index * item.w); 23999 item.x = item.x + ((float)chart->slots[slot].index); 24000 24001 /* user chart bar selection */ 24002 if (!(layout->flags & NK_WINDOW_ROM) && 24003 NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) { 24004 ret = NK_CHART_HOVERING; 24005 ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down && 24006 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24007 color = chart->slots[slot].highlight; 24008 } 24009 nk_fill_rect(out, item, 0, color); 24010 chart->slots[slot].index += 1; 24011 return ret; 24012 } 24013 NK_API nk_flags 24014 nk_chart_push_slot(struct nk_context *ctx, float value, int slot) 24015 { 24016 nk_flags flags; 24017 struct nk_window *win; 24018 24019 NK_ASSERT(ctx); 24020 NK_ASSERT(ctx->current); 24021 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24022 NK_ASSERT(slot < ctx->current->layout->chart.slot); 24023 if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false; 24024 if (slot >= ctx->current->layout->chart.slot) return nk_false; 24025 24026 win = ctx->current; 24027 if (win->layout->chart.slot < slot) return nk_false; 24028 switch (win->layout->chart.slots[slot].type) { 24029 case NK_CHART_LINES: 24030 flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break; 24031 case NK_CHART_COLUMN: 24032 flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break; 24033 default: 24034 case NK_CHART_MAX: 24035 flags = 0; 24036 } 24037 return flags; 24038 } 24039 NK_API nk_flags 24040 nk_chart_push(struct nk_context *ctx, float value) 24041 { 24042 return nk_chart_push_slot(ctx, value, 0); 24043 } 24044 NK_API void 24045 nk_chart_end(struct nk_context *ctx) 24046 { 24047 struct nk_window *win; 24048 struct nk_chart *chart; 24049 24050 NK_ASSERT(ctx); 24051 NK_ASSERT(ctx->current); 24052 if (!ctx || !ctx->current) 24053 return; 24054 24055 win = ctx->current; 24056 chart = &win->layout->chart; 24057 NK_MEMSET(chart, 0, sizeof(*chart)); 24058 return; 24059 } 24060 NK_API void 24061 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values, 24062 int count, int offset) 24063 { 24064 int i = 0; 24065 float min_value; 24066 float max_value; 24067 24068 NK_ASSERT(ctx); 24069 NK_ASSERT(values); 24070 if (!ctx || !values || !count) return; 24071 24072 min_value = values[offset]; 24073 max_value = values[offset]; 24074 for (i = 0; i < count; ++i) { 24075 min_value = NK_MIN(values[i + offset], min_value); 24076 max_value = NK_MAX(values[i + offset], max_value); 24077 } 24078 24079 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 24080 for (i = 0; i < count; ++i) 24081 nk_chart_push(ctx, values[i + offset]); 24082 nk_chart_end(ctx); 24083 } 24084 } 24085 NK_API void 24086 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata, 24087 float(*value_getter)(void* user, int index), int count, int offset) 24088 { 24089 int i = 0; 24090 float min_value; 24091 float max_value; 24092 24093 NK_ASSERT(ctx); 24094 NK_ASSERT(value_getter); 24095 if (!ctx || !value_getter || !count) return; 24096 24097 max_value = min_value = value_getter(userdata, offset); 24098 for (i = 0; i < count; ++i) { 24099 float value = value_getter(userdata, i + offset); 24100 min_value = NK_MIN(value, min_value); 24101 max_value = NK_MAX(value, max_value); 24102 } 24103 24104 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 24105 for (i = 0; i < count; ++i) 24106 nk_chart_push(ctx, value_getter(userdata, i + offset)); 24107 nk_chart_end(ctx); 24108 } 24109 } 24110 24111 24112 24113 24114 24115 /* ============================================================== 24116 * 24117 * COLOR PICKER 24118 * 24119 * ===============================================================*/ 24120 NK_LIB int 24121 nk_color_picker_behavior(nk_flags *state, 24122 const struct nk_rect *bounds, const struct nk_rect *matrix, 24123 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 24124 struct nk_colorf *color, const struct nk_input *in) 24125 { 24126 float hsva[4]; 24127 int value_changed = 0; 24128 int hsv_changed = 0; 24129 24130 NK_ASSERT(state); 24131 NK_ASSERT(matrix); 24132 NK_ASSERT(hue_bar); 24133 NK_ASSERT(color); 24134 24135 /* color matrix */ 24136 nk_colorf_hsva_fv(hsva, *color); 24137 if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) { 24138 hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); 24139 hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); 24140 value_changed = hsv_changed = 1; 24141 } 24142 /* hue bar */ 24143 if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) { 24144 hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); 24145 value_changed = hsv_changed = 1; 24146 } 24147 /* alpha bar */ 24148 if (alpha_bar) { 24149 if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) { 24150 hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); 24151 value_changed = 1; 24152 } 24153 } 24154 nk_widget_state_reset(state); 24155 if (hsv_changed) { 24156 *color = nk_hsva_colorfv(hsva); 24157 *state = NK_WIDGET_STATE_ACTIVE; 24158 } 24159 if (value_changed) { 24160 color->a = hsva[3]; 24161 *state = NK_WIDGET_STATE_ACTIVE; 24162 } 24163 /* set color picker widget state */ 24164 if (nk_input_is_mouse_hovering_rect(in, *bounds)) 24165 *state = NK_WIDGET_STATE_HOVERED; 24166 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 24167 *state |= NK_WIDGET_STATE_ENTERED; 24168 else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 24169 *state |= NK_WIDGET_STATE_LEFT; 24170 return value_changed; 24171 } 24172 NK_LIB void 24173 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, 24174 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 24175 struct nk_colorf col) 24176 { 24177 NK_STORAGE const struct nk_color black = {0,0,0,255}; 24178 NK_STORAGE const struct nk_color white = {255, 255, 255, 255}; 24179 NK_STORAGE const struct nk_color black_trans = {0,0,0,0}; 24180 24181 const float crosshair_size = 7.0f; 24182 struct nk_color temp; 24183 float hsva[4]; 24184 float line_y; 24185 int i; 24186 24187 NK_ASSERT(o); 24188 NK_ASSERT(matrix); 24189 NK_ASSERT(hue_bar); 24190 24191 /* draw hue bar */ 24192 nk_colorf_hsva_fv(hsva, col); 24193 for (i = 0; i < 6; ++i) { 24194 NK_GLOBAL const struct nk_color hue_colors[] = { 24195 {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255}, 24196 {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255} 24197 }; 24198 nk_fill_rect_multi_color(o, 24199 nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, 24200 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], 24201 hue_colors[i+1], hue_colors[i+1]); 24202 } 24203 line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); 24204 nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, 24205 line_y, 1, nk_rgb(255,255,255)); 24206 24207 /* draw alpha bar */ 24208 if (alpha_bar) { 24209 float alpha = NK_SATURATE(col.a); 24210 line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); 24211 24212 nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); 24213 nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, 24214 line_y, 1, nk_rgb(255,255,255)); 24215 } 24216 24217 /* draw color matrix */ 24218 temp = nk_hsv_f(hsva[0], 1.0f, 1.0f); 24219 nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white); 24220 nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); 24221 24222 /* draw cross-hair */ 24223 {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2]; 24224 p.x = (float)(int)(matrix->x + S * matrix->w); 24225 p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h); 24226 nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); 24227 nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white); 24228 nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white); 24229 nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);} 24230 } 24231 NK_LIB int 24232 nk_do_color_picker(nk_flags *state, 24233 struct nk_command_buffer *out, struct nk_colorf *col, 24234 enum nk_color_format fmt, struct nk_rect bounds, 24235 struct nk_vec2 padding, const struct nk_input *in, 24236 const struct nk_user_font *font) 24237 { 24238 int ret = 0; 24239 struct nk_rect matrix; 24240 struct nk_rect hue_bar; 24241 struct nk_rect alpha_bar; 24242 float bar_w; 24243 24244 NK_ASSERT(out); 24245 NK_ASSERT(col); 24246 NK_ASSERT(state); 24247 NK_ASSERT(font); 24248 if (!out || !col || !state || !font) 24249 return ret; 24250 24251 bar_w = font->height; 24252 bounds.x += padding.x; 24253 bounds.y += padding.x; 24254 bounds.w -= 2 * padding.x; 24255 bounds.h -= 2 * padding.y; 24256 24257 matrix.x = bounds.x; 24258 matrix.y = bounds.y; 24259 matrix.h = bounds.h; 24260 matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); 24261 24262 hue_bar.w = bar_w; 24263 hue_bar.y = bounds.y; 24264 hue_bar.h = matrix.h; 24265 hue_bar.x = matrix.x + matrix.w + padding.x; 24266 24267 alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; 24268 alpha_bar.y = bounds.y; 24269 alpha_bar.w = bar_w; 24270 alpha_bar.h = matrix.h; 24271 24272 ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar, 24273 (fmt == NK_RGBA) ? &alpha_bar:0, col, in); 24274 nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col); 24275 return ret; 24276 } 24277 NK_API int 24278 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color, 24279 enum nk_color_format fmt) 24280 { 24281 struct nk_window *win; 24282 struct nk_panel *layout; 24283 const struct nk_style *config; 24284 const struct nk_input *in; 24285 24286 enum nk_widget_layout_states state; 24287 struct nk_rect bounds; 24288 24289 NK_ASSERT(ctx); 24290 NK_ASSERT(color); 24291 NK_ASSERT(ctx->current); 24292 NK_ASSERT(ctx->current->layout); 24293 if (!ctx || !ctx->current || !ctx->current->layout || !color) 24294 return 0; 24295 24296 win = ctx->current; 24297 config = &ctx->style; 24298 layout = win->layout; 24299 state = nk_widget(&bounds, ctx); 24300 if (!state) return 0; 24301 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24302 return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds, 24303 nk_vec2(0,0), in, config->font); 24304 } 24305 NK_API struct nk_colorf 24306 nk_color_picker(struct nk_context *ctx, struct nk_colorf color, 24307 enum nk_color_format fmt) 24308 { 24309 nk_color_pick(ctx, &color, fmt); 24310 return color; 24311 } 24312 24313 24314 24315 24316 24317 /* ============================================================== 24318 * 24319 * COMBO 24320 * 24321 * ===============================================================*/ 24322 NK_INTERN int 24323 nk_combo_begin(struct nk_context *ctx, struct nk_window *win, 24324 struct nk_vec2 size, int is_clicked, struct nk_rect header) 24325 { 24326 struct nk_window *popup; 24327 int is_open = 0; 24328 int is_active = 0; 24329 struct nk_rect body; 24330 nk_hash hash; 24331 24332 NK_ASSERT(ctx); 24333 NK_ASSERT(ctx->current); 24334 NK_ASSERT(ctx->current->layout); 24335 if (!ctx || !ctx->current || !ctx->current->layout) 24336 return 0; 24337 24338 popup = win->popup.win; 24339 body.x = header.x; 24340 body.w = size.x; 24341 body.y = header.y + header.h-ctx->style.window.combo_border; 24342 body.h = size.y; 24343 24344 hash = win->popup.combo_count++; 24345 is_open = (popup) ? nk_true:nk_false; 24346 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO); 24347 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 24348 (!is_open && !is_active && !is_clicked)) return 0; 24349 if (!nk_nonblock_begin(ctx, 0, body, 24350 (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0; 24351 24352 win->popup.type = NK_PANEL_COMBO; 24353 win->popup.name = hash; 24354 return 1; 24355 } 24356 NK_API int 24357 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len, 24358 struct nk_vec2 size) 24359 { 24360 const struct nk_input *in; 24361 struct nk_window *win; 24362 struct nk_style *style; 24363 24364 enum nk_widget_layout_states s; 24365 int is_clicked = nk_false; 24366 struct nk_rect header; 24367 const struct nk_style_item *background; 24368 struct nk_text text; 24369 24370 NK_ASSERT(ctx); 24371 NK_ASSERT(selected); 24372 NK_ASSERT(ctx->current); 24373 NK_ASSERT(ctx->current->layout); 24374 if (!ctx || !ctx->current || !ctx->current->layout || !selected) 24375 return 0; 24376 24377 win = ctx->current; 24378 style = &ctx->style; 24379 s = nk_widget(&header, ctx); 24380 if (s == NK_WIDGET_INVALID) 24381 return 0; 24382 24383 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24384 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24385 is_clicked = nk_true; 24386 24387 /* draw combo box header background and border */ 24388 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24389 background = &style->combo.active; 24390 text.text = style->combo.label_active; 24391 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24392 background = &style->combo.hover; 24393 text.text = style->combo.label_hover; 24394 } else { 24395 background = &style->combo.normal; 24396 text.text = style->combo.label_normal; 24397 } 24398 if (background->type == NK_STYLE_ITEM_IMAGE) { 24399 text.background = nk_rgba(0,0,0,0); 24400 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24401 } else { 24402 text.background = background->data.color; 24403 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24404 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24405 } 24406 { 24407 /* print currently selected text item */ 24408 struct nk_rect label; 24409 struct nk_rect button; 24410 struct nk_rect content; 24411 24412 enum nk_symbol_type sym; 24413 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24414 sym = style->combo.sym_hover; 24415 else if (is_clicked) 24416 sym = style->combo.sym_active; 24417 else sym = style->combo.sym_normal; 24418 24419 /* calculate button */ 24420 button.w = header.h - 2 * style->combo.button_padding.y; 24421 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24422 button.y = header.y + style->combo.button_padding.y; 24423 button.h = button.w; 24424 24425 content.x = button.x + style->combo.button.padding.x; 24426 content.y = button.y + style->combo.button.padding.y; 24427 content.w = button.w - 2 * style->combo.button.padding.x; 24428 content.h = button.h - 2 * style->combo.button.padding.y; 24429 24430 /* draw selected label */ 24431 text.padding = nk_vec2(0,0); 24432 label.x = header.x + style->combo.content_padding.x; 24433 label.y = header.y + style->combo.content_padding.y; 24434 label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;; 24435 label.h = header.h - 2 * style->combo.content_padding.y; 24436 nk_widget_text(&win->buffer, label, selected, len, &text, 24437 NK_TEXT_LEFT, ctx->style.font); 24438 24439 /* draw open/close button */ 24440 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24441 &ctx->style.combo.button, sym, style->font); 24442 } 24443 return nk_combo_begin(ctx, win, size, is_clicked, header); 24444 } 24445 NK_API int 24446 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size) 24447 { 24448 return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size); 24449 } 24450 NK_API int 24451 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size) 24452 { 24453 struct nk_window *win; 24454 struct nk_style *style; 24455 const struct nk_input *in; 24456 24457 struct nk_rect header; 24458 int is_clicked = nk_false; 24459 enum nk_widget_layout_states s; 24460 const struct nk_style_item *background; 24461 24462 NK_ASSERT(ctx); 24463 NK_ASSERT(ctx->current); 24464 NK_ASSERT(ctx->current->layout); 24465 if (!ctx || !ctx->current || !ctx->current->layout) 24466 return 0; 24467 24468 win = ctx->current; 24469 style = &ctx->style; 24470 s = nk_widget(&header, ctx); 24471 if (s == NK_WIDGET_INVALID) 24472 return 0; 24473 24474 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24475 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24476 is_clicked = nk_true; 24477 24478 /* draw combo box header background and border */ 24479 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 24480 background = &style->combo.active; 24481 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24482 background = &style->combo.hover; 24483 else background = &style->combo.normal; 24484 24485 if (background->type == NK_STYLE_ITEM_IMAGE) { 24486 nk_draw_image(&win->buffer, header, &background->data.image,nk_white); 24487 } else { 24488 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24489 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24490 } 24491 { 24492 struct nk_rect content; 24493 struct nk_rect button; 24494 struct nk_rect bounds; 24495 24496 enum nk_symbol_type sym; 24497 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24498 sym = style->combo.sym_hover; 24499 else if (is_clicked) 24500 sym = style->combo.sym_active; 24501 else sym = style->combo.sym_normal; 24502 24503 /* calculate button */ 24504 button.w = header.h - 2 * style->combo.button_padding.y; 24505 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24506 button.y = header.y + style->combo.button_padding.y; 24507 button.h = button.w; 24508 24509 content.x = button.x + style->combo.button.padding.x; 24510 content.y = button.y + style->combo.button.padding.y; 24511 content.w = button.w - 2 * style->combo.button.padding.x; 24512 content.h = button.h - 2 * style->combo.button.padding.y; 24513 24514 /* draw color */ 24515 bounds.h = header.h - 4 * style->combo.content_padding.y; 24516 bounds.y = header.y + 2 * style->combo.content_padding.y; 24517 bounds.x = header.x + 2 * style->combo.content_padding.x; 24518 bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; 24519 nk_fill_rect(&win->buffer, bounds, 0, color); 24520 24521 /* draw open/close button */ 24522 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24523 &ctx->style.combo.button, sym, style->font); 24524 } 24525 return nk_combo_begin(ctx, win, size, is_clicked, header); 24526 } 24527 NK_API int 24528 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size) 24529 { 24530 struct nk_window *win; 24531 struct nk_style *style; 24532 const struct nk_input *in; 24533 24534 struct nk_rect header; 24535 int is_clicked = nk_false; 24536 enum nk_widget_layout_states s; 24537 const struct nk_style_item *background; 24538 struct nk_color sym_background; 24539 struct nk_color symbol_color; 24540 24541 NK_ASSERT(ctx); 24542 NK_ASSERT(ctx->current); 24543 NK_ASSERT(ctx->current->layout); 24544 if (!ctx || !ctx->current || !ctx->current->layout) 24545 return 0; 24546 24547 win = ctx->current; 24548 style = &ctx->style; 24549 s = nk_widget(&header, ctx); 24550 if (s == NK_WIDGET_INVALID) 24551 return 0; 24552 24553 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24554 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24555 is_clicked = nk_true; 24556 24557 /* draw combo box header background and border */ 24558 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24559 background = &style->combo.active; 24560 symbol_color = style->combo.symbol_active; 24561 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24562 background = &style->combo.hover; 24563 symbol_color = style->combo.symbol_hover; 24564 } else { 24565 background = &style->combo.normal; 24566 symbol_color = style->combo.symbol_hover; 24567 } 24568 24569 if (background->type == NK_STYLE_ITEM_IMAGE) { 24570 sym_background = nk_rgba(0,0,0,0); 24571 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24572 } else { 24573 sym_background = background->data.color; 24574 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24575 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24576 } 24577 { 24578 struct nk_rect bounds = {0,0,0,0}; 24579 struct nk_rect content; 24580 struct nk_rect button; 24581 24582 enum nk_symbol_type sym; 24583 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24584 sym = style->combo.sym_hover; 24585 else if (is_clicked) 24586 sym = style->combo.sym_active; 24587 else sym = style->combo.sym_normal; 24588 24589 /* calculate button */ 24590 button.w = header.h - 2 * style->combo.button_padding.y; 24591 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 24592 button.y = header.y + style->combo.button_padding.y; 24593 button.h = button.w; 24594 24595 content.x = button.x + style->combo.button.padding.x; 24596 content.y = button.y + style->combo.button.padding.y; 24597 content.w = button.w - 2 * style->combo.button.padding.x; 24598 content.h = button.h - 2 * style->combo.button.padding.y; 24599 24600 /* draw symbol */ 24601 bounds.h = header.h - 2 * style->combo.content_padding.y; 24602 bounds.y = header.y + style->combo.content_padding.y; 24603 bounds.x = header.x + style->combo.content_padding.x; 24604 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 24605 nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, 24606 1.0f, style->font); 24607 24608 /* draw open/close button */ 24609 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 24610 &ctx->style.combo.button, sym, style->font); 24611 } 24612 return nk_combo_begin(ctx, win, size, is_clicked, header); 24613 } 24614 NK_API int 24615 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len, 24616 enum nk_symbol_type symbol, struct nk_vec2 size) 24617 { 24618 struct nk_window *win; 24619 struct nk_style *style; 24620 struct nk_input *in; 24621 24622 struct nk_rect header; 24623 int is_clicked = nk_false; 24624 enum nk_widget_layout_states s; 24625 const struct nk_style_item *background; 24626 struct nk_color symbol_color; 24627 struct nk_text text; 24628 24629 NK_ASSERT(ctx); 24630 NK_ASSERT(ctx->current); 24631 NK_ASSERT(ctx->current->layout); 24632 if (!ctx || !ctx->current || !ctx->current->layout) 24633 return 0; 24634 24635 win = ctx->current; 24636 style = &ctx->style; 24637 s = nk_widget(&header, ctx); 24638 if (!s) return 0; 24639 24640 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24641 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24642 is_clicked = nk_true; 24643 24644 /* draw combo box header background and border */ 24645 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24646 background = &style->combo.active; 24647 symbol_color = style->combo.symbol_active; 24648 text.text = style->combo.label_active; 24649 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24650 background = &style->combo.hover; 24651 symbol_color = style->combo.symbol_hover; 24652 text.text = style->combo.label_hover; 24653 } else { 24654 background = &style->combo.normal; 24655 symbol_color = style->combo.symbol_normal; 24656 text.text = style->combo.label_normal; 24657 } 24658 if (background->type == NK_STYLE_ITEM_IMAGE) { 24659 text.background = nk_rgba(0,0,0,0); 24660 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24661 } else { 24662 text.background = background->data.color; 24663 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24664 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24665 } 24666 { 24667 struct nk_rect content; 24668 struct nk_rect button; 24669 struct nk_rect label; 24670 struct nk_rect image; 24671 24672 enum nk_symbol_type sym; 24673 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24674 sym = style->combo.sym_hover; 24675 else if (is_clicked) 24676 sym = style->combo.sym_active; 24677 else sym = style->combo.sym_normal; 24678 24679 /* calculate button */ 24680 button.w = header.h - 2 * style->combo.button_padding.y; 24681 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24682 button.y = header.y + style->combo.button_padding.y; 24683 button.h = button.w; 24684 24685 content.x = button.x + style->combo.button.padding.x; 24686 content.y = button.y + style->combo.button.padding.y; 24687 content.w = button.w - 2 * style->combo.button.padding.x; 24688 content.h = button.h - 2 * style->combo.button.padding.y; 24689 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24690 &ctx->style.combo.button, sym, style->font); 24691 24692 /* draw symbol */ 24693 image.x = header.x + style->combo.content_padding.x; 24694 image.y = header.y + style->combo.content_padding.y; 24695 image.h = header.h - 2 * style->combo.content_padding.y; 24696 image.w = image.h; 24697 nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, 24698 1.0f, style->font); 24699 24700 /* draw label */ 24701 text.padding = nk_vec2(0,0); 24702 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 24703 label.y = header.y + style->combo.content_padding.y; 24704 label.w = (button.x - style->combo.content_padding.x) - label.x; 24705 label.h = header.h - 2 * style->combo.content_padding.y; 24706 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 24707 } 24708 return nk_combo_begin(ctx, win, size, is_clicked, header); 24709 } 24710 NK_API int 24711 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) 24712 { 24713 struct nk_window *win; 24714 struct nk_style *style; 24715 const struct nk_input *in; 24716 24717 struct nk_rect header; 24718 int is_clicked = nk_false; 24719 enum nk_widget_layout_states s; 24720 const struct nk_style_item *background; 24721 24722 NK_ASSERT(ctx); 24723 NK_ASSERT(ctx->current); 24724 NK_ASSERT(ctx->current->layout); 24725 if (!ctx || !ctx->current || !ctx->current->layout) 24726 return 0; 24727 24728 win = ctx->current; 24729 style = &ctx->style; 24730 s = nk_widget(&header, ctx); 24731 if (s == NK_WIDGET_INVALID) 24732 return 0; 24733 24734 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24735 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24736 is_clicked = nk_true; 24737 24738 /* draw combo box header background and border */ 24739 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 24740 background = &style->combo.active; 24741 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24742 background = &style->combo.hover; 24743 else background = &style->combo.normal; 24744 24745 if (background->type == NK_STYLE_ITEM_IMAGE) { 24746 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24747 } else { 24748 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24749 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24750 } 24751 { 24752 struct nk_rect bounds = {0,0,0,0}; 24753 struct nk_rect content; 24754 struct nk_rect button; 24755 24756 enum nk_symbol_type sym; 24757 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24758 sym = style->combo.sym_hover; 24759 else if (is_clicked) 24760 sym = style->combo.sym_active; 24761 else sym = style->combo.sym_normal; 24762 24763 /* calculate button */ 24764 button.w = header.h - 2 * style->combo.button_padding.y; 24765 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 24766 button.y = header.y + style->combo.button_padding.y; 24767 button.h = button.w; 24768 24769 content.x = button.x + style->combo.button.padding.x; 24770 content.y = button.y + style->combo.button.padding.y; 24771 content.w = button.w - 2 * style->combo.button.padding.x; 24772 content.h = button.h - 2 * style->combo.button.padding.y; 24773 24774 /* draw image */ 24775 bounds.h = header.h - 2 * style->combo.content_padding.y; 24776 bounds.y = header.y + style->combo.content_padding.y; 24777 bounds.x = header.x + style->combo.content_padding.x; 24778 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 24779 nk_draw_image(&win->buffer, bounds, &img, nk_white); 24780 24781 /* draw open/close button */ 24782 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 24783 &ctx->style.combo.button, sym, style->font); 24784 } 24785 return nk_combo_begin(ctx, win, size, is_clicked, header); 24786 } 24787 NK_API int 24788 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, 24789 struct nk_image img, struct nk_vec2 size) 24790 { 24791 struct nk_window *win; 24792 struct nk_style *style; 24793 struct nk_input *in; 24794 24795 struct nk_rect header; 24796 int is_clicked = nk_false; 24797 enum nk_widget_layout_states s; 24798 const struct nk_style_item *background; 24799 struct nk_text text; 24800 24801 NK_ASSERT(ctx); 24802 NK_ASSERT(ctx->current); 24803 NK_ASSERT(ctx->current->layout); 24804 if (!ctx || !ctx->current || !ctx->current->layout) 24805 return 0; 24806 24807 win = ctx->current; 24808 style = &ctx->style; 24809 s = nk_widget(&header, ctx); 24810 if (!s) return 0; 24811 24812 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24813 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24814 is_clicked = nk_true; 24815 24816 /* draw combo box header background and border */ 24817 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24818 background = &style->combo.active; 24819 text.text = style->combo.label_active; 24820 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24821 background = &style->combo.hover; 24822 text.text = style->combo.label_hover; 24823 } else { 24824 background = &style->combo.normal; 24825 text.text = style->combo.label_normal; 24826 } 24827 if (background->type == NK_STYLE_ITEM_IMAGE) { 24828 text.background = nk_rgba(0,0,0,0); 24829 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24830 } else { 24831 text.background = background->data.color; 24832 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24833 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24834 } 24835 { 24836 struct nk_rect content; 24837 struct nk_rect button; 24838 struct nk_rect label; 24839 struct nk_rect image; 24840 24841 enum nk_symbol_type sym; 24842 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24843 sym = style->combo.sym_hover; 24844 else if (is_clicked) 24845 sym = style->combo.sym_active; 24846 else sym = style->combo.sym_normal; 24847 24848 /* calculate button */ 24849 button.w = header.h - 2 * style->combo.button_padding.y; 24850 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24851 button.y = header.y + style->combo.button_padding.y; 24852 button.h = button.w; 24853 24854 content.x = button.x + style->combo.button.padding.x; 24855 content.y = button.y + style->combo.button.padding.y; 24856 content.w = button.w - 2 * style->combo.button.padding.x; 24857 content.h = button.h - 2 * style->combo.button.padding.y; 24858 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24859 &ctx->style.combo.button, sym, style->font); 24860 24861 /* draw image */ 24862 image.x = header.x + style->combo.content_padding.x; 24863 image.y = header.y + style->combo.content_padding.y; 24864 image.h = header.h - 2 * style->combo.content_padding.y; 24865 image.w = image.h; 24866 nk_draw_image(&win->buffer, image, &img, nk_white); 24867 24868 /* draw label */ 24869 text.padding = nk_vec2(0,0); 24870 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 24871 label.y = header.y + style->combo.content_padding.y; 24872 label.w = (button.x - style->combo.content_padding.x) - label.x; 24873 label.h = header.h - 2 * style->combo.content_padding.y; 24874 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 24875 } 24876 return nk_combo_begin(ctx, win, size, is_clicked, header); 24877 } 24878 NK_API int 24879 nk_combo_begin_symbol_label(struct nk_context *ctx, 24880 const char *selected, enum nk_symbol_type type, struct nk_vec2 size) 24881 { 24882 return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size); 24883 } 24884 NK_API int 24885 nk_combo_begin_image_label(struct nk_context *ctx, 24886 const char *selected, struct nk_image img, struct nk_vec2 size) 24887 { 24888 return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size); 24889 } 24890 NK_API int 24891 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align) 24892 { 24893 return nk_contextual_item_text(ctx, text, len, align); 24894 } 24895 NK_API int 24896 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align) 24897 { 24898 return nk_contextual_item_label(ctx, label, align); 24899 } 24900 NK_API int 24901 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text, 24902 int len, nk_flags alignment) 24903 { 24904 return nk_contextual_item_image_text(ctx, img, text, len, alignment); 24905 } 24906 NK_API int 24907 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img, 24908 const char *text, nk_flags alignment) 24909 { 24910 return nk_contextual_item_image_label(ctx, img, text, alignment); 24911 } 24912 NK_API int 24913 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 24914 const char *text, int len, nk_flags alignment) 24915 { 24916 return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment); 24917 } 24918 NK_API int 24919 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 24920 const char *label, nk_flags alignment) 24921 { 24922 return nk_contextual_item_symbol_label(ctx, sym, label, alignment); 24923 } 24924 NK_API void nk_combo_end(struct nk_context *ctx) 24925 { 24926 nk_contextual_end(ctx); 24927 } 24928 NK_API void nk_combo_close(struct nk_context *ctx) 24929 { 24930 nk_contextual_close(ctx); 24931 } 24932 NK_API int 24933 nk_combo(struct nk_context *ctx, const char **items, int count, 24934 int selected, int item_height, struct nk_vec2 size) 24935 { 24936 int i = 0; 24937 int max_height; 24938 struct nk_vec2 item_spacing; 24939 struct nk_vec2 window_padding; 24940 24941 NK_ASSERT(ctx); 24942 NK_ASSERT(items); 24943 NK_ASSERT(ctx->current); 24944 if (!ctx || !items ||!count) 24945 return selected; 24946 24947 item_spacing = ctx->style.window.spacing; 24948 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 24949 max_height = count * item_height + count * (int)item_spacing.y; 24950 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 24951 size.y = NK_MIN(size.y, (float)max_height); 24952 if (nk_combo_begin_label(ctx, items[selected], size)) { 24953 nk_layout_row_dynamic(ctx, (float)item_height, 1); 24954 for (i = 0; i < count; ++i) { 24955 if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) 24956 selected = i; 24957 } 24958 nk_combo_end(ctx); 24959 } 24960 return selected; 24961 } 24962 NK_API int 24963 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, 24964 int separator, int selected, int count, int item_height, struct nk_vec2 size) 24965 { 24966 int i; 24967 int max_height; 24968 struct nk_vec2 item_spacing; 24969 struct nk_vec2 window_padding; 24970 const char *current_item; 24971 const char *iter; 24972 int length = 0; 24973 24974 NK_ASSERT(ctx); 24975 NK_ASSERT(items_separated_by_separator); 24976 if (!ctx || !items_separated_by_separator) 24977 return selected; 24978 24979 /* calculate popup window */ 24980 item_spacing = ctx->style.window.spacing; 24981 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 24982 max_height = count * item_height + count * (int)item_spacing.y; 24983 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 24984 size.y = NK_MIN(size.y, (float)max_height); 24985 24986 /* find selected item */ 24987 current_item = items_separated_by_separator; 24988 for (i = 0; i < count; ++i) { 24989 iter = current_item; 24990 while (*iter && *iter != separator) iter++; 24991 length = (int)(iter - current_item); 24992 if (i == selected) break; 24993 current_item = iter + 1; 24994 } 24995 24996 if (nk_combo_begin_text(ctx, current_item, length, size)) { 24997 current_item = items_separated_by_separator; 24998 nk_layout_row_dynamic(ctx, (float)item_height, 1); 24999 for (i = 0; i < count; ++i) { 25000 iter = current_item; 25001 while (*iter && *iter != separator) iter++; 25002 length = (int)(iter - current_item); 25003 if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) 25004 selected = i; 25005 current_item = current_item + length + 1; 25006 } 25007 nk_combo_end(ctx); 25008 } 25009 return selected; 25010 } 25011 NK_API int 25012 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros, 25013 int selected, int count, int item_height, struct nk_vec2 size) 25014 { 25015 return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size); 25016 } 25017 NK_API int 25018 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), 25019 void *userdata, int selected, int count, int item_height, struct nk_vec2 size) 25020 { 25021 int i; 25022 int max_height; 25023 struct nk_vec2 item_spacing; 25024 struct nk_vec2 window_padding; 25025 const char *item; 25026 25027 NK_ASSERT(ctx); 25028 NK_ASSERT(item_getter); 25029 if (!ctx || !item_getter) 25030 return selected; 25031 25032 /* calculate popup window */ 25033 item_spacing = ctx->style.window.spacing; 25034 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25035 max_height = count * item_height + count * (int)item_spacing.y; 25036 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25037 size.y = NK_MIN(size.y, (float)max_height); 25038 25039 item_getter(userdata, selected, &item); 25040 if (nk_combo_begin_label(ctx, item, size)) { 25041 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25042 for (i = 0; i < count; ++i) { 25043 item_getter(userdata, i, &item); 25044 if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) 25045 selected = i; 25046 } 25047 nk_combo_end(ctx); 25048 } return selected; 25049 } 25050 NK_API void 25051 nk_combobox(struct nk_context *ctx, const char **items, int count, 25052 int *selected, int item_height, struct nk_vec2 size) 25053 { 25054 *selected = nk_combo(ctx, items, count, *selected, item_height, size); 25055 } 25056 NK_API void 25057 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros, 25058 int *selected, int count, int item_height, struct nk_vec2 size) 25059 { 25060 *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size); 25061 } 25062 NK_API void 25063 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator, 25064 int separator,int *selected, int count, int item_height, struct nk_vec2 size) 25065 { 25066 *selected = nk_combo_separator(ctx, items_separated_by_separator, separator, 25067 *selected, count, item_height, size); 25068 } 25069 NK_API void 25070 nk_combobox_callback(struct nk_context *ctx, 25071 void(*item_getter)(void* data, int id, const char **out_text), 25072 void *userdata, int *selected, int count, int item_height, struct nk_vec2 size) 25073 { 25074 *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size); 25075 } 25076 25077 25078 25079 25080 25081 /* =============================================================== 25082 * 25083 * TOOLTIP 25084 * 25085 * ===============================================================*/ 25086 NK_API int 25087 nk_tooltip_begin(struct nk_context *ctx, float width) 25088 { 25089 int x,y,w,h; 25090 struct nk_window *win; 25091 const struct nk_input *in; 25092 struct nk_rect bounds; 25093 int ret; 25094 25095 NK_ASSERT(ctx); 25096 NK_ASSERT(ctx->current); 25097 NK_ASSERT(ctx->current->layout); 25098 if (!ctx || !ctx->current || !ctx->current->layout) 25099 return 0; 25100 25101 /* make sure that no nonblocking popup is currently active */ 25102 win = ctx->current; 25103 in = &ctx->input; 25104 if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK)) 25105 return 0; 25106 25107 w = nk_iceilf(width); 25108 h = nk_iceilf(nk_null_rect.h); 25109 x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x; 25110 y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y; 25111 25112 bounds.x = (float)x; 25113 bounds.y = (float)y; 25114 bounds.w = (float)w; 25115 bounds.h = (float)h; 25116 25117 ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC, 25118 "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds); 25119 if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 25120 win->popup.type = NK_PANEL_TOOLTIP; 25121 ctx->current->layout->type = NK_PANEL_TOOLTIP; 25122 return ret; 25123 } 25124 25125 NK_API void 25126 nk_tooltip_end(struct nk_context *ctx) 25127 { 25128 NK_ASSERT(ctx); 25129 NK_ASSERT(ctx->current); 25130 if (!ctx || !ctx->current) return; 25131 ctx->current->seq--; 25132 nk_popup_close(ctx); 25133 nk_popup_end(ctx); 25134 } 25135 NK_API void 25136 nk_tooltip(struct nk_context *ctx, const char *text) 25137 { 25138 const struct nk_style *style; 25139 struct nk_vec2 padding; 25140 25141 int text_len; 25142 float text_width; 25143 float text_height; 25144 25145 NK_ASSERT(ctx); 25146 NK_ASSERT(ctx->current); 25147 NK_ASSERT(ctx->current->layout); 25148 NK_ASSERT(text); 25149 if (!ctx || !ctx->current || !ctx->current->layout || !text) 25150 return; 25151 25152 /* fetch configuration data */ 25153 style = &ctx->style; 25154 padding = style->window.padding; 25155 25156 /* calculate size of the text and tooltip */ 25157 text_len = nk_strlen(text); 25158 text_width = style->font->width(style->font->userdata, 25159 style->font->height, text, text_len); 25160 text_width += (4 * padding.x); 25161 text_height = (style->font->height + 2 * padding.y); 25162 25163 /* execute tooltip and fill with text */ 25164 if (nk_tooltip_begin(ctx, (float)text_width)) { 25165 nk_layout_row_dynamic(ctx, (float)text_height, 1); 25166 nk_text(ctx, text, text_len, NK_TEXT_LEFT); 25167 nk_tooltip_end(ctx); 25168 } 25169 } 25170 #ifdef NK_INCLUDE_STANDARD_VARARGS 25171 NK_API void 25172 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...) 25173 { 25174 va_list args; 25175 va_start(args, fmt); 25176 nk_tooltipfv(ctx, fmt, args); 25177 va_end(args); 25178 } 25179 NK_API void 25180 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) 25181 { 25182 char buf[256]; 25183 nk_strfmt(buf, NK_LEN(buf), fmt, args); 25184 nk_tooltip(ctx, buf); 25185 } 25186 #endif 25187 25188 25189 25190 #endif /* NK_IMPLEMENTATION */ 25191 25192 /* 25193 /// ## License 25194 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 25195 /// ------------------------------------------------------------------------------ 25196 /// This software is available under 2 licenses -- choose whichever you prefer. 25197 /// ------------------------------------------------------------------------------ 25198 /// ALTERNATIVE A - MIT License 25199 /// Copyright (c) 2016-2018 Micha Mettke 25200 /// Permission is hereby granted, free of charge, to any person obtaining a copy of 25201 /// this software and associated documentation files (the "Software"), to deal in 25202 /// the Software without restriction, including without limitation the rights to 25203 /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 25204 /// of the Software, and to permit persons to whom the Software is furnished to do 25205 /// so, subject to the following conditions: 25206 /// The above copyright notice and this permission notice shall be included in all 25207 /// copies or substantial portions of the Software. 25208 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25209 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25210 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25211 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25212 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25213 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25214 /// SOFTWARE. 25215 /// ------------------------------------------------------------------------------ 25216 /// ALTERNATIVE B - Public Domain (www.unlicense.org) 25217 /// This is free and unencumbered software released into the public domain. 25218 /// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 25219 /// software, either in source code form or as a compiled binary, for any purpose, 25220 /// commercial or non-commercial, and by any means. 25221 /// In jurisdictions that recognize copyright laws, the author or authors of this 25222 /// software dedicate any and all copyright interest in the software to the public 25223 /// domain. We make this dedication for the benefit of the public at large and to 25224 /// the detriment of our heirs and successors. We intend this dedication to be an 25225 /// overt act of relinquishment in perpetuity of all present and future rights to 25226 /// this software under copyright law. 25227 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25228 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25229 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25230 /// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 25231 /// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25232 /// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25233 /// ------------------------------------------------------------------------------ 25234 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25235 25236 /// ## Changelog 25237 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 25238 /// [date][x.yy.zz]-[description] 25239 /// -[date]: date on which the change has been pushed 25240 /// -[x.yy.zz]: Numerical version string representation. Each version number on the right 25241 /// resets back to zero if version on the left is incremented. 25242 /// - [x]: Major version with API and library breaking changes 25243 /// - [yy]: Minor version with non-breaking API and library changes 25244 /// - [zz]: Bug fix version with no direct changes to API 25245 /// 25246 /// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame 25247 /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to 25248 /// clear provided buffers. So make sure to either free 25249 /// or clear each passed buffer after calling nk_convert. 25250 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior 25251 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process 25252 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype 25253 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug 25254 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title 25255 /// - 2018/01/07 (3.00.1) - Started to change documentation style 25256 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken 25257 /// because of conversions between float and byte color representation. 25258 /// Color pickers now use floating point values to represent 25259 /// HSV values. To get back the old behavior I added some additional 25260 /// color conversion functions to cast between nk_color and 25261 /// nk_colorf. 25262 /// - 2017/12/23 (2.00.7) - Fixed small warning 25263 /// - 2017/12/23 (2.00.7) - Fixed nk_edit_buffer behavior if activated to allow input 25264 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior 25265 /// - 2017/12/04 (2.00.6) - Added formated string tooltip widget 25266 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag NK_WINDOW_NO_INPUT 25267 /// - 2017/11/15 (2.00.4) - Fixed font merging 25268 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions 25269 /// - 2017/09/14 (2.00.2) - Fixed nk_edit_buffer and nk_edit_focus behavior 25270 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior 25271 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now 25272 /// require the name of the window and must happen outside the window 25273 /// building process (between function call nk_begin and nk_end). 25274 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last 25275 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows 25276 /// - 2017/08/27 (1.40.7) - Fixed window background flag 25277 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked 25278 /// query for widgets 25279 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked 25280 /// and filled rectangles 25281 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in 25282 /// process of being destroyed. 25283 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in 25284 /// window instead of directly in table. 25285 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro 25286 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero 25287 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only 25288 /// comes in effect if you pass in zero was row height argument 25289 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change 25290 /// how layouting works. From now there will be an internal minimum 25291 /// row height derived from font height. If you need a row smaller than 25292 /// that you can directly set it by `nk_layout_set_min_row_height` and 25293 /// reset the value back by calling `nk_layout_reset_min_row_height. 25294 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix 25295 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a nk_layout_xxx function 25296 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer 25297 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped 25298 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries 25299 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space 25300 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size 25301 /// - 2017/05/06 (1.38.0) - Added platform double-click support 25302 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends 25303 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipbard support 25304 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing 25305 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error 25306 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags 25307 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption 25308 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows 25309 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior 25310 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377 25311 /// - 2017/03/18 (1.34.3) - Fixed long window header titles 25312 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering 25313 /// - 2017/03/04 (1.34.1) - Fixed group closable flag 25314 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support 25315 /// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus 25316 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows 25317 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows 25318 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing 25319 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner 25320 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both 25321 /// dynamic and static widgets. 25322 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit 25323 /// - 2016/12/31 (1.29.2)- Fixed closing window bug of minimized windows 25324 /// - 2016/12/03 (1.29.1)- Fixed wrapped text with no seperator and C89 error 25325 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters 25326 /// - 2016/11/22 (1.28.6)- Fixed window minimized closing bug 25327 /// - 2016/11/19 (1.28.5)- Fixed abstract combo box closing behavior 25328 /// - 2016/11/19 (1.28.4)- Fixed tooltip flickering 25329 /// - 2016/11/19 (1.28.3)- Fixed memory leak caused by popup repeated closing 25330 /// - 2016/11/18 (1.28.2)- Fixed memory leak caused by popup panel allocation 25331 /// - 2016/11/10 (1.28.1)- Fixed some warnings and C++ error 25332 /// - 2016/11/10 (1.28.0)- Added additional `nk_button` versions which allows to directly 25333 /// pass in a style struct to change buttons visual. 25334 /// - 2016/11/10 (1.27.0)- Added additional 'nk_tree' versions to support external state 25335 /// storage. Just like last the `nk_group` commit the main 25336 /// advantage is that you optionally can minimize nuklears runtime 25337 /// memory consumption or handle hash collisions. 25338 /// - 2016/11/09 (1.26.0)- Added additional `nk_group` version to support external scrollbar 25339 /// offset storage. Main advantage is that you can externalize 25340 /// the memory management for the offset. It could also be helpful 25341 /// if you have a hash collision in `nk_group_begin` but really 25342 /// want the name. In addition I added `nk_list_view` which allows 25343 /// to draw big lists inside a group without actually having to 25344 /// commit the whole list to nuklear (issue #269). 25345 /// - 2016/10/30 (1.25.1)- Fixed clipping rectangle bug inside `nk_draw_list` 25346 /// - 2016/10/29 (1.25.0)- Pulled `nk_panel` memory management into nuklear and out of 25347 /// the hands of the user. From now on users don't have to care 25348 /// about panels unless they care about some information. If you 25349 /// still need the panel just call `nk_window_get_panel`. 25350 /// - 2016/10/21 (1.24.0)- Changed widget border drawing to stroked rectangle from filled 25351 /// rectangle for less overdraw and widget background transparency. 25352 /// - 2016/10/18 (1.23.0)- Added `nk_edit_focus` for manually edit widget focus control 25353 /// - 2016/09/29 (1.22.7)- Fixed deduction of basic type in non `<stdint.h>` compilation 25354 /// - 2016/09/29 (1.22.6)- Fixed edit widget UTF-8 text cursor drawing bug 25355 /// - 2016/09/28 (1.22.5)- Fixed edit widget UTF-8 text appending/inserting/removing 25356 /// - 2016/09/28 (1.22.4)- Fixed drawing bug inside edit widgets which offset all text 25357 /// text in every edit widget if one of them is scrolled. 25358 /// - 2016/09/28 (1.22.3)- Fixed small bug in edit widgets if not active. The wrong 25359 /// text length is passed. It should have been in bytes but 25360 /// was passed as glyphes. 25361 /// - 2016/09/20 (1.22.2)- Fixed color button size calculation 25362 /// - 2016/09/20 (1.22.1)- Fixed some `nk_vsnprintf` behavior bugs and removed 25363 /// `<stdio.h>` again from `NK_INCLUDE_STANDARD_VARARGS`. 25364 /// - 2016/09/18 (1.22.0)- C89 does not support vsnprintf only C99 and newer as well 25365 /// as C++11 and newer. In addition to use vsnprintf you have 25366 /// to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS` 25367 /// is not enough. That behavior is now fixed. By default if 25368 /// both varargs as well as stdio is selected I try to use 25369 /// vsnprintf if not possible I will revert to vsprintf. If 25370 /// varargs but not stdio was defined I will use my own function. 25371 /// - 2016/09/15 (1.21.2)- Fixed panel `close` behavior for deeper panel levels 25372 /// - 2016/09/15 (1.21.1)- Fixed C++ errors and wrong argument to `nk_panel_get_xxxx` 25373 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo, 25374 /// and contextual which prevented closing in y-direction if 25375 /// popup did not reach max height. 25376 /// In addition the height parameter was changed into vec2 25377 /// for width and height to have more control over the popup size. 25378 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection 25379 /// - 2016/09/13 (1.20.2)- Fixed slider behavior hopefully for the last time. This time 25380 /// all calculation are correct so no more hackery. 25381 /// - 2016/09/13 (1.20.1)- Internal change to divide window/panel flags into panel flags and types. 25382 /// Suprisinly spend years in C and still happened to confuse types 25383 /// with flags. Probably something to take note. 25384 /// - 2016/09/08 (1.20.0)- Added additional helper function to make it easier to just 25385 /// take the produced buffers from `nk_convert` and unplug the 25386 /// iteration process from `nk_context`. So now you can 25387 /// just use the vertex,element and command buffer + two pointer 25388 /// inside the command buffer retrieved by calls `nk__draw_begin` 25389 /// and `nk__draw_end` and macro `nk_draw_foreach_bounded`. 25390 /// - 2016/09/08 (1.19.0)- Added additional asserts to make sure every `nk_xxx_begin` call 25391 /// for windows, popups, combobox, menu and contextual is guarded by 25392 /// `if` condition and does not produce false drawing output. 25393 /// - 2016/09/08 (1.18.0)- Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` 25394 /// to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and 25395 /// `NK_SYMBOL_RECT_OUTLINE`. 25396 /// - 2016/09/08 (1.17.0)- Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` 25397 /// to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and 25398 /// `NK_SYMBOL_CIRCLE_OUTLINE`. 25399 /// - 2016/09/08 (1.16.0)- Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` 25400 /// is not defined by supporting the biggest compiler GCC, clang and MSVC. 25401 /// - 2016/09/07 (1.15.3)- Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error 25402 /// - 2016/09/04 (1.15.2)- Fixed wrong combobox height calculation 25403 /// - 2016/09/03 (1.15.1)- Fixed gaps inside combo boxes in OpenGL 25404 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and 25405 /// instead made it user provided. The range of types to convert 25406 /// to is quite limited at the moment, but I would be more than 25407 /// happy to accept PRs to add additional. 25408 /// - 2016/08/30 (1.14.2) - Removed unused variables 25409 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors 25410 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly 25411 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables 25412 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would 25413 /// refrain from using slider with a big number of steps. 25414 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the 25415 /// window was in Read Only Mode. 25416 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just 25417 /// a hack for combo box and menu. 25418 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since 25419 /// it is bugged and causes issues in window selection. 25420 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now 25421 /// determined by the scrollbar size 25422 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11 25423 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection 25424 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code 25425 /// handling panel padding and panel border. 25426 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx` 25427 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups 25428 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes 25429 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for 25430 /// hash collisions. Currently limited to NK_WINDOW_MAX_NAME 25431 /// which in term can be redefined if not big enough. 25432 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code 25433 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released' 25434 /// to account for key press and release happening in one frame. 25435 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate 25436 /// - 2016/08/17 (1.09.6)- Removed invalid check for value zero in nk_propertyx 25437 /// - 2016/08/16 (1.09.5)- Fixed ROM mode for deeper levels of popup windows parents. 25438 /// - 2016/08/15 (1.09.4)- Editbox are now still active if enter was pressed with flag 25439 /// `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep 25440 /// typing after commiting. 25441 /// - 2016/08/15 (1.09.4)- Removed redundant code 25442 /// - 2016/08/15 (1.09.4)- Fixed negative numbers in `nk_strtoi` and remove unused variable 25443 /// - 2016/08/15 (1.09.3)- Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background 25444 /// window only as selected by hovering and not by clicking. 25445 /// - 2016/08/14 (1.09.2)- Fixed a bug in font atlas which caused wrong loading 25446 /// of glyphes for font with multiple ranges. 25447 /// - 2016/08/12 (1.09.1)- Added additional function to check if window is currently 25448 /// hidden and therefore not visible. 25449 /// - 2016/08/12 (1.09.1)- nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` 25450 /// instead of the old flag `NK_WINDOW_HIDDEN` 25451 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed 25452 /// the underlying implementation to not cast to float and instead 25453 /// work directly on the given values. 25454 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 25455 /// floating pointer number to string conversion for additional 25456 /// precision. 25457 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 25458 /// string to floating point number conversion for additional 25459 /// precision. 25460 /// - 2016/08/08 (1.07.2)- Fixed compiling error without define NK_INCLUDE_FIXED_TYPE 25461 /// - 2016/08/08 (1.07.1)- Fixed possible floating point error inside `nk_widget` leading 25462 /// to wrong wiget width calculation which results in widgets falsly 25463 /// becomming tagged as not inside window and cannot be accessed. 25464 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and 25465 /// closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown 25466 /// by using `nk_window_show` and closed by either clicking the close 25467 /// icon in a window or by calling `nk_window_close`. Only closed 25468 /// windows get removed at the end of the frame while hidden windows 25469 /// remain. 25470 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to 25471 /// `nk_edit_string` which takes, edits and outputs a '\0' terminated string. 25472 /// - 2016/08/08 (1.05.4)- Fixed scrollbar auto hiding behavior 25473 /// - 2016/08/08 (1.05.3)- Fixed wrong panel padding selection in `nk_layout_widget_space` 25474 /// - 2016/08/07 (1.05.2)- Fixed old bug in dynamic immediate mode layout API, calculating 25475 /// wrong item spacing and panel width. 25476 ///- 2016/08/07 (1.05.1)- Hopefully finally fixed combobox popup drawing bug 25477 ///- 2016/08/07 (1.05.0) - Split varargs away from NK_INCLUDE_STANDARD_IO into own 25478 /// define NK_INCLUDE_STANDARD_VARARGS to allow more fine 25479 /// grained controlled over library includes. 25480 /// - 2016/08/06 (1.04.5)- Changed memset calls to NK_MEMSET 25481 /// - 2016/08/04 (1.04.4)- Fixed fast window scaling behavior 25482 /// - 2016/08/04 (1.04.3)- Fixed window scaling, movement bug which appears if you 25483 /// move/scale a window and another window is behind it. 25484 /// If you are fast enough then the window behind gets activated 25485 /// and the operation is blocked. I now require activating 25486 /// by hovering only if mouse is not pressed. 25487 /// - 2016/08/04 (1.04.2)- Fixed changing fonts 25488 /// - 2016/08/03 (1.04.1)- Fixed `NK_WINDOW_BACKGROUND` behavior 25489 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image` 25490 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for 25491 /// sub windows (combo, menu, ...) 25492 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor 25493 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window 25494 /// to be always in the background of the screen 25495 /// - 2016/08/03 (1.03.2)- Removed invalid assert macro for NK_RGB color picker 25496 /// - 2016/08/01 (1.03.1)- Added helper macros into header include guard 25497 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to 25498 /// simplify memory management by removing the need to 25499 /// allocate the pool. 25500 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled 25501 /// will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT 25502 /// seconds without window interaction. To make it work 25503 /// you have to also set a delta time inside the `nk_context`. 25504 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs 25505 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context` 25506 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument 25507 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified 25508 /// font atlas memory management by converting pointer 25509 /// arrays for fonts and font configurations to lists. 25510 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button 25511 /// behavior instead of passing it for every function call. 25512 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25513 25514 /// ## Gallery 25515 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png) 25516 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png) 25517 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png) 25518 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png) 25519 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png) 25520 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png) 25521 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif) 25522 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png) 25523 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png) 25524 /// 25525 /// ## Credits 25526 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br /> 25527 /// 25528 /// Embeds [stb_texedit](https://github.com/nothings/stb/blob/master/stb_textedit.h), [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) and [stb_rectpack](https://github.com/nothings/stb/blob/master/stb_rect_pack.h) by Sean Barret (public domain) <br /> 25529 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br /> 25530 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br /> 25531 /// 25532 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and 25533 /// giving me the inspiration for this library, Casey Muratori for handmade hero 25534 /// and his original immediate mode graphical user interface idea and Sean 25535 /// Barret for his amazing single header libraries which restored my faith 25536 /// in libraries and brought me to create some of my own. Finally Apoorva Joshi 25537 /// for his single header file packer. 25538 */ 25539