1 /* 2 /// # Nuklear 3 ///  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 /// NK_UINT_DRAW_INDEX | Defining this will set the size of vertex index elements when using NK_VERTEX_BUFFER_OUTPUT to 32bit instead of the default of 16bit 109 /// NK_KEYSTATE_BASED_INPUT | Define this if your backend uses key state for each frame rather than key press/release events 110 /// 111 /// !!! WARNING 112 /// The following flags will pull in the standard C library: 113 /// - NK_INCLUDE_DEFAULT_ALLOCATOR 114 /// - NK_INCLUDE_STANDARD_IO 115 /// - NK_INCLUDE_STANDARD_VARARGS 116 /// 117 /// !!! WARNING 118 /// The following flags if defined need to be defined for both header and implementation: 119 /// - NK_INCLUDE_FIXED_TYPES 120 /// - NK_INCLUDE_DEFAULT_ALLOCATOR 121 /// - NK_INCLUDE_STANDARD_VARARGS 122 /// - NK_INCLUDE_VERTEX_BUFFER_OUTPUT 123 /// - NK_INCLUDE_FONT_BAKING 124 /// - NK_INCLUDE_DEFAULT_FONT 125 /// - NK_INCLUDE_STANDARD_VARARGS 126 /// - NK_INCLUDE_COMMAND_USERDATA 127 /// - NK_UINT_DRAW_INDEX 128 /// 129 /// ### Constants 130 /// Define | Description 131 /// --------------------------------|--------------------------------------- 132 /// 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. 133 /// NK_MAX_NUMBER_BUFFER | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient. 134 /// 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. 135 /// 136 /// !!! WARNING 137 /// The following constants if defined need to be defined for both header and implementation: 138 /// - NK_MAX_NUMBER_BUFFER 139 /// - NK_BUFFER_DEFAULT_INITIAL_SIZE 140 /// - NK_INPUT_MAX 141 /// 142 /// ### Dependencies 143 /// Function | Description 144 /// ------------|--------------------------------------------------------------- 145 /// NK_ASSERT | If you don't define this, nuklear will use <assert.h> with assert(). 146 /// NK_MEMSET | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version. 147 /// NK_MEMCPY | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version. 148 /// 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. 149 /// NK_SIN | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation. 150 /// NK_COS | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation. 151 /// 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!). 152 /// 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!). 153 /// 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. 154 /// 155 /// !!! WARNING 156 /// The following dependencies will pull in the standard C library if not redefined: 157 /// - NK_ASSERT 158 /// 159 /// !!! WARNING 160 /// The following dependencies if defined need to be defined for both header and implementation: 161 /// - NK_ASSERT 162 /// 163 /// !!! WARNING 164 /// The following dependencies if defined need to be defined only for the implementation part: 165 /// - NK_MEMSET 166 /// - NK_MEMCPY 167 /// - NK_SQRT 168 /// - NK_SIN 169 /// - NK_COS 170 /// - NK_STRTOD 171 /// - NK_DTOA 172 /// - NK_VSNPRINTF 173 /// 174 /// ## Example 175 /// 176 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 177 /// // init gui state 178 /// enum {EASY, HARD}; 179 /// static int op = EASY; 180 /// static float value = 0.6f; 181 /// static int i = 20; 182 /// struct nk_context ctx; 183 /// 184 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font); 185 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220), 186 /// NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { 187 /// // fixed widget pixel width 188 /// nk_layout_row_static(&ctx, 30, 80, 1); 189 /// if (nk_button_label(&ctx, "button")) { 190 /// // event handling 191 /// } 192 /// 193 /// // fixed widget window ratio width 194 /// nk_layout_row_dynamic(&ctx, 30, 2); 195 /// if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY; 196 /// if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD; 197 /// 198 /// // custom widget pixel width 199 /// nk_layout_row_begin(&ctx, NK_STATIC, 30, 2); 200 /// { 201 /// nk_layout_row_push(&ctx, 50); 202 /// nk_label(&ctx, "Volume:", NK_TEXT_LEFT); 203 /// nk_layout_row_push(&ctx, 110); 204 /// nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f); 205 /// } 206 /// nk_layout_row_end(&ctx); 207 /// } 208 /// nk_end(&ctx); 209 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 210 /// 211 ///  212 /// 213 /// ## API 214 /// 215 */ 216 #ifndef NK_SINGLE_FILE 217 #define NK_SINGLE_FILE 218 #endif 219 220 #ifndef NK_NUKLEAR_H_ 221 #define NK_NUKLEAR_H_ 222 223 #ifdef __cplusplus 224 extern "C" { 225 #endif 226 /* 227 * ============================================================== 228 * 229 * CONSTANTS 230 * 231 * =============================================================== 232 */ 233 #define NK_UNDEFINED (-1.0f) 234 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */ 235 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/ 236 #ifndef NK_INPUT_MAX 237 #define NK_INPUT_MAX 16 238 #endif 239 #ifndef NK_MAX_NUMBER_BUFFER 240 #define NK_MAX_NUMBER_BUFFER 64 241 #endif 242 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT 243 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f 244 #endif 245 /* 246 * ============================================================== 247 * 248 * HELPER 249 * 250 * =============================================================== 251 */ 252 #ifndef NK_API 253 #ifdef NK_PRIVATE 254 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L)) 255 #define NK_API static inline 256 #elif defined(__cplusplus) 257 #define NK_API static inline 258 #else 259 #define NK_API static 260 #endif 261 #else 262 #define NK_API extern 263 #endif 264 #endif 265 #ifndef NK_LIB 266 #ifdef NK_SINGLE_FILE 267 #define NK_LIB static 268 #else 269 #define NK_LIB extern 270 #endif 271 #endif 272 273 #define NK_INTERN static 274 #define NK_STORAGE static 275 #define NK_GLOBAL static 276 277 #define NK_FLAG(x) (1 << (x)) 278 #define NK_STRINGIFY(x) #x 279 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x) 280 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 281 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2) 282 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2) 283 284 #ifdef _MSC_VER 285 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__) 286 #else 287 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__) 288 #endif 289 290 #ifndef NK_STATIC_ASSERT 291 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1] 292 #endif 293 294 #ifndef NK_FILE_LINE 295 #ifdef _MSC_VER 296 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__) 297 #else 298 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__) 299 #endif 300 #endif 301 302 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b)) 303 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a)) 304 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i)) 305 306 #ifdef NK_INCLUDE_STANDARD_VARARGS 307 #include <stdarg.h> /* valist, va_start, va_end, ... */ 308 #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ 309 #include <sal.h> 310 #define NK_PRINTF_FORMAT_STRING _Printf_format_string_ 311 #else 312 #define NK_PRINTF_FORMAT_STRING 313 #endif 314 #if defined(__GNUC__) 315 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1))) 316 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0))) 317 #else 318 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) 319 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) 320 #endif 321 #endif 322 323 /* 324 * =============================================================== 325 * 326 * BASIC 327 * 328 * =============================================================== 329 */ 330 #ifdef NK_INCLUDE_FIXED_TYPES 331 #include <stdint.h> 332 #define NK_INT8 int8_t 333 #define NK_UINT8 uint8_t 334 #define NK_INT16 int16_t 335 #define NK_UINT16 uint16_t 336 #define NK_INT32 int32_t 337 #define NK_UINT32 uint32_t 338 #define NK_SIZE_TYPE uintptr_t 339 #define NK_POINTER_TYPE uintptr_t 340 #else 341 #ifndef NK_INT8 342 #define NK_INT8 signed char 343 #endif 344 #ifndef NK_UINT8 345 #define NK_UINT8 unsigned char 346 #endif 347 #ifndef NK_INT16 348 #define NK_INT16 signed short 349 #endif 350 #ifndef NK_UINT16 351 #define NK_UINT16 unsigned short 352 #endif 353 #ifndef NK_INT32 354 #if defined(_MSC_VER) 355 #define NK_INT32 __int32 356 #else 357 #define NK_INT32 signed int 358 #endif 359 #endif 360 #ifndef NK_UINT32 361 #if defined(_MSC_VER) 362 #define NK_UINT32 unsigned __int32 363 #else 364 #define NK_UINT32 unsigned int 365 #endif 366 #endif 367 #ifndef NK_SIZE_TYPE 368 #if defined(_WIN64) && defined(_MSC_VER) 369 #define NK_SIZE_TYPE unsigned __int64 370 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 371 #define NK_SIZE_TYPE unsigned __int32 372 #elif defined(__GNUC__) || defined(__clang__) 373 #if defined(__x86_64__) || defined(__ppc64__) 374 #define NK_SIZE_TYPE unsigned long 375 #else 376 #define NK_SIZE_TYPE unsigned int 377 #endif 378 #else 379 #define NK_SIZE_TYPE unsigned long 380 #endif 381 #endif 382 #ifndef NK_POINTER_TYPE 383 #if defined(_WIN64) && defined(_MSC_VER) 384 #define NK_POINTER_TYPE unsigned __int64 385 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 386 #define NK_POINTER_TYPE unsigned __int32 387 #elif defined(__GNUC__) || defined(__clang__) 388 #if defined(__x86_64__) || defined(__ppc64__) 389 #define NK_POINTER_TYPE unsigned long 390 #else 391 #define NK_POINTER_TYPE unsigned int 392 #endif 393 #else 394 #define NK_POINTER_TYPE unsigned long 395 #endif 396 #endif 397 #endif 398 399 typedef NK_INT8 nk_char; 400 typedef NK_UINT8 nk_uchar; 401 typedef NK_UINT8 nk_byte; 402 typedef NK_INT16 nk_short; 403 typedef NK_UINT16 nk_ushort; 404 typedef NK_INT32 nk_int; 405 typedef NK_UINT32 nk_uint; 406 typedef NK_SIZE_TYPE nk_size; 407 typedef NK_POINTER_TYPE nk_ptr; 408 409 typedef nk_uint nk_hash; 410 typedef nk_uint nk_flags; 411 typedef nk_uint nk_rune; 412 413 /* Make sure correct type size: 414 * This will fire with a negative subscript error if the type sizes 415 * are set incorrectly by the compiler, and compile out if not */ 416 NK_STATIC_ASSERT(sizeof(nk_short) == 2); 417 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 418 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 419 NK_STATIC_ASSERT(sizeof(nk_int) == 4); 420 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 421 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 422 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 423 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 424 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); 425 426 /* ============================================================================ 427 * 428 * API 429 * 430 * =========================================================================== */ 431 struct nk_buffer; 432 struct nk_allocator; 433 struct nk_command_buffer; 434 struct nk_draw_command; 435 struct nk_convert_config; 436 struct nk_style_item; 437 struct nk_text_edit; 438 struct nk_draw_list; 439 struct nk_user_font; 440 struct nk_panel; 441 struct nk_context; 442 struct nk_draw_vertex_layout_element; 443 struct nk_style_button; 444 struct nk_style_toggle; 445 struct nk_style_selectable; 446 struct nk_style_slide; 447 struct nk_style_progress; 448 struct nk_style_scrollbar; 449 struct nk_style_edit; 450 struct nk_style_property; 451 struct nk_style_chart; 452 struct nk_style_combo; 453 struct nk_style_tab; 454 struct nk_style_window_header; 455 struct nk_style_window; 456 457 enum {nk_false, nk_true}; 458 struct nk_color {nk_byte r,g,b,a;}; 459 struct nk_colorf {float r,g,b,a;}; 460 struct nk_vec2 {float x,y;}; 461 struct nk_vec2i {short x, y;}; 462 struct nk_rect {float x,y,w,h;}; 463 struct nk_recti {short x,y,w,h;}; 464 typedef char nk_glyph[NK_UTF_SIZE]; 465 typedef union {void *ptr; int id;} nk_handle; 466 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];}; 467 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;}; 468 struct nk_scroll {nk_uint x, y;}; 469 470 enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT}; 471 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER}; 472 enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true}; 473 enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL}; 474 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true}; 475 enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true}; 476 enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX}; 477 enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02}; 478 enum nk_color_format {NK_RGB, NK_RGBA}; 479 enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC}; 480 enum nk_layout_format {NK_DYNAMIC, NK_STATIC}; 481 enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB}; 482 483 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size); 484 typedef void (*nk_plugin_free)(nk_handle, void *old); 485 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode); 486 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*); 487 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len); 488 489 struct nk_allocator { 490 nk_handle userdata; 491 nk_plugin_alloc alloc; 492 nk_plugin_free free; 493 }; 494 enum nk_symbol_type { 495 NK_SYMBOL_NONE, 496 NK_SYMBOL_X, 497 NK_SYMBOL_UNDERSCORE, 498 NK_SYMBOL_CIRCLE_SOLID, 499 NK_SYMBOL_CIRCLE_OUTLINE, 500 NK_SYMBOL_RECT_SOLID, 501 NK_SYMBOL_RECT_OUTLINE, 502 NK_SYMBOL_TRIANGLE_UP, 503 NK_SYMBOL_TRIANGLE_DOWN, 504 NK_SYMBOL_TRIANGLE_LEFT, 505 NK_SYMBOL_TRIANGLE_RIGHT, 506 NK_SYMBOL_PLUS, 507 NK_SYMBOL_MINUS, 508 NK_SYMBOL_MAX 509 }; 510 /* ============================================================================= 511 * 512 * CONTEXT 513 * 514 * =============================================================================*/ 515 /*/// ### Context 516 /// Contexts are the main entry point and the majestro of nuklear and contain all required state. 517 /// They are used for window, memory, input, style, stack, commands and time management and need 518 /// to be passed into all nuklear GUI specific functions. 519 /// 520 /// #### Usage 521 /// To use a context it first has to be initialized which can be achieved by calling 522 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`. 523 /// Each takes in a font handle and a specific way of handling memory. Memory control 524 /// hereby ranges from standard library to just specifying a fixed sized block of memory 525 /// which nuklear has to manage itself from. 526 /// 527 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 528 /// struct nk_context ctx; 529 /// nk_init_xxx(&ctx, ...); 530 /// while (1) { 531 /// // [...] 532 /// nk_clear(&ctx); 533 /// } 534 /// nk_free(&ctx); 535 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 536 /// 537 /// #### Reference 538 /// Function | Description 539 /// --------------------|------------------------------------------------------- 540 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free) 541 /// __nk_init_fixed__ | Initializes context from single fixed size memory block 542 /// __nk_init__ | Initializes context with memory allocator callbacks for alloc and free 543 /// __nk_init_custom__ | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations 544 /// __nk_clear__ | Called at the end of the frame to reset and prepare the context for the next frame 545 /// __nk_free__ | Shutdown and free all memory allocated inside the context 546 /// __nk_set_user_data__| Utility function to pass user data to draw command 547 */ 548 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 549 /*/// #### nk_init_default 550 /// Initializes a `nk_context` struct with a default standard library allocator. 551 /// Should be used if you don't want to be bothered with memory management in nuklear. 552 /// 553 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 554 /// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font); 555 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 556 /// 557 /// Parameter | Description 558 /// ------------|--------------------------------------------------------------- 559 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 560 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 561 /// 562 /// Returns either `false(0)` on failure or `true(1)` on success. 563 /// 564 */ 565 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*); 566 #endif 567 /*/// #### nk_init_fixed 568 /// Initializes a `nk_context` struct from single fixed size memory block 569 /// Should be used if you want complete control over nuklear's memory management. 570 /// Especially recommended for system with little memory or systems with virtual memory. 571 /// For the later case you can just allocate for example 16MB of virtual memory 572 /// and only the required amount of memory will actually be committed. 573 /// 574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 575 /// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font); 576 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 577 /// 578 /// !!! Warning 579 /// make sure the passed memory block is aligned correctly for `nk_draw_commands`. 580 /// 581 /// Parameter | Description 582 /// ------------|-------------------------------------------------------------- 583 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 584 /// __memory__ | Must point to a previously allocated memory block 585 /// __size__ | Must contain the total size of __memory__ 586 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 587 /// 588 /// Returns either `false(0)` on failure or `true(1)` on success. 589 */ 590 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*); 591 /*/// #### nk_init 592 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate 593 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation 594 /// interface to nuklear. Can be useful for cases like monitoring memory consumption. 595 /// 596 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 597 /// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font); 598 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 599 /// 600 /// Parameter | Description 601 /// ------------|--------------------------------------------------------------- 602 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 603 /// __alloc__ | Must point to a previously allocated memory allocator 604 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 605 /// 606 /// Returns either `false(0)` on failure or `true(1)` on success. 607 */ 608 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*); 609 /*/// #### nk_init_custom 610 /// Initializes a `nk_context` struct from two different either fixed or growing 611 /// buffers. The first buffer is for allocating draw commands while the second buffer is 612 /// used for allocating windows, panels and state tables. 613 /// 614 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 615 /// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font); 616 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 617 /// 618 /// Parameter | Description 619 /// ------------|--------------------------------------------------------------- 620 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 621 /// __cmds__ | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into 622 /// __pool__ | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables 623 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 624 /// 625 /// Returns either `false(0)` on failure or `true(1)` on success. 626 */ 627 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*); 628 /*/// #### nk_clear 629 /// Resets the context state at the end of the frame. This includes mostly 630 /// garbage collector tasks like removing windows or table not called and therefore 631 /// used anymore. 632 /// 633 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 634 /// void nk_clear(struct nk_context *ctx); 635 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 636 /// 637 /// Parameter | Description 638 /// ------------|----------------------------------------------------------- 639 /// __ctx__ | Must point to a previously initialized `nk_context` struct 640 */ 641 NK_API void nk_clear(struct nk_context*); 642 /*/// #### nk_free 643 /// Frees all memory allocated by nuklear. Not needed if context was 644 /// initialized with `nk_init_fixed`. 645 /// 646 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 647 /// void nk_free(struct nk_context *ctx); 648 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 649 /// 650 /// Parameter | Description 651 /// ------------|----------------------------------------------------------- 652 /// __ctx__ | Must point to a previously initialized `nk_context` struct 653 */ 654 NK_API void nk_free(struct nk_context*); 655 #ifdef NK_INCLUDE_COMMAND_USERDATA 656 /*/// #### nk_set_user_data 657 /// Sets the currently passed userdata passed down into each draw command. 658 /// 659 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 660 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data); 661 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 662 /// 663 /// Parameter | Description 664 /// ------------|-------------------------------------------------------------- 665 /// __ctx__ | Must point to a previously initialized `nk_context` struct 666 /// __data__ | Handle with either pointer or index to be passed into every draw commands 667 */ 668 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle); 669 #endif 670 /* ============================================================================= 671 * 672 * INPUT 673 * 674 * =============================================================================*/ 675 /*/// ### Input 676 /// The input API is responsible for holding the current input state composed of 677 /// mouse, key and text input states. 678 /// It is worth noting that no direct OS or window handling is done in nuklear. 679 /// Instead all input state has to be provided by platform specific code. This on one hand 680 /// expects more work from the user and complicates usage but on the other hand 681 /// provides simple abstraction over a big number of platforms, libraries and other 682 /// already provided functionality. 683 /// 684 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 685 /// nk_input_begin(&ctx); 686 /// while (GetEvent(&evt)) { 687 /// if (evt.type == MOUSE_MOVE) 688 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 689 /// else if (evt.type == [...]) { 690 /// // [...] 691 /// } 692 /// } nk_input_end(&ctx); 693 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 694 /// 695 /// #### Usage 696 /// Input state needs to be provided to nuklear by first calling `nk_input_begin` 697 /// which resets internal state like delta mouse position and button transistions. 698 /// After `nk_input_begin` all current input state needs to be provided. This includes 699 /// mouse motion, button and key pressed and released, text input and scrolling. 700 /// Both event- or state-based input handling are supported by this API 701 /// and should work without problems. Finally after all input state has been 702 /// mirrored `nk_input_end` needs to be called to finish input process. 703 /// 704 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 705 /// struct nk_context ctx; 706 /// nk_init_xxx(&ctx, ...); 707 /// while (1) { 708 /// Event evt; 709 /// nk_input_begin(&ctx); 710 /// while (GetEvent(&evt)) { 711 /// if (evt.type == MOUSE_MOVE) 712 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 713 /// else if (evt.type == [...]) { 714 /// // [...] 715 /// } 716 /// } 717 /// nk_input_end(&ctx); 718 /// // [...] 719 /// nk_clear(&ctx); 720 /// } nk_free(&ctx); 721 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 722 /// 723 /// #### Reference 724 /// Function | Description 725 /// --------------------|------------------------------------------------------- 726 /// __nk_input_begin__ | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls 727 /// __nk_input_motion__ | Mirrors mouse cursor position 728 /// __nk_input_key__ | Mirrors key state with either pressed or released 729 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released 730 /// __nk_input_scroll__ | Mirrors mouse scroll values 731 /// __nk_input_char__ | Adds a single ASCII text character into an internal text buffer 732 /// __nk_input_glyph__ | Adds a single multi-byte UTF-8 character into an internal text buffer 733 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer 734 /// __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 735 */ 736 enum nk_keys { 737 NK_KEY_NONE, 738 NK_KEY_SHIFT, 739 NK_KEY_CTRL, 740 NK_KEY_DEL, 741 NK_KEY_ENTER, 742 NK_KEY_TAB, 743 NK_KEY_BACKSPACE, 744 NK_KEY_COPY, 745 NK_KEY_CUT, 746 NK_KEY_PASTE, 747 NK_KEY_UP, 748 NK_KEY_DOWN, 749 NK_KEY_LEFT, 750 NK_KEY_RIGHT, 751 /* Shortcuts: text field */ 752 NK_KEY_TEXT_INSERT_MODE, 753 NK_KEY_TEXT_REPLACE_MODE, 754 NK_KEY_TEXT_RESET_MODE, 755 NK_KEY_TEXT_LINE_START, 756 NK_KEY_TEXT_LINE_END, 757 NK_KEY_TEXT_START, 758 NK_KEY_TEXT_END, 759 NK_KEY_TEXT_UNDO, 760 NK_KEY_TEXT_REDO, 761 NK_KEY_TEXT_SELECT_ALL, 762 NK_KEY_TEXT_WORD_LEFT, 763 NK_KEY_TEXT_WORD_RIGHT, 764 /* Shortcuts: scrollbar */ 765 NK_KEY_SCROLL_START, 766 NK_KEY_SCROLL_END, 767 NK_KEY_SCROLL_DOWN, 768 NK_KEY_SCROLL_UP, 769 NK_KEY_MAX 770 }; 771 enum nk_buttons { 772 NK_BUTTON_LEFT, 773 NK_BUTTON_MIDDLE, 774 NK_BUTTON_RIGHT, 775 NK_BUTTON_DOUBLE, 776 NK_BUTTON_MAX 777 }; 778 /*/// #### nk_input_begin 779 /// Begins the input mirroring process by resetting text, scroll 780 /// mouse, previous mouse position and movement as well as key state transitions, 781 /// 782 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 783 /// void nk_input_begin(struct nk_context*); 784 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 785 /// 786 /// Parameter | Description 787 /// ------------|----------------------------------------------------------- 788 /// __ctx__ | Must point to a previously initialized `nk_context` struct 789 */ 790 NK_API void nk_input_begin(struct nk_context*); 791 /*/// #### nk_input_motion 792 /// Mirrors current mouse position to nuklear 793 /// 794 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 795 /// void nk_input_motion(struct nk_context *ctx, int x, int y); 796 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 797 /// 798 /// Parameter | Description 799 /// ------------|----------------------------------------------------------- 800 /// __ctx__ | Must point to a previously initialized `nk_context` struct 801 /// __x__ | Must hold an integer describing the current mouse cursor x-position 802 /// __y__ | Must hold an integer describing the current mouse cursor y-position 803 */ 804 NK_API void nk_input_motion(struct nk_context*, int x, int y); 805 /*/// #### nk_input_key 806 /// Mirrors the state of a specific key to nuklear 807 /// 808 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 809 /// void nk_input_key(struct nk_context*, enum nk_keys key, int down); 810 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 811 /// 812 /// Parameter | Description 813 /// ------------|----------------------------------------------------------- 814 /// __ctx__ | Must point to a previously initialized `nk_context` struct 815 /// __key__ | Must be any value specified in enum `nk_keys` that needs to be mirrored 816 /// __down__ | Must be 0 for key is up and 1 for key is down 817 */ 818 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down); 819 /*/// #### nk_input_button 820 /// Mirrors the state of a specific mouse button to nuklear 821 /// 822 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 823 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, int down); 824 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 825 /// 826 /// Parameter | Description 827 /// ------------|----------------------------------------------------------- 828 /// __ctx__ | Must point to a previously initialized `nk_context` struct 829 /// __btn__ | Must be any value specified in enum `nk_buttons` that needs to be mirrored 830 /// __x__ | Must contain an integer describing mouse cursor x-position on click up/down 831 /// __y__ | Must contain an integer describing mouse cursor y-position on click up/down 832 /// __down__ | Must be 0 for key is up and 1 for key is down 833 */ 834 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down); 835 /*/// #### nk_input_scroll 836 /// Copies the last mouse scroll value to nuklear. Is generally 837 /// a scroll value. So does not have to come from mouse and could also originate 838 /// TODO finish this sentence 839 /// 840 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 841 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val); 842 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 843 /// 844 /// Parameter | Description 845 /// ------------|----------------------------------------------------------- 846 /// __ctx__ | Must point to a previously initialized `nk_context` struct 847 /// __val__ | vector with both X- as well as Y-scroll value 848 */ 849 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val); 850 /*/// #### nk_input_char 851 /// Copies a single ASCII character into an internal text buffer 852 /// This is basically a helper function to quickly push ASCII characters into 853 /// nuklear. 854 /// 855 /// !!! Note 856 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 857 /// 858 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 859 /// void nk_input_char(struct nk_context *ctx, char c); 860 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 861 /// 862 /// Parameter | Description 863 /// ------------|----------------------------------------------------------- 864 /// __ctx__ | Must point to a previously initialized `nk_context` struct 865 /// __c__ | Must be a single ASCII character preferable one that can be printed 866 */ 867 NK_API void nk_input_char(struct nk_context*, char); 868 /*/// #### nk_input_glyph 869 /// Converts an encoded unicode rune into UTF-8 and copies the result into an 870 /// internal text buffer. 871 /// 872 /// !!! Note 873 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 874 /// 875 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 876 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g); 877 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 878 /// 879 /// Parameter | Description 880 /// ------------|----------------------------------------------------------- 881 /// __ctx__ | Must point to a previously initialized `nk_context` struct 882 /// __g__ | UTF-32 unicode codepoint 883 */ 884 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph); 885 /*/// #### nk_input_unicode 886 /// Converts a unicode rune into UTF-8 and copies the result 887 /// into an internal text buffer. 888 /// !!! Note 889 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 890 /// 891 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 892 /// void nk_input_unicode(struct nk_context*, nk_rune rune); 893 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 894 /// 895 /// Parameter | Description 896 /// ------------|----------------------------------------------------------- 897 /// __ctx__ | Must point to a previously initialized `nk_context` struct 898 /// __rune__ | UTF-32 unicode codepoint 899 */ 900 NK_API void nk_input_unicode(struct nk_context*, nk_rune); 901 /*/// #### nk_input_end 902 /// End the input mirroring process by resetting mouse grabbing 903 /// state to ensure the mouse cursor is not grabbed indefinitely. 904 /// 905 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 906 /// void nk_input_end(struct nk_context *ctx); 907 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 908 /// 909 /// Parameter | Description 910 /// ------------|----------------------------------------------------------- 911 /// __ctx__ | Must point to a previously initialized `nk_context` struct 912 */ 913 NK_API void nk_input_end(struct nk_context*); 914 /* ============================================================================= 915 * 916 * DRAWING 917 * 918 * =============================================================================*/ 919 /*/// ### Drawing 920 /// This library was designed to be render backend agnostic so it does 921 /// not draw anything to screen directly. Instead all drawn shapes, widgets 922 /// are made of, are buffered into memory and make up a command queue. 923 /// Each frame therefore fills the command buffer with draw commands 924 /// that then need to be executed by the user and his own render backend. 925 /// After that the command buffer needs to be cleared and a new frame can be 926 /// started. It is probably important to note that the command buffer is the main 927 /// drawing API and the optional vertex buffer API only takes this format and 928 /// converts it into a hardware accessible format. 929 /// 930 /// #### Usage 931 /// To draw all draw commands accumulated over a frame you need your own render 932 /// backend able to draw a number of 2D primitives. This includes at least 933 /// filled and stroked rectangles, circles, text, lines, triangles and scissors. 934 /// As soon as this criterion is met you can iterate over each draw command 935 /// and execute each draw command in a interpreter like fashion: 936 /// 937 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 938 /// const struct nk_command *cmd = 0; 939 /// nk_foreach(cmd, &ctx) { 940 /// switch (cmd->type) { 941 /// case NK_COMMAND_LINE: 942 /// your_draw_line_function(...) 943 /// break; 944 /// case NK_COMMAND_RECT 945 /// your_draw_rect_function(...) 946 /// break; 947 /// case //...: 948 /// //[...] 949 /// } 950 /// } 951 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 952 /// 953 /// In program flow context draw commands need to be executed after input has been 954 /// gathered and the complete UI with windows and their contained widgets have 955 /// been executed and before calling `nk_clear` which frees all previously 956 /// allocated draw commands. 957 /// 958 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 959 /// struct nk_context ctx; 960 /// nk_init_xxx(&ctx, ...); 961 /// while (1) { 962 /// Event evt; 963 /// nk_input_begin(&ctx); 964 /// while (GetEvent(&evt)) { 965 /// if (evt.type == MOUSE_MOVE) 966 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 967 /// else if (evt.type == [...]) { 968 /// [...] 969 /// } 970 /// } 971 /// nk_input_end(&ctx); 972 /// // 973 /// // [...] 974 /// // 975 /// const struct nk_command *cmd = 0; 976 /// nk_foreach(cmd, &ctx) { 977 /// switch (cmd->type) { 978 /// case NK_COMMAND_LINE: 979 /// your_draw_line_function(...) 980 /// break; 981 /// case NK_COMMAND_RECT 982 /// your_draw_rect_function(...) 983 /// break; 984 /// case ...: 985 /// // [...] 986 /// } 987 /// nk_clear(&ctx); 988 /// } 989 /// nk_free(&ctx); 990 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 991 /// 992 /// You probably noticed that you have to draw all of the UI each frame which is 993 /// quite wasteful. While the actual UI updating loop is quite fast rendering 994 /// without actually needing it is not. So there are multiple things you could do. 995 /// 996 /// First is only update on input. This of course is only an option if your 997 /// application only depends on the UI and does not require any outside calculations. 998 /// If you actually only update on input make sure to update the UI two times each 999 /// frame and call `nk_clear` directly after the first pass and only draw in 1000 /// the second pass. In addition it is recommended to also add additional timers 1001 /// to make sure the UI is not drawn more than a fixed number of frames per second. 1002 /// 1003 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1004 /// struct nk_context ctx; 1005 /// nk_init_xxx(&ctx, ...); 1006 /// while (1) { 1007 /// // [...wait for input ] 1008 /// // [...do two UI passes ...] 1009 /// do_ui(...) 1010 /// nk_clear(&ctx); 1011 /// do_ui(...) 1012 /// // 1013 /// // draw 1014 /// const struct nk_command *cmd = 0; 1015 /// nk_foreach(cmd, &ctx) { 1016 /// switch (cmd->type) { 1017 /// case NK_COMMAND_LINE: 1018 /// your_draw_line_function(...) 1019 /// break; 1020 /// case NK_COMMAND_RECT 1021 /// your_draw_rect_function(...) 1022 /// break; 1023 /// case ...: 1024 /// //[...] 1025 /// } 1026 /// nk_clear(&ctx); 1027 /// } 1028 /// nk_free(&ctx); 1029 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1030 /// 1031 /// The second probably more applicable trick is to only draw if anything changed. 1032 /// It is not really useful for applications with continuous draw loop but 1033 /// quite useful for desktop applications. To actually get nuklear to only 1034 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and 1035 /// allocate a memory buffer that will store each unique drawing output. 1036 /// After each frame you compare the draw command memory inside the library 1037 /// with your allocated buffer by memcmp. If memcmp detects differences 1038 /// you have to copy the command buffer into the allocated buffer 1039 /// and then draw like usual (this example uses fixed memory but you could 1040 /// use dynamically allocated memory). 1041 /// 1042 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1043 /// //[... other defines ...] 1044 /// #define NK_ZERO_COMMAND_MEMORY 1045 /// #include "nuklear.h" 1046 /// // 1047 /// // setup context 1048 /// struct nk_context ctx; 1049 /// void *last = calloc(1,64*1024); 1050 /// void *buf = calloc(1,64*1024); 1051 /// nk_init_fixed(&ctx, buf, 64*1024); 1052 /// // 1053 /// // loop 1054 /// while (1) { 1055 /// // [...input...] 1056 /// // [...ui...] 1057 /// void *cmds = nk_buffer_memory(&ctx.memory); 1058 /// if (memcmp(cmds, last, ctx.memory.allocated)) { 1059 /// memcpy(last,cmds,ctx.memory.allocated); 1060 /// const struct nk_command *cmd = 0; 1061 /// nk_foreach(cmd, &ctx) { 1062 /// switch (cmd->type) { 1063 /// case NK_COMMAND_LINE: 1064 /// your_draw_line_function(...) 1065 /// break; 1066 /// case NK_COMMAND_RECT 1067 /// your_draw_rect_function(...) 1068 /// break; 1069 /// case ...: 1070 /// // [...] 1071 /// } 1072 /// } 1073 /// } 1074 /// nk_clear(&ctx); 1075 /// } 1076 /// nk_free(&ctx); 1077 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1078 /// 1079 /// Finally while using draw commands makes sense for higher abstracted platforms like 1080 /// X11 and Win32 or drawing libraries it is often desirable to use graphics 1081 /// hardware directly. Therefore it is possible to just define 1082 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output. 1083 /// To access the vertex output you first have to convert all draw commands into 1084 /// vertexes by calling `nk_convert` which takes in your preferred vertex format. 1085 /// After successfully converting all draw commands just iterate over and execute all 1086 /// vertex draw commands: 1087 /// 1088 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1089 /// // fill configuration 1090 /// struct your_vertex 1091 /// { 1092 /// float pos[2]; // important to keep it to 2 floats 1093 /// float uv[2]; 1094 /// unsigned char col[4]; 1095 /// }; 1096 /// struct nk_convert_config cfg = {}; 1097 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = { 1098 /// {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)}, 1099 /// {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)}, 1100 /// {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)}, 1101 /// {NK_VERTEX_LAYOUT_END} 1102 /// }; 1103 /// cfg.shape_AA = NK_ANTI_ALIASING_ON; 1104 /// cfg.line_AA = NK_ANTI_ALIASING_ON; 1105 /// cfg.vertex_layout = vertex_layout; 1106 /// cfg.vertex_size = sizeof(struct your_vertex); 1107 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex); 1108 /// cfg.circle_segment_count = 22; 1109 /// cfg.curve_segment_count = 22; 1110 /// cfg.arc_segment_count = 22; 1111 /// cfg.global_alpha = 1.0f; 1112 /// cfg.null = dev->null; 1113 /// // 1114 /// // setup buffers and convert 1115 /// struct nk_buffer cmds, verts, idx; 1116 /// nk_buffer_init_default(&cmds); 1117 /// nk_buffer_init_default(&verts); 1118 /// nk_buffer_init_default(&idx); 1119 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg); 1120 /// // 1121 /// // draw 1122 /// nk_draw_foreach(cmd, &ctx, &cmds) { 1123 /// if (!cmd->elem_count) continue; 1124 /// //[...] 1125 /// } 1126 /// nk_buffer_free(&cms); 1127 /// nk_buffer_free(&verts); 1128 /// nk_buffer_free(&idx); 1129 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1130 /// 1131 /// #### Reference 1132 /// Function | Description 1133 /// --------------------|------------------------------------------------------- 1134 /// __nk__begin__ | Returns the first draw command in the context draw command list to be drawn 1135 /// __nk__next__ | Increments the draw command iterator to the next command inside the context draw command list 1136 /// __nk_foreach__ | Iterates over each draw command inside the context draw command list 1137 /// __nk_convert__ | Converts from the abstract draw commands list into a hardware accessible vertex format 1138 /// __nk_draw_begin__ | Returns the first vertex command in the context vertex draw list to be executed 1139 /// __nk__draw_next__ | Increments the vertex command iterator to the next command inside the context vertex command list 1140 /// __nk__draw_end__ | Returns the end of the vertex draw list 1141 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list 1142 */ 1143 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON}; 1144 enum nk_convert_result { 1145 NK_CONVERT_SUCCESS = 0, 1146 NK_CONVERT_INVALID_PARAM = 1, 1147 NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1), 1148 NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2), 1149 NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3) 1150 }; 1151 struct nk_draw_null_texture { 1152 nk_handle texture; /* texture handle to a texture with a white pixel */ 1153 struct nk_vec2 uv; /* coordinates to a white pixel in the texture */ 1154 }; 1155 struct nk_convert_config { 1156 float global_alpha; /* global alpha value */ 1157 enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */ 1158 enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */ 1159 unsigned circle_segment_count; /* number of segments used for circles: default to 22 */ 1160 unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */ 1161 unsigned curve_segment_count; /* number of segments used for curves: default to 22 */ 1162 struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */ 1163 const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ 1164 nk_size vertex_size; /* sizeof one vertex for vertex packing */ 1165 nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */ 1166 }; 1167 /*/// #### nk__begin 1168 /// Returns a draw command list iterator to iterate all draw 1169 /// commands accumulated over one frame. 1170 /// 1171 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1172 /// const struct nk_command* nk__begin(struct nk_context*); 1173 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1174 /// 1175 /// Parameter | Description 1176 /// ------------|----------------------------------------------------------- 1177 /// __ctx__ | must point to an previously initialized `nk_context` struct at the end of a frame 1178 /// 1179 /// Returns draw command pointer pointing to the first command inside the draw command list 1180 */ 1181 NK_API const struct nk_command* nk__begin(struct nk_context*); 1182 /*/// #### nk__next 1183 /// Returns draw command pointer pointing to the next command inside the draw command list 1184 /// 1185 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1186 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1187 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1188 /// 1189 /// Parameter | Description 1190 /// ------------|----------------------------------------------------------- 1191 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1192 /// __cmd__ | Must point to an previously a draw command either returned by `nk__begin` or `nk__next` 1193 /// 1194 /// Returns draw command pointer pointing to the next command inside the draw command list 1195 */ 1196 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1197 /*/// #### nk_foreach 1198 /// Iterates over each draw command inside the context draw command list 1199 /// 1200 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1201 /// #define nk_foreach(c, ctx) 1202 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1203 /// 1204 /// Parameter | Description 1205 /// ------------|----------------------------------------------------------- 1206 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1207 /// __cmd__ | Command pointer initialized to NULL 1208 /// 1209 /// Iterates over each draw command inside the context draw command list 1210 */ 1211 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c)) 1212 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 1213 /*/// #### nk_convert 1214 /// Converts all internal draw commands into vertex draw commands and fills 1215 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format 1216 /// as well as some other configuration values have to be configured by filling out a 1217 /// `nk_convert_config` struct. 1218 /// 1219 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1220 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 1221 /// struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); 1222 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1223 /// 1224 /// Parameter | Description 1225 /// ------------|----------------------------------------------------------- 1226 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1227 /// __cmds__ | Must point to a previously initialized buffer to hold converted vertex draw commands 1228 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices 1229 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices 1230 /// __config__ | Must point to a filled out `nk_config` struct to configure the conversion process 1231 /// 1232 /// Returns one of enum nk_convert_result error codes 1233 /// 1234 /// Parameter | Description 1235 /// --------------------------------|----------------------------------------------------------- 1236 /// NK_CONVERT_SUCCESS | Signals a successful draw command to vertex buffer conversion 1237 /// NK_CONVERT_INVALID_PARAM | An invalid argument was passed in the function call 1238 /// NK_CONVERT_COMMAND_BUFFER_FULL | The provided buffer for storing draw commands is full or failed to allocate more memory 1239 /// NK_CONVERT_VERTEX_BUFFER_FULL | The provided buffer for storing vertices is full or failed to allocate more memory 1240 /// NK_CONVERT_ELEMENT_BUFFER_FULL | The provided buffer for storing indicies is full or failed to allocate more memory 1241 */ 1242 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*); 1243 /*/// #### nk__draw_begin 1244 /// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer 1245 /// 1246 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1247 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1248 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1249 /// 1250 /// Parameter | Description 1251 /// ------------|----------------------------------------------------------- 1252 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1253 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1254 /// 1255 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer 1256 */ 1257 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1258 /*/// #### nk__draw_end 1259 /// Returns the vertex draw command at the end of the vertex draw command buffer 1260 /// 1261 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1262 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf); 1263 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1264 /// 1265 /// Parameter | Description 1266 /// ------------|----------------------------------------------------------- 1267 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1268 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1269 /// 1270 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1271 */ 1272 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*); 1273 /*/// #### nk__draw_next 1274 /// Increments the vertex draw command buffer iterator 1275 /// 1276 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1277 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1278 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1279 /// 1280 /// Parameter | Description 1281 /// ------------|----------------------------------------------------------- 1282 /// __cmd__ | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command 1283 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1284 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1285 /// 1286 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1287 */ 1288 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1289 /*/// #### nk_draw_foreach 1290 /// Iterates over each vertex draw command inside a vertex draw command buffer 1291 /// 1292 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1293 /// #define nk_draw_foreach(cmd,ctx, b) 1294 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1295 /// 1296 /// Parameter | Description 1297 /// ------------|----------------------------------------------------------- 1298 /// __cmd__ | `nk_draw_command`iterator set to NULL 1299 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1300 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1301 */ 1302 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) 1303 #endif 1304 /* ============================================================================= 1305 * 1306 * WINDOW 1307 * 1308 * ============================================================================= 1309 /// ### Window 1310 /// Windows are the main persistent state used inside nuklear and are life time 1311 /// controlled by simply "retouching" (i.e. calling) each window each frame. 1312 /// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx` 1313 /// and `nk_end`. Calling any widgets outside these two functions will result in an 1314 /// assert in debug or no state change in release mode.<br /><br /> 1315 /// 1316 /// Each window holds frame persistent state like position, size, flags, state tables, 1317 /// and some garbage collected internal persistent widget state. Each window 1318 /// is linked into a window stack list which determines the drawing and overlapping 1319 /// order. The topmost window thereby is the currently active window.<br /><br /> 1320 /// 1321 /// To change window position inside the stack occurs either automatically by 1322 /// user input by being clicked on or programmatically by calling `nk_window_focus`. 1323 /// Windows by default are visible unless explicitly being defined with flag 1324 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag 1325 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling 1326 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br /> 1327 /// 1328 /// #### Usage 1329 /// To create and keep a window you have to call one of the two `nk_begin_xxx` 1330 /// functions to start window declarations and `nk_end` at the end. Furthermore it 1331 /// is recommended to check the return value of `nk_begin_xxx` and only process 1332 /// widgets inside the window if the value is not 0. Either way you have to call 1333 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to 1334 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not 1335 /// in a segmentation fault. 1336 /// 1337 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1338 /// if (nk_begin_xxx(...) { 1339 /// // [... widgets ...] 1340 /// } 1341 /// nk_end(ctx); 1342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1343 /// 1344 /// In the grand concept window and widget declarations need to occur after input 1345 /// handling and before drawing to screen. Not doing so can result in higher 1346 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear` 1347 /// is called at the end of the frame. While nuklear's default platform backends 1348 /// already call `nk_clear` for you if you write your own backend not calling 1349 /// `nk_clear` can cause asserts or even worse undefined behavior. 1350 /// 1351 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1352 /// struct nk_context ctx; 1353 /// nk_init_xxx(&ctx, ...); 1354 /// while (1) { 1355 /// Event evt; 1356 /// nk_input_begin(&ctx); 1357 /// while (GetEvent(&evt)) { 1358 /// if (evt.type == MOUSE_MOVE) 1359 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 1360 /// else if (evt.type == [...]) { 1361 /// nk_input_xxx(...); 1362 /// } 1363 /// } 1364 /// nk_input_end(&ctx); 1365 /// 1366 /// if (nk_begin_xxx(...) { 1367 /// //[...] 1368 /// } 1369 /// nk_end(ctx); 1370 /// 1371 /// const struct nk_command *cmd = 0; 1372 /// nk_foreach(cmd, &ctx) { 1373 /// case NK_COMMAND_LINE: 1374 /// your_draw_line_function(...) 1375 /// break; 1376 /// case NK_COMMAND_RECT 1377 /// your_draw_rect_function(...) 1378 /// break; 1379 /// case //...: 1380 /// //[...] 1381 /// } 1382 /// nk_clear(&ctx); 1383 /// } 1384 /// nk_free(&ctx); 1385 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1386 /// 1387 /// #### Reference 1388 /// Function | Description 1389 /// ------------------------------------|---------------------------------------- 1390 /// nk_begin | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed 1391 /// nk_begin_titled | Extended window start with separated title and identifier to allow multiple windows with same name but not title 1392 /// nk_end | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup 1393 // 1394 /// nk_window_find | Finds and returns the window with give name 1395 /// nk_window_get_bounds | Returns a rectangle with screen position and size of the currently processed window. 1396 /// nk_window_get_position | Returns the position of the currently processed window 1397 /// nk_window_get_size | Returns the size with width and height of the currently processed window 1398 /// nk_window_get_width | Returns the width of the currently processed window 1399 /// nk_window_get_height | Returns the height of the currently processed window 1400 /// nk_window_get_panel | Returns the underlying panel which contains all processing state of the current window 1401 /// nk_window_get_content_region | Returns the position and size of the currently visible and non-clipped space inside the currently processed window 1402 /// nk_window_get_content_region_min | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1403 /// nk_window_get_content_region_max | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1404 /// nk_window_get_content_region_size | Returns the size of the currently visible and non-clipped space inside the currently processed window 1405 /// nk_window_get_canvas | Returns the draw command buffer. Can be used to draw custom widgets 1406 /// nk_window_get_scroll | Gets the scroll offset of the current window 1407 /// nk_window_has_focus | Returns if the currently processed window is currently active 1408 /// nk_window_is_collapsed | Returns if the window with given name is currently minimized/collapsed 1409 /// nk_window_is_closed | Returns if the currently processed window was closed 1410 /// nk_window_is_hidden | Returns if the currently processed window was hidden 1411 /// nk_window_is_active | Same as nk_window_has_focus for some reason 1412 /// nk_window_is_hovered | Returns if the currently processed window is currently being hovered by mouse 1413 /// nk_window_is_any_hovered | Return if any window currently hovered 1414 /// nk_item_is_any_active | Returns if any window or widgets is currently hovered or active 1415 // 1416 /// nk_window_set_bounds | Updates position and size of the currently processed window 1417 /// nk_window_set_position | Updates position of the currently process window 1418 /// nk_window_set_size | Updates the size of the currently processed window 1419 /// nk_window_set_focus | Set the currently processed window as active window 1420 /// nk_window_set_scroll | Sets the scroll offset of the current window 1421 // 1422 /// nk_window_close | Closes the window with given window name which deletes the window at the end of the frame 1423 /// nk_window_collapse | Collapses the window with given window name 1424 /// nk_window_collapse_if | Collapses the window with given window name if the given condition was met 1425 /// nk_window_show | Hides a visible or reshows a hidden window 1426 /// nk_window_show_if | Hides/shows a window depending on condition 1427 */ 1428 /* 1429 /// #### nk_panel_flags 1430 /// Flag | Description 1431 /// ----------------------------|---------------------------------------- 1432 /// NK_WINDOW_BORDER | Draws a border around the window to visually separate window from the background 1433 /// NK_WINDOW_MOVABLE | The movable flag indicates that a window can be moved by user input or by dragging the window header 1434 /// 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 1435 /// NK_WINDOW_CLOSABLE | Adds a closable icon into the header 1436 /// NK_WINDOW_MINIMIZABLE | Adds a minimize icon into the header 1437 /// NK_WINDOW_NO_SCROLLBAR | Removes the scrollbar from the window 1438 /// NK_WINDOW_TITLE | Forces a header at the top at the window showing the title 1439 /// 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 1440 /// NK_WINDOW_BACKGROUND | Always keep window in the background 1441 /// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-bottom corner instead right-bottom 1442 /// NK_WINDOW_NO_INPUT | Prevents window of scaling, moving or getting focus 1443 /// 1444 /// #### nk_collapse_states 1445 /// State | Description 1446 /// ----------------|----------------------------------------------------------- 1447 /// __NK_MINIMIZED__| UI section is collased and not visibile until maximized 1448 /// __NK_MAXIMIZED__| UI section is extended and visibile until minimized 1449 /// <br /><br /> 1450 */ 1451 enum nk_panel_flags { 1452 NK_WINDOW_BORDER = NK_FLAG(0), 1453 NK_WINDOW_MOVABLE = NK_FLAG(1), 1454 NK_WINDOW_SCALABLE = NK_FLAG(2), 1455 NK_WINDOW_CLOSABLE = NK_FLAG(3), 1456 NK_WINDOW_MINIMIZABLE = NK_FLAG(4), 1457 NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), 1458 NK_WINDOW_TITLE = NK_FLAG(6), 1459 NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), 1460 NK_WINDOW_BACKGROUND = NK_FLAG(8), 1461 NK_WINDOW_SCALE_LEFT = NK_FLAG(9), 1462 NK_WINDOW_NO_INPUT = NK_FLAG(10) 1463 }; 1464 /*/// #### nk_begin 1465 /// Starts a new window; needs to be called every frame for every 1466 /// window (unless hidden) or otherwise the window gets removed 1467 /// 1468 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1469 /// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1470 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1471 /// 1472 /// Parameter | Description 1473 /// ------------|----------------------------------------------------------- 1474 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1475 /// __title__ | Window title and identifier. Needs to be persistent over frames to identify the window 1476 /// __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 1477 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1478 /// 1479 /// Returns `true(1)` if the window can be filled up with widgets from this point 1480 /// until `nk_end` or `false(0)` otherwise for example if minimized 1481 */ 1482 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1483 /*/// #### nk_begin_titled 1484 /// Extended window start with separated title and identifier to allow multiple 1485 /// windows with same title but not name 1486 /// 1487 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1488 /// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1489 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1490 /// 1491 /// Parameter | Description 1492 /// ------------|----------------------------------------------------------- 1493 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1494 /// __name__ | Window identifier. Needs to be persistent over frames to identify the window 1495 /// __title__ | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set 1496 /// __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 1497 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1498 /// 1499 /// Returns `true(1)` if the window can be filled up with widgets from this point 1500 /// until `nk_end` or `false(0)` otherwise for example if minimized 1501 */ 1502 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1503 /*/// #### nk_end 1504 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup. 1505 /// All widget calls after this functions will result in asserts or no state changes 1506 /// 1507 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1508 /// void nk_end(struct nk_context *ctx); 1509 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1510 /// 1511 /// Parameter | Description 1512 /// ------------|----------------------------------------------------------- 1513 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1514 */ 1515 NK_API void nk_end(struct nk_context *ctx); 1516 /*/// #### nk_window_find 1517 /// Finds and returns a window from passed name 1518 /// 1519 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1520 /// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1521 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1522 /// 1523 /// Parameter | Description 1524 /// ------------|----------------------------------------------------------- 1525 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1526 /// __name__ | Window identifier 1527 /// 1528 /// Returns a `nk_window` struct pointing to the identified window or NULL if 1529 /// no window with the given name was found 1530 */ 1531 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1532 /*/// #### nk_window_get_bounds 1533 /// Returns a rectangle with screen position and size of the currently processed window 1534 /// 1535 /// !!! WARNING 1536 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1537 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1538 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1539 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1540 /// 1541 /// Parameter | Description 1542 /// ------------|----------------------------------------------------------- 1543 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1544 /// 1545 /// Returns a `nk_rect` struct with window upper left window position and size 1546 */ 1547 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1548 /*/// #### nk_window_get_position 1549 /// Returns the position of the currently processed window. 1550 /// 1551 /// !!! WARNING 1552 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1553 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1554 /// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1555 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1556 /// 1557 /// Parameter | Description 1558 /// ------------|----------------------------------------------------------- 1559 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1560 /// 1561 /// Returns a `nk_vec2` struct with window upper left position 1562 */ 1563 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1564 /*/// #### nk_window_get_size 1565 /// Returns the size with width and height of the currently processed window. 1566 /// 1567 /// !!! WARNING 1568 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1569 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1570 /// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx); 1571 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1572 /// 1573 /// Parameter | Description 1574 /// ------------|----------------------------------------------------------- 1575 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1576 /// 1577 /// Returns a `nk_vec2` struct with window width and height 1578 */ 1579 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*); 1580 /*/// #### nk_window_get_width 1581 /// Returns the width of the currently processed window. 1582 /// 1583 /// !!! WARNING 1584 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1585 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1586 /// float nk_window_get_width(const struct nk_context *ctx); 1587 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1588 /// 1589 /// Parameter | Description 1590 /// ------------|----------------------------------------------------------- 1591 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1592 /// 1593 /// Returns the current window width 1594 */ 1595 NK_API float nk_window_get_width(const struct nk_context*); 1596 /*/// #### nk_window_get_height 1597 /// Returns the height of the currently processed window. 1598 /// 1599 /// !!! WARNING 1600 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1601 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1602 /// float nk_window_get_height(const struct nk_context *ctx); 1603 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1604 /// 1605 /// Parameter | Description 1606 /// ------------|----------------------------------------------------------- 1607 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1608 /// 1609 /// Returns the current window height 1610 */ 1611 NK_API float nk_window_get_height(const struct nk_context*); 1612 /*/// #### nk_window_get_panel 1613 /// Returns the underlying panel which contains all processing state of the current window. 1614 /// 1615 /// !!! WARNING 1616 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1617 /// !!! WARNING 1618 /// Do not keep the returned panel pointer around, it is only valid until `nk_end` 1619 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1620 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx); 1621 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1622 /// 1623 /// Parameter | Description 1624 /// ------------|----------------------------------------------------------- 1625 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1626 /// 1627 /// Returns a pointer to window internal `nk_panel` state. 1628 */ 1629 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*); 1630 /*/// #### nk_window_get_content_region 1631 /// Returns the position and size of the currently visible and non-clipped space 1632 /// inside the currently processed window. 1633 /// 1634 /// !!! WARNING 1635 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1636 /// 1637 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1638 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx); 1639 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1640 /// 1641 /// Parameter | Description 1642 /// ------------|----------------------------------------------------------- 1643 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1644 /// 1645 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset) 1646 /// of the visible space inside the current window 1647 */ 1648 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*); 1649 /*/// #### nk_window_get_content_region_min 1650 /// Returns the upper left position of the currently visible and non-clipped 1651 /// space inside the currently processed window. 1652 /// 1653 /// !!! WARNING 1654 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1655 /// 1656 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1657 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx); 1658 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1659 /// 1660 /// Parameter | Description 1661 /// ------------|----------------------------------------------------------- 1662 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1663 /// 1664 /// returns `nk_vec2` struct with upper left screen position (no scrollbar offset) 1665 /// of the visible space inside the current window 1666 */ 1667 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*); 1668 /*/// #### nk_window_get_content_region_max 1669 /// Returns the lower right screen position of the currently visible and 1670 /// non-clipped space inside the currently processed window. 1671 /// 1672 /// !!! WARNING 1673 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1674 /// 1675 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1676 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx); 1677 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1678 /// 1679 /// Parameter | Description 1680 /// ------------|----------------------------------------------------------- 1681 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1682 /// 1683 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset) 1684 /// of the visible space inside the current window 1685 */ 1686 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*); 1687 /*/// #### nk_window_get_content_region_size 1688 /// Returns the size of the currently visible and non-clipped space inside the 1689 /// currently processed window 1690 /// 1691 /// !!! WARNING 1692 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1693 /// 1694 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1695 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx); 1696 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1697 /// 1698 /// Parameter | Description 1699 /// ------------|----------------------------------------------------------- 1700 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1701 /// 1702 /// Returns `nk_vec2` struct with size the visible space inside the current window 1703 */ 1704 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); 1705 /*/// #### nk_window_get_canvas 1706 /// Returns the draw command buffer. Can be used to draw custom widgets 1707 /// !!! WARNING 1708 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1709 /// !!! WARNING 1710 /// Do not keep the returned command buffer pointer around it is only valid until `nk_end` 1711 /// 1712 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1713 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx); 1714 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1715 /// 1716 /// Parameter | Description 1717 /// ------------|----------------------------------------------------------- 1718 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1719 /// 1720 /// Returns a pointer to window internal `nk_command_buffer` struct used as 1721 /// drawing canvas. Can be used to do custom drawing. 1722 */ 1723 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); 1724 /*/// #### nk_window_get_scroll 1725 /// Gets the scroll offset for the current window 1726 /// !!! WARNING 1727 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1728 /// 1729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1730 /// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y); 1731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1732 /// 1733 /// Parameter | Description 1734 /// -------------|----------------------------------------------------------- 1735 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1736 /// __offset_x__ | A pointer to the x offset output (or NULL to ignore) 1737 /// __offset_y__ | A pointer to the y offset output (or NULL to ignore) 1738 */ 1739 NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); 1740 /*/// #### nk_window_has_focus 1741 /// Returns if the currently processed window is currently active 1742 /// !!! WARNING 1743 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1744 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1745 /// int nk_window_has_focus(const struct nk_context *ctx); 1746 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1747 /// 1748 /// Parameter | Description 1749 /// ------------|----------------------------------------------------------- 1750 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1751 /// 1752 /// Returns `false(0)` if current window is not active or `true(1)` if it is 1753 */ 1754 NK_API int nk_window_has_focus(const struct nk_context*); 1755 /*/// #### nk_window_is_hovered 1756 /// Return if the current window is being hovered 1757 /// !!! WARNING 1758 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1759 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1760 /// int nk_window_is_hovered(struct nk_context *ctx); 1761 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1762 /// 1763 /// Parameter | Description 1764 /// ------------|----------------------------------------------------------- 1765 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1766 /// 1767 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise 1768 */ 1769 NK_API int nk_window_is_hovered(struct nk_context*); 1770 /*/// #### nk_window_is_collapsed 1771 /// Returns if the window with given name is currently minimized/collapsed 1772 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1773 /// int nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1774 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1775 /// 1776 /// Parameter | Description 1777 /// ------------|----------------------------------------------------------- 1778 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1779 /// __name__ | Identifier of window you want to check if it is collapsed 1780 /// 1781 /// Returns `true(1)` if current window is minimized and `false(0)` if window not 1782 /// found or is not minimized 1783 */ 1784 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1785 /*/// #### nk_window_is_closed 1786 /// Returns if the window with given name was closed by calling `nk_close` 1787 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1788 /// int nk_window_is_closed(struct nk_context *ctx, const char *name); 1789 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1790 /// 1791 /// Parameter | Description 1792 /// ------------|----------------------------------------------------------- 1793 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1794 /// __name__ | Identifier of window you want to check if it is closed 1795 /// 1796 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed 1797 */ 1798 NK_API int nk_window_is_closed(struct nk_context*, const char*); 1799 /*/// #### nk_window_is_hidden 1800 /// Returns if the window with given name is hidden 1801 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1802 /// int nk_window_is_hidden(struct nk_context *ctx, const char *name); 1803 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1804 /// 1805 /// Parameter | Description 1806 /// ------------|----------------------------------------------------------- 1807 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1808 /// __name__ | Identifier of window you want to check if it is hidden 1809 /// 1810 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible 1811 */ 1812 NK_API int nk_window_is_hidden(struct nk_context*, const char*); 1813 /*/// #### nk_window_is_active 1814 /// Same as nk_window_has_focus for some reason 1815 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1816 /// int nk_window_is_active(struct nk_context *ctx, const char *name); 1817 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1818 /// 1819 /// Parameter | Description 1820 /// ------------|----------------------------------------------------------- 1821 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1822 /// __name__ | Identifier of window you want to check if it is active 1823 /// 1824 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active 1825 */ 1826 NK_API int nk_window_is_active(struct nk_context*, const char*); 1827 /*/// #### nk_window_is_any_hovered 1828 /// Returns if the any window is being hovered 1829 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1830 /// int nk_window_is_any_hovered(struct nk_context*); 1831 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1832 /// 1833 /// Parameter | Description 1834 /// ------------|----------------------------------------------------------- 1835 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1836 /// 1837 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise 1838 */ 1839 NK_API int nk_window_is_any_hovered(struct nk_context*); 1840 /*/// #### nk_item_is_any_active 1841 /// Returns if the any window is being hovered or any widget is currently active. 1842 /// Can be used to decide if input should be processed by UI or your specific input handling. 1843 /// Example could be UI and 3D camera to move inside a 3D space. 1844 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1845 /// int nk_item_is_any_active(struct nk_context*); 1846 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1847 /// 1848 /// Parameter | Description 1849 /// ------------|----------------------------------------------------------- 1850 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1851 /// 1852 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise 1853 */ 1854 NK_API int nk_item_is_any_active(struct nk_context*); 1855 /*/// #### nk_window_set_bounds 1856 /// Updates position and size of window with passed in name 1857 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1858 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1859 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1860 /// 1861 /// Parameter | Description 1862 /// ------------|----------------------------------------------------------- 1863 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1864 /// __name__ | Identifier of the window to modify both position and size 1865 /// __bounds__ | Must point to a `nk_rect` struct with the new position and size 1866 */ 1867 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1868 /*/// #### nk_window_set_position 1869 /// Updates position of window with passed name 1870 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1871 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1872 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1873 /// 1874 /// Parameter | Description 1875 /// ------------|----------------------------------------------------------- 1876 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1877 /// __name__ | Identifier of the window to modify both position 1878 /// __pos__ | Must point to a `nk_vec2` struct with the new position 1879 */ 1880 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1881 /*/// #### nk_window_set_size 1882 /// Updates size of window with passed in name 1883 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1884 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1885 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1886 /// 1887 /// Parameter | Description 1888 /// ------------|----------------------------------------------------------- 1889 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1890 /// __name__ | Identifier of the window to modify both window size 1891 /// __size__ | Must point to a `nk_vec2` struct with new window size 1892 */ 1893 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1894 /*/// #### nk_window_set_focus 1895 /// Sets the window with given name as active 1896 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1897 /// void nk_window_set_focus(struct nk_context*, const char *name); 1898 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1899 /// 1900 /// Parameter | Description 1901 /// ------------|----------------------------------------------------------- 1902 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1903 /// __name__ | Identifier of the window to set focus on 1904 */ 1905 NK_API void nk_window_set_focus(struct nk_context*, const char *name); 1906 /*/// #### nk_window_set_scroll 1907 /// Sets the scroll offset for the current window 1908 /// !!! WARNING 1909 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1910 /// 1911 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1912 /// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y); 1913 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1914 /// 1915 /// Parameter | Description 1916 /// -------------|----------------------------------------------------------- 1917 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1918 /// __offset_x__ | The x offset to scroll to 1919 /// __offset_y__ | The y offset to scroll to 1920 */ 1921 NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); 1922 /*/// #### nk_window_close 1923 /// Closes a window and marks it for being freed at the end of the frame 1924 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1925 /// void nk_window_close(struct nk_context *ctx, const char *name); 1926 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1927 /// 1928 /// Parameter | Description 1929 /// ------------|----------------------------------------------------------- 1930 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1931 /// __name__ | Identifier of the window to close 1932 */ 1933 NK_API void nk_window_close(struct nk_context *ctx, const char *name); 1934 /*/// #### nk_window_collapse 1935 /// Updates collapse state of a window with given name 1936 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1937 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1938 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1939 /// 1940 /// Parameter | Description 1941 /// ------------|----------------------------------------------------------- 1942 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1943 /// __name__ | Identifier of the window to close 1944 /// __state__ | value out of nk_collapse_states section 1945 */ 1946 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1947 /*/// #### nk_window_collapse_if 1948 /// Updates collapse state of a window with given name if given condition is met 1949 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1950 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1951 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1952 /// 1953 /// Parameter | Description 1954 /// ------------|----------------------------------------------------------- 1955 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1956 /// __name__ | Identifier of the window to either collapse or maximize 1957 /// __state__ | value out of nk_collapse_states section the window should be put into 1958 /// __cond__ | condition that has to be met to actually commit the collapse state change 1959 */ 1960 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1961 /*/// #### nk_window_show 1962 /// updates visibility state of a window with given name 1963 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1964 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1965 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1966 /// 1967 /// Parameter | Description 1968 /// ------------|----------------------------------------------------------- 1969 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1970 /// __name__ | Identifier of the window to either collapse or maximize 1971 /// __state__ | state with either visible or hidden to modify the window with 1972 */ 1973 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1974 /*/// #### nk_window_show_if 1975 /// Updates visibility state of a window with given name if a given condition is met 1976 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1977 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1978 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1979 /// 1980 /// Parameter | Description 1981 /// ------------|----------------------------------------------------------- 1982 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1983 /// __name__ | Identifier of the window to either hide or show 1984 /// __state__ | state with either visible or hidden to modify the window with 1985 /// __cond__ | condition that has to be met to actually commit the visbility state change 1986 */ 1987 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1988 /* ============================================================================= 1989 * 1990 * LAYOUT 1991 * 1992 * ============================================================================= 1993 /// ### Layouting 1994 /// Layouting in general describes placing widget inside a window with position and size. 1995 /// While in this particular implementation there are five different APIs for layouting 1996 /// each with different trade offs between control and ease of use. <br /><br /> 1997 /// 1998 /// All layouting methods in this library are based around the concept of a row. 1999 /// A row has a height the window content grows by and a number of columns and each 2000 /// layouting method specifies how each widget is placed inside the row. 2001 /// After a row has been allocated by calling a layouting functions and then 2002 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br /> 2003 /// 2004 /// To actually define a layout you just call the appropriate layouting function 2005 /// and each subsequent widget call will place the widget as specified. Important 2006 /// here is that if you define more widgets then columns defined inside the layout 2007 /// functions it will allocate the next row without you having to make another layouting <br /><br /> 2008 /// call. 2009 /// 2010 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API 2011 /// is that you have to define the row height for each. However the row height 2012 /// often depends on the height of the font. <br /><br /> 2013 /// 2014 /// To fix that internally nuklear uses a minimum row height that is set to the 2015 /// height plus padding of currently active font and overwrites the row height 2016 /// value if zero. <br /><br /> 2017 /// 2018 /// If you manually want to change the minimum row height then 2019 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to 2020 /// reset it back to be derived from font height. <br /><br /> 2021 /// 2022 /// Also if you change the font in nuklear it will automatically change the minimum 2023 /// row height for you and. This means if you change the font but still want 2024 /// a minimum row height smaller than the font you have to repush your value. <br /><br /> 2025 /// 2026 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx` 2027 /// layouting method in combination with a cassowary constraint solver (there are 2028 /// some versions on github with permissive license model) to take over all control over widget 2029 /// layouting yourself. However for quick and dirty layouting using all the other layouting 2030 /// functions should be fine. 2031 /// 2032 /// #### Usage 2033 /// 1. __nk_layout_row_dynamic__<br /><br /> 2034 /// The easiest layouting function is `nk_layout_row_dynamic`. It provides each 2035 /// widgets with same horizontal space inside the row and dynamically grows 2036 /// if the owning window grows in width. So the number of columns dictates 2037 /// the size of each widget dynamically by formula: 2038 /// 2039 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2040 /// widget_width = (window_width - padding - spacing) * (1/colum_count) 2041 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2042 /// 2043 /// Just like all other layouting APIs if you define more widget than columns this 2044 /// library will allocate a new row and keep all layouting parameters previously 2045 /// defined. 2046 /// 2047 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2048 /// if (nk_begin_xxx(...) { 2049 /// // first row with height: 30 composed of two widgets 2050 /// nk_layout_row_dynamic(&ctx, 30, 2); 2051 /// nk_widget(...); 2052 /// nk_widget(...); 2053 /// // 2054 /// // second row with same parameter as defined above 2055 /// nk_widget(...); 2056 /// nk_widget(...); 2057 /// // 2058 /// // third row uses 0 for height which will use auto layouting 2059 /// nk_layout_row_dynamic(&ctx, 0, 2); 2060 /// nk_widget(...); 2061 /// nk_widget(...); 2062 /// } 2063 /// nk_end(...); 2064 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2065 /// 2066 /// 2. __nk_layout_row_static__<br /><br /> 2067 /// Another easy layouting function is `nk_layout_row_static`. It provides each 2068 /// widget with same horizontal pixel width inside the row and does not grow 2069 /// if the owning window scales smaller or bigger. 2070 /// 2071 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2072 /// if (nk_begin_xxx(...) { 2073 /// // first row with height: 30 composed of two widgets with width: 80 2074 /// nk_layout_row_static(&ctx, 30, 80, 2); 2075 /// nk_widget(...); 2076 /// nk_widget(...); 2077 /// // 2078 /// // second row with same parameter as defined above 2079 /// nk_widget(...); 2080 /// nk_widget(...); 2081 /// // 2082 /// // third row uses 0 for height which will use auto layouting 2083 /// nk_layout_row_static(&ctx, 0, 80, 2); 2084 /// nk_widget(...); 2085 /// nk_widget(...); 2086 /// } 2087 /// nk_end(...); 2088 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2089 /// 2090 /// 3. __nk_layout_row_xxx__<br /><br /> 2091 /// A little bit more advanced layouting API are functions `nk_layout_row_begin`, 2092 /// `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly 2093 /// specify each column pixel or window ratio in a row. It supports either 2094 /// directly setting per column pixel width or widget window ratio but not 2095 /// both. Furthermore it is a immediate mode API so each value is directly 2096 /// pushed before calling a widget. Therefore the layout is not automatically 2097 /// repeating like the last two layouting functions. 2098 /// 2099 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2100 /// if (nk_begin_xxx(...) { 2101 /// // first row with height: 25 composed of two widgets with width 60 and 40 2102 /// nk_layout_row_begin(ctx, NK_STATIC, 25, 2); 2103 /// nk_layout_row_push(ctx, 60); 2104 /// nk_widget(...); 2105 /// nk_layout_row_push(ctx, 40); 2106 /// nk_widget(...); 2107 /// nk_layout_row_end(ctx); 2108 /// // 2109 /// // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75 2110 /// nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2); 2111 /// nk_layout_row_push(ctx, 0.25f); 2112 /// nk_widget(...); 2113 /// nk_layout_row_push(ctx, 0.75f); 2114 /// nk_widget(...); 2115 /// nk_layout_row_end(ctx); 2116 /// // 2117 /// // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75 2118 /// nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2); 2119 /// nk_layout_row_push(ctx, 0.25f); 2120 /// nk_widget(...); 2121 /// nk_layout_row_push(ctx, 0.75f); 2122 /// nk_widget(...); 2123 /// nk_layout_row_end(ctx); 2124 /// } 2125 /// nk_end(...); 2126 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2127 /// 2128 /// 4. __nk_layout_row__<br /><br /> 2129 /// The array counterpart to API nk_layout_row_xxx is the single nk_layout_row 2130 /// functions. Instead of pushing either pixel or window ratio for every widget 2131 /// it allows to define it by array. The trade of for less control is that 2132 /// `nk_layout_row` is automatically repeating. Otherwise the behavior is the 2133 /// same. 2134 /// 2135 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2136 /// if (nk_begin_xxx(...) { 2137 /// // two rows with height: 30 composed of two widgets with width 60 and 40 2138 /// const float size[] = {60,40}; 2139 /// nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); 2140 /// nk_widget(...); 2141 /// nk_widget(...); 2142 /// nk_widget(...); 2143 /// nk_widget(...); 2144 /// // 2145 /// // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75 2146 /// const float ratio[] = {0.25, 0.75}; 2147 /// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2148 /// nk_widget(...); 2149 /// nk_widget(...); 2150 /// nk_widget(...); 2151 /// nk_widget(...); 2152 /// // 2153 /// // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75 2154 /// const float ratio[] = {0.25, 0.75}; 2155 /// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2156 /// nk_widget(...); 2157 /// nk_widget(...); 2158 /// nk_widget(...); 2159 /// nk_widget(...); 2160 /// } 2161 /// nk_end(...); 2162 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2163 /// 2164 /// 5. __nk_layout_row_template_xxx__<br /><br /> 2165 /// The most complex and second most flexible API is a simplified flexbox version without 2166 /// line wrapping and weights for dynamic widgets. It is an immediate mode API but 2167 /// unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called 2168 /// before calling the templated widgets. 2169 /// The row template layout has three different per widget size specifier. The first 2170 /// one is the `nk_layout_row_template_push_static` with fixed widget pixel width. 2171 /// They do not grow if the row grows and will always stay the same. 2172 /// The second size specifier is `nk_layout_row_template_push_variable` 2173 /// which defines a minimum widget size but it also can grow if more space is available 2174 /// not taken by other widgets. 2175 /// Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic` 2176 /// which are completely flexible and unlike variable widgets can even shrink 2177 /// to zero if not enough space is provided. 2178 /// 2179 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2180 /// if (nk_begin_xxx(...) { 2181 /// // two rows with height: 30 composed of three widgets 2182 /// nk_layout_row_template_begin(ctx, 30); 2183 /// nk_layout_row_template_push_dynamic(ctx); 2184 /// nk_layout_row_template_push_variable(ctx, 80); 2185 /// nk_layout_row_template_push_static(ctx, 80); 2186 /// nk_layout_row_template_end(ctx); 2187 /// // 2188 /// // first row 2189 /// nk_widget(...); // dynamic widget can go to zero if not enough space 2190 /// nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space 2191 /// nk_widget(...); // static widget with fixed 80 pixel width 2192 /// // 2193 /// // second row same layout 2194 /// nk_widget(...); 2195 /// nk_widget(...); 2196 /// nk_widget(...); 2197 /// } 2198 /// nk_end(...); 2199 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2200 /// 2201 /// 6. __nk_layout_space_xxx__<br /><br /> 2202 /// Finally the most flexible API directly allows you to place widgets inside the 2203 /// window. The space layout API is an immediate mode API which does not support 2204 /// row auto repeat and directly sets position and size of a widget. Position 2205 /// and size hereby can be either specified as ratio of allocated space or 2206 /// allocated space local position and pixel size. Since this API is quite 2207 /// powerful there are a number of utility functions to get the available space 2208 /// and convert between local allocated space and screen space. 2209 /// 2210 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2211 /// if (nk_begin_xxx(...) { 2212 /// // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2213 /// nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX); 2214 /// nk_layout_space_push(ctx, nk_rect(0,0,150,200)); 2215 /// nk_widget(...); 2216 /// nk_layout_space_push(ctx, nk_rect(200,200,100,200)); 2217 /// nk_widget(...); 2218 /// nk_layout_space_end(ctx); 2219 /// // 2220 /// // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2221 /// nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX); 2222 /// nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1)); 2223 /// nk_widget(...); 2224 /// nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1)); 2225 /// nk_widget(...); 2226 /// } 2227 /// nk_end(...); 2228 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2229 /// 2230 /// #### Reference 2231 /// Function | Description 2232 /// ----------------------------------------|------------------------------------ 2233 /// nk_layout_set_min_row_height | Set the currently used minimum row height to a specified value 2234 /// nk_layout_reset_min_row_height | Resets the currently used minimum row height to font height 2235 /// nk_layout_widget_bounds | Calculates current width a static layout row can fit inside a window 2236 /// nk_layout_ratio_from_pixel | Utility functions to calculate window ratio from pixel size 2237 // 2238 /// nk_layout_row_dynamic | Current layout is divided into n same sized growing columns 2239 /// nk_layout_row_static | Current layout is divided into n same fixed sized columns 2240 /// nk_layout_row_begin | Starts a new row with given height and number of columns 2241 /// nk_layout_row_push | Pushes another column with given size or window ratio 2242 /// nk_layout_row_end | Finished previously started row 2243 /// nk_layout_row | Specifies row columns in array as either window ratio or size 2244 // 2245 /// nk_layout_row_template_begin | Begins the row template declaration 2246 /// nk_layout_row_template_push_dynamic | Adds a dynamic column that dynamically grows and can go to zero if not enough space 2247 /// nk_layout_row_template_push_variable | Adds a variable column that dynamically grows but does not shrink below specified pixel width 2248 /// nk_layout_row_template_push_static | Adds a static column that does not grow and will always have the same size 2249 /// nk_layout_row_template_end | Marks the end of the row template 2250 // 2251 /// nk_layout_space_begin | Begins a new layouting space that allows to specify each widgets position and size 2252 /// nk_layout_space_push | Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2253 /// nk_layout_space_end | Marks the end of the layouting space 2254 // 2255 /// nk_layout_space_bounds | Callable after nk_layout_space_begin and returns total space allocated 2256 /// nk_layout_space_to_screen | Converts vector from nk_layout_space coordinate space into screen space 2257 /// nk_layout_space_to_local | Converts vector from screen space into nk_layout_space coordinates 2258 /// nk_layout_space_rect_to_screen | Converts rectangle from nk_layout_space coordinate space into screen space 2259 /// nk_layout_space_rect_to_local | Converts rectangle from screen space into nk_layout_space coordinates 2260 */ 2261 /*/// #### nk_layout_set_min_row_height 2262 /// Sets the currently used minimum row height. 2263 /// !!! WARNING 2264 /// The passed height needs to include both your preferred row height 2265 /// as well as padding. No internal padding is added. 2266 /// 2267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2268 /// void nk_layout_set_min_row_height(struct nk_context*, float height); 2269 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2270 /// 2271 /// Parameter | Description 2272 /// ------------|----------------------------------------------------------- 2273 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2274 /// __height__ | New minimum row height to be used for auto generating the row height 2275 */ 2276 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height); 2277 /*/// #### nk_layout_reset_min_row_height 2278 /// Reset the currently used minimum row height back to `font_height + text_padding + padding` 2279 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2280 /// void nk_layout_reset_min_row_height(struct nk_context*); 2281 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2282 /// 2283 /// Parameter | Description 2284 /// ------------|----------------------------------------------------------- 2285 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2286 */ 2287 NK_API void nk_layout_reset_min_row_height(struct nk_context*); 2288 /*/// #### nk_layout_widget_bounds 2289 /// Returns the width of the next row allocate by one of the layouting functions 2290 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2291 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2292 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2293 /// 2294 /// Parameter | Description 2295 /// ------------|----------------------------------------------------------- 2296 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2297 /// 2298 /// Return `nk_rect` with both position and size of the next row 2299 */ 2300 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2301 /*/// #### nk_layout_ratio_from_pixel 2302 /// Utility functions to calculate window ratio from pixel size 2303 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2304 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2305 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2306 /// 2307 /// Parameter | Description 2308 /// ------------|----------------------------------------------------------- 2309 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2310 /// __pixel__ | Pixel_width to convert to window ratio 2311 /// 2312 /// Returns `nk_rect` with both position and size of the next row 2313 */ 2314 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2315 /*/// #### nk_layout_row_dynamic 2316 /// Sets current row layout to share horizontal space 2317 /// between @cols number of widgets evenly. Once called all subsequent widget 2318 /// calls greater than @cols will allocate a new row with same layout. 2319 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2320 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2322 /// 2323 /// Parameter | Description 2324 /// ------------|----------------------------------------------------------- 2325 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2326 /// __height__ | Holds height of each widget in row or zero for auto layouting 2327 /// __columns__ | Number of widget inside row 2328 */ 2329 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2330 /*/// #### nk_layout_row_static 2331 /// Sets current row layout to fill @cols number of widgets 2332 /// in row with same @item_width horizontal size. Once called all subsequent widget 2333 /// calls greater than @cols will allocate a new row with same layout. 2334 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2335 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2336 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2337 /// 2338 /// Parameter | Description 2339 /// ------------|----------------------------------------------------------- 2340 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2341 /// __height__ | Holds height of each widget in row or zero for auto layouting 2342 /// __width__ | Holds pixel width of each widget in the row 2343 /// __columns__ | Number of widget inside row 2344 */ 2345 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2346 /*/// #### nk_layout_row_begin 2347 /// Starts a new dynamic or fixed row with given height and columns. 2348 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2349 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2350 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2351 /// 2352 /// Parameter | Description 2353 /// ------------|----------------------------------------------------------- 2354 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2355 /// __fmt__ | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2356 /// __height__ | holds height of each widget in row or zero for auto layouting 2357 /// __columns__ | Number of widget inside row 2358 */ 2359 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2360 /*/// #### nk_layout_row_push 2361 /// Specifies either window ratio or width of a single column 2362 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2363 /// void nk_layout_row_push(struct nk_context*, float value); 2364 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2365 /// 2366 /// Parameter | Description 2367 /// ------------|----------------------------------------------------------- 2368 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2369 /// __value__ | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call 2370 */ 2371 NK_API void nk_layout_row_push(struct nk_context*, float value); 2372 /*/// #### nk_layout_row_end 2373 /// Finished previously started row 2374 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2375 /// void nk_layout_row_end(struct nk_context*); 2376 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2377 /// 2378 /// Parameter | Description 2379 /// ------------|----------------------------------------------------------- 2380 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2381 */ 2382 NK_API void nk_layout_row_end(struct nk_context*); 2383 /*/// #### nk_layout_row 2384 /// Specifies row columns in array as either window ratio or size 2385 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2386 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2387 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2388 /// 2389 /// Parameter | Description 2390 /// ------------|----------------------------------------------------------- 2391 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2392 /// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2393 /// __height__ | Holds height of each widget in row or zero for auto layouting 2394 /// __columns__ | Number of widget inside row 2395 */ 2396 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2397 /*/// #### nk_layout_row_template_begin 2398 /// Begins the row template declaration 2399 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2400 /// void nk_layout_row_template_begin(struct nk_context*, float row_height); 2401 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2402 /// 2403 /// Parameter | Description 2404 /// ------------|----------------------------------------------------------- 2405 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2406 /// __height__ | Holds height of each widget in row or zero for auto layouting 2407 */ 2408 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height); 2409 /*/// #### nk_layout_row_template_push_dynamic 2410 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space 2411 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2412 /// void nk_layout_row_template_push_dynamic(struct nk_context*); 2413 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2414 /// 2415 /// Parameter | Description 2416 /// ------------|----------------------------------------------------------- 2417 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2418 /// __height__ | Holds height of each widget in row or zero for auto layouting 2419 */ 2420 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*); 2421 /*/// #### nk_layout_row_template_push_variable 2422 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width 2423 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2424 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2425 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2426 /// 2427 /// Parameter | Description 2428 /// ------------|----------------------------------------------------------- 2429 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2430 /// __width__ | Holds the minimum pixel width the next column must always be 2431 */ 2432 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2433 /*/// #### nk_layout_row_template_push_static 2434 /// Adds a static column that does not grow and will always have the same size 2435 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2436 /// void nk_layout_row_template_push_static(struct nk_context*, float width); 2437 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2438 /// 2439 /// Parameter | Description 2440 /// ------------|----------------------------------------------------------- 2441 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2442 /// __width__ | Holds the absolute pixel width value the next column must be 2443 */ 2444 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width); 2445 /*/// #### nk_layout_row_template_end 2446 /// Marks the end of the row template 2447 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2448 /// void nk_layout_row_template_end(struct nk_context*); 2449 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2450 /// 2451 /// Parameter | Description 2452 /// ------------|----------------------------------------------------------- 2453 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2454 */ 2455 NK_API void nk_layout_row_template_end(struct nk_context*); 2456 /*/// #### nk_layout_space_begin 2457 /// Begins a new layouting space that allows to specify each widgets position and size. 2458 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2459 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2460 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2461 /// 2462 /// Parameter | Description 2463 /// ------------|----------------------------------------------------------- 2464 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2465 /// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2466 /// __height__ | Holds height of each widget in row or zero for auto layouting 2467 /// __columns__ | Number of widgets inside row 2468 */ 2469 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2470 /*/// #### nk_layout_space_push 2471 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2472 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2473 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds); 2474 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2475 /// 2476 /// Parameter | Description 2477 /// ------------|----------------------------------------------------------- 2478 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2479 /// __bounds__ | Position and size in laoyut space local coordinates 2480 */ 2481 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds); 2482 /*/// #### nk_layout_space_end 2483 /// Marks the end of the layout space 2484 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2485 /// void nk_layout_space_end(struct nk_context*); 2486 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2487 /// 2488 /// Parameter | Description 2489 /// ------------|----------------------------------------------------------- 2490 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2491 */ 2492 NK_API void nk_layout_space_end(struct nk_context*); 2493 /*/// #### nk_layout_space_bounds 2494 /// Utility function to calculate total space allocated for `nk_layout_space` 2495 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2496 /// struct nk_rect nk_layout_space_bounds(struct nk_context*); 2497 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2498 /// 2499 /// Parameter | Description 2500 /// ------------|----------------------------------------------------------- 2501 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2502 /// 2503 /// Returns `nk_rect` holding the total space allocated 2504 */ 2505 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*); 2506 /*/// #### nk_layout_space_to_screen 2507 /// Converts vector from nk_layout_space coordinate space into screen space 2508 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2509 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2510 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2511 /// 2512 /// Parameter | Description 2513 /// ------------|----------------------------------------------------------- 2514 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2515 /// __vec__ | Position to convert from layout space into screen coordinate space 2516 /// 2517 /// Returns transformed `nk_vec2` in screen space coordinates 2518 */ 2519 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2520 /*/// #### nk_layout_space_to_local 2521 /// Converts vector from layout space into screen space 2522 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2523 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2524 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2525 /// 2526 /// Parameter | Description 2527 /// ------------|----------------------------------------------------------- 2528 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2529 /// __vec__ | Position to convert from screen space into layout coordinate space 2530 /// 2531 /// Returns transformed `nk_vec2` in layout space coordinates 2532 */ 2533 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2534 /*/// #### nk_layout_space_rect_to_screen 2535 /// Converts rectangle from screen space into layout space 2536 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2537 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2538 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2539 /// 2540 /// Parameter | Description 2541 /// ------------|----------------------------------------------------------- 2542 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2543 /// __bounds__ | Rectangle to convert from layout space into screen space 2544 /// 2545 /// Returns transformed `nk_rect` in screen space coordinates 2546 */ 2547 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2548 /*/// #### nk_layout_space_rect_to_local 2549 /// Converts rectangle from layout space into screen space 2550 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2551 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2552 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2553 /// 2554 /// Parameter | Description 2555 /// ------------|----------------------------------------------------------- 2556 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2557 /// __bounds__ | Rectangle to convert from layout space into screen space 2558 /// 2559 /// Returns transformed `nk_rect` in layout space coordinates 2560 */ 2561 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2562 /* ============================================================================= 2563 * 2564 * GROUP 2565 * 2566 * ============================================================================= 2567 /// ### Groups 2568 /// Groups are basically windows inside windows. They allow to subdivide space 2569 /// in a window to layout widgets as a group. Almost all more complex widget 2570 /// layouting requirements can be solved using groups and basic layouting 2571 /// fuctionality. Groups just like windows are identified by an unique name and 2572 /// internally keep track of scrollbar offsets by default. However additional 2573 /// versions are provided to directly manage the scrollbar. 2574 /// 2575 /// #### Usage 2576 /// To create a group you have to call one of the three `nk_group_begin_xxx` 2577 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it 2578 /// is required to check the return value of `nk_group_begin_xxx` and only process 2579 /// widgets inside the window if the value is not 0. 2580 /// Nesting groups is possible and even encouraged since many layouting schemes 2581 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end` 2582 /// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0: 2583 /// 2584 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2585 /// if (nk_group_begin_xxx(ctx, ...) { 2586 /// // [... widgets ...] 2587 /// nk_group_end(ctx); 2588 /// } 2589 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2590 /// 2591 /// In the grand concept groups can be called after starting a window 2592 /// with `nk_begin_xxx` and before calling `nk_end`: 2593 /// 2594 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2595 /// struct nk_context ctx; 2596 /// nk_init_xxx(&ctx, ...); 2597 /// while (1) { 2598 /// // Input 2599 /// Event evt; 2600 /// nk_input_begin(&ctx); 2601 /// while (GetEvent(&evt)) { 2602 /// if (evt.type == MOUSE_MOVE) 2603 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 2604 /// else if (evt.type == [...]) { 2605 /// nk_input_xxx(...); 2606 /// } 2607 /// } 2608 /// nk_input_end(&ctx); 2609 /// // 2610 /// // Window 2611 /// if (nk_begin_xxx(...) { 2612 /// // [...widgets...] 2613 /// nk_layout_row_dynamic(...); 2614 /// if (nk_group_begin_xxx(ctx, ...) { 2615 /// //[... widgets ...] 2616 /// nk_group_end(ctx); 2617 /// } 2618 /// } 2619 /// nk_end(ctx); 2620 /// // 2621 /// // Draw 2622 /// const struct nk_command *cmd = 0; 2623 /// nk_foreach(cmd, &ctx) { 2624 /// switch (cmd->type) { 2625 /// case NK_COMMAND_LINE: 2626 /// your_draw_line_function(...) 2627 /// break; 2628 /// case NK_COMMAND_RECT 2629 /// your_draw_rect_function(...) 2630 /// break; 2631 /// case ...: 2632 /// // [...] 2633 /// } 2634 /// nk_clear(&ctx); 2635 /// } 2636 /// nk_free(&ctx); 2637 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2638 /// #### Reference 2639 /// Function | Description 2640 /// --------------------------------|------------------------------------------- 2641 /// nk_group_begin | Start a new group with internal scrollbar handling 2642 /// nk_group_begin_titled | Start a new group with separeted name and title and internal scrollbar handling 2643 /// nk_group_end | Ends a group. Should only be called if nk_group_begin returned non-zero 2644 /// nk_group_scrolled_offset_begin | Start a new group with manual separated handling of scrollbar x- and y-offset 2645 /// nk_group_scrolled_begin | Start a new group with manual scrollbar handling 2646 /// nk_group_scrolled_end | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero 2647 /// nk_group_get_scroll | Gets the scroll offset for the given group 2648 /// nk_group_set_scroll | Sets the scroll offset for the given group 2649 */ 2650 /*/// #### nk_group_begin 2651 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2653 /// int nk_group_begin(struct nk_context*, const char *title, nk_flags); 2654 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2655 /// 2656 /// Parameter | Description 2657 /// ------------|----------------------------------------------------------- 2658 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2659 /// __title__ | Must be an unique identifier for this group that is also used for the group header 2660 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2661 /// 2662 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2663 */ 2664 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags); 2665 /*/// #### nk_group_begin_titled 2666 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2668 /// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2669 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2670 /// 2671 /// Parameter | Description 2672 /// ------------|----------------------------------------------------------- 2673 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2674 /// __id__ | Must be an unique identifier for this group 2675 /// __title__ | Group header title 2676 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2677 /// 2678 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2679 */ 2680 NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2681 /*/// #### nk_group_end 2682 /// Ends a widget group 2683 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2684 /// void nk_group_end(struct nk_context*); 2685 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2686 /// 2687 /// Parameter | Description 2688 /// ------------|----------------------------------------------------------- 2689 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2690 */ 2691 NK_API void nk_group_end(struct nk_context*); 2692 /*/// #### nk_group_scrolled_offset_begin 2693 /// starts a new widget group. requires a previous layouting function to specify 2694 /// a size. Does not keep track of scrollbar. 2695 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2696 /// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2697 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2698 /// 2699 /// Parameter | Description 2700 /// ------------|----------------------------------------------------------- 2701 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2702 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally. 2703 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically 2704 /// __title__ | Window unique group title used to both identify and display in the group header 2705 /// __flags__ | Window flags from the nk_panel_flags section 2706 /// 2707 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2708 */ 2709 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); 2710 /*/// #### nk_group_scrolled_begin 2711 /// Starts a new widget group. requires a previous 2712 /// layouting function to specify a size. Does not keep track of scrollbar. 2713 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2714 /// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2715 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2716 /// 2717 /// Parameter | Description 2718 /// ------------|----------------------------------------------------------- 2719 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2720 /// __off__ | Both x- and y- scroll offset. Allows for manual scrollbar control 2721 /// __title__ | Window unique group title used to both identify and display in the group header 2722 /// __flags__ | Window flags from nk_panel_flags section 2723 /// 2724 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2725 */ 2726 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2727 /*/// #### nk_group_scrolled_end 2728 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin. 2729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2730 /// void nk_group_scrolled_end(struct nk_context*); 2731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2732 /// 2733 /// Parameter | Description 2734 /// ------------|----------------------------------------------------------- 2735 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2736 */ 2737 NK_API void nk_group_scrolled_end(struct nk_context*); 2738 /*/// #### nk_group_get_scroll 2739 /// Gets the scroll position of the given group. 2740 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2741 /// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); 2742 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2743 /// 2744 /// Parameter | Description 2745 /// -------------|----------------------------------------------------------- 2746 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2747 /// __id__ | The id of the group to get the scroll position of 2748 /// __x_offset__ | A pointer to the x offset output (or NULL to ignore) 2749 /// __y_offset__ | A pointer to the y offset output (or NULL to ignore) 2750 */ 2751 NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); 2752 /*/// #### nk_group_set_scroll 2753 /// Sets the scroll position of the given group. 2754 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2755 /// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); 2756 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2757 /// 2758 /// Parameter | Description 2759 /// -------------|----------------------------------------------------------- 2760 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2761 /// __id__ | The id of the group to scroll 2762 /// __x_offset__ | The x offset to scroll to 2763 /// __y_offset__ | The y offset to scroll to 2764 */ 2765 NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); 2766 /* ============================================================================= 2767 * 2768 * TREE 2769 * 2770 * ============================================================================= 2771 /// ### Tree 2772 /// Trees represent two different concept. First the concept of a collapsable 2773 /// UI section that can be either in a hidden or visibile state. They allow the UI 2774 /// user to selectively minimize the current set of visible UI to comprehend. 2775 /// The second concept are tree widgets for visual UI representation of trees.<br /><br /> 2776 /// 2777 /// Trees thereby can be nested for tree representations and multiple nested 2778 /// collapsable UI sections. All trees are started by calling of the 2779 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the 2780 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label 2781 /// and optionally an image to be displayed and the initial collapse state from 2782 /// the nk_collapse_states section.<br /><br /> 2783 /// 2784 /// The runtime state of the tree is either stored outside the library by the caller 2785 /// or inside which requires a unique ID. The unique ID can either be generated 2786 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`, 2787 /// by `__FILE__` and a user provided ID generated for example by loop index with 2788 /// function `nk_tree_push_id` or completely provided from outside by user with 2789 /// function `nk_tree_push_hashed`. 2790 /// 2791 /// #### Usage 2792 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx` 2793 /// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the 2794 /// end. 2795 /// Each starting function will either return `false(0)` if the tree is collapsed 2796 /// or hidden and therefore does not need to be filled with content or `true(1)` 2797 /// if visible and required to be filled. 2798 /// 2799 /// !!! Note 2800 /// The tree header does not require and layouting function and instead 2801 /// calculates a auto height based on the currently used font size 2802 /// 2803 /// The tree ending functions only need to be called if the tree content is 2804 /// actually visible. So make sure the tree push function is guarded by `if` 2805 /// and the pop call is only taken if the tree is visible. 2806 /// 2807 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2808 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) { 2809 /// nk_layout_row_dynamic(...); 2810 /// nk_widget(...); 2811 /// nk_tree_pop(ctx); 2812 /// } 2813 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2814 /// 2815 /// #### Reference 2816 /// Function | Description 2817 /// ----------------------------|------------------------------------------- 2818 /// nk_tree_push | Start a collapsable UI section with internal state management 2819 /// nk_tree_push_id | Start a collapsable UI section with internal state management callable in a look 2820 /// nk_tree_push_hashed | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state 2821 /// nk_tree_image_push | Start a collapsable UI section with image and label header 2822 /// nk_tree_image_push_id | Start a collapsable UI section with image and label header and internal state management callable in a look 2823 /// 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 2824 /// nk_tree_pop | Ends a collapsable UI section 2825 // 2826 /// nk_tree_state_push | Start a collapsable UI section with external state management 2827 /// nk_tree_state_image_push | Start a collapsable UI section with image and label header and external state management 2828 /// nk_tree_state_pop | Ends a collapsabale UI section 2829 /// 2830 /// #### nk_tree_type 2831 /// Flag | Description 2832 /// ----------------|---------------------------------------- 2833 /// NK_TREE_NODE | Highlighted tree header to mark a collapsable UI section 2834 /// NK_TREE_TAB | Non-highighted tree header closer to tree representations 2835 */ 2836 /*/// #### nk_tree_push 2837 /// Starts a collapsable UI section with internal state management 2838 /// !!! WARNING 2839 /// To keep track of the runtime tree collapsable state this function uses 2840 /// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2841 /// to call this function in a loop please use `nk_tree_push_id` or 2842 /// `nk_tree_push_hashed` instead. 2843 /// 2844 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2845 /// #define nk_tree_push(ctx, type, title, state) 2846 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2847 /// 2848 /// Parameter | Description 2849 /// ------------|----------------------------------------------------------- 2850 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2851 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2852 /// __title__ | Label printed in the tree header 2853 /// __state__ | Initial tree state value out of nk_collapse_states 2854 /// 2855 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2856 */ 2857 #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__) 2858 /*/// #### nk_tree_push_id 2859 /// Starts a collapsable UI section with internal state management callable in a look 2860 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2861 /// #define nk_tree_push_id(ctx, type, title, state, id) 2862 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2863 /// 2864 /// Parameter | Description 2865 /// ------------|----------------------------------------------------------- 2866 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2867 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2868 /// __title__ | Label printed in the tree header 2869 /// __state__ | Initial tree state value out of nk_collapse_states 2870 /// __id__ | Loop counter index if this function is called in a loop 2871 /// 2872 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2873 */ 2874 #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) 2875 /*/// #### nk_tree_push_hashed 2876 /// Start a collapsable UI section with internal state management with full 2877 /// control over internal unique ID used to store state 2878 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2879 /// 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); 2880 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2881 /// 2882 /// Parameter | Description 2883 /// ------------|----------------------------------------------------------- 2884 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2885 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2886 /// __title__ | Label printed in the tree header 2887 /// __state__ | Initial tree state value out of nk_collapse_states 2888 /// __hash__ | Memory block or string to generate the ID from 2889 /// __len__ | Size of passed memory block or string in __hash__ 2890 /// __seed__ | Seeding value if this function is called in a loop or default to `0` 2891 /// 2892 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2893 */ 2894 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); 2895 /*/// #### nk_tree_image_push 2896 /// Start a collapsable UI section with image and label header 2897 /// !!! WARNING 2898 /// To keep track of the runtime tree collapsable state this function uses 2899 /// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2900 /// to call this function in a loop please use `nk_tree_image_push_id` or 2901 /// `nk_tree_image_push_hashed` instead. 2902 /// 2903 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2904 /// #define nk_tree_image_push(ctx, type, img, title, state) 2905 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2906 // 2907 /// Parameter | Description 2908 /// ------------|----------------------------------------------------------- 2909 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2910 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2911 /// __img__ | Image to display inside the header on the left of the label 2912 /// __title__ | Label printed in the tree header 2913 /// __state__ | Initial tree state value out of nk_collapse_states 2914 /// 2915 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2916 */ 2917 #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__) 2918 /*/// #### nk_tree_image_push_id 2919 /// Start a collapsable UI section with image and label header and internal state 2920 /// management callable in a look 2921 /// 2922 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2923 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id) 2924 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2925 /// 2926 /// Parameter | Description 2927 /// ------------|----------------------------------------------------------- 2928 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2929 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2930 /// __img__ | Image to display inside the header on the left of the label 2931 /// __title__ | Label printed in the tree header 2932 /// __state__ | Initial tree state value out of nk_collapse_states 2933 /// __id__ | Loop counter index if this function is called in a loop 2934 /// 2935 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2936 */ 2937 #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) 2938 /*/// #### nk_tree_image_push_hashed 2939 /// Start a collapsable UI section with internal state management with full 2940 /// control over internal unique ID used to store state 2941 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2942 /// 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); 2943 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2944 /// 2945 /// Parameter | Description 2946 /// ------------|----------------------------------------------------------- 2947 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2948 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2949 /// __img__ | Image to display inside the header on the left of the label 2950 /// __title__ | Label printed in the tree header 2951 /// __state__ | Initial tree state value out of nk_collapse_states 2952 /// __hash__ | Memory block or string to generate the ID from 2953 /// __len__ | Size of passed memory block or string in __hash__ 2954 /// __seed__ | Seeding value if this function is called in a loop or default to `0` 2955 /// 2956 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2957 */ 2958 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); 2959 /*/// #### nk_tree_pop 2960 /// Ends a collapsabale UI section 2961 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2962 /// void nk_tree_pop(struct nk_context*); 2963 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2964 /// 2965 /// Parameter | Description 2966 /// ------------|----------------------------------------------------------- 2967 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2968 */ 2969 NK_API void nk_tree_pop(struct nk_context*); 2970 /*/// #### nk_tree_state_push 2971 /// Start a collapsable UI section with external state management 2972 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2973 /// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 2974 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2975 /// 2976 /// Parameter | Description 2977 /// ------------|----------------------------------------------------------- 2978 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2979 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2980 /// __title__ | Label printed in the tree header 2981 /// __state__ | Persistent state to update 2982 /// 2983 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2984 */ 2985 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 2986 /*/// #### nk_tree_state_image_push 2987 /// Start a collapsable UI section with image and label header and external state management 2988 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2989 /// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); 2990 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2991 /// 2992 /// Parameter | Description 2993 /// ------------|----------------------------------------------------------- 2994 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2995 /// __img__ | Image to display inside the header on the left of the label 2996 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2997 /// __title__ | Label printed in the tree header 2998 /// __state__ | Persistent state to update 2999 /// 3000 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 3001 */ 3002 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); 3003 /*/// #### nk_tree_state_pop 3004 /// Ends a collapsabale UI section 3005 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3006 /// void nk_tree_state_pop(struct nk_context*); 3007 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3008 /// 3009 /// Parameter | Description 3010 /// ------------|----------------------------------------------------------- 3011 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3012 */ 3013 NK_API void nk_tree_state_pop(struct nk_context*); 3014 3015 #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__) 3016 #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) 3017 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); 3018 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); 3019 NK_API void nk_tree_element_pop(struct nk_context*); 3020 3021 /* ============================================================================= 3022 * 3023 * LIST VIEW 3024 * 3025 * ============================================================================= */ 3026 struct nk_list_view { 3027 /* public: */ 3028 int begin, end, count; 3029 /* private: */ 3030 int total_height; 3031 struct nk_context *ctx; 3032 nk_uint *scroll_pointer; 3033 nk_uint scroll_value; 3034 }; 3035 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); 3036 NK_API void nk_list_view_end(struct nk_list_view*); 3037 /* ============================================================================= 3038 * 3039 * WIDGET 3040 * 3041 * ============================================================================= */ 3042 enum nk_widget_layout_states { 3043 NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */ 3044 NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */ 3045 NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */ 3046 }; 3047 enum nk_widget_states { 3048 NK_WIDGET_STATE_MODIFIED = NK_FLAG(1), 3049 NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */ 3050 NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */ 3051 NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */ 3052 NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */ 3053 NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */ 3054 NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */ 3055 NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */ 3056 }; 3057 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*); 3058 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2); 3059 NK_API struct nk_rect nk_widget_bounds(struct nk_context*); 3060 NK_API struct nk_vec2 nk_widget_position(struct nk_context*); 3061 NK_API struct nk_vec2 nk_widget_size(struct nk_context*); 3062 NK_API float nk_widget_width(struct nk_context*); 3063 NK_API float nk_widget_height(struct nk_context*); 3064 NK_API int nk_widget_is_hovered(struct nk_context*); 3065 NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons); 3066 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down); 3067 NK_API void nk_spacing(struct nk_context*, int cols); 3068 /* ============================================================================= 3069 * 3070 * TEXT 3071 * 3072 * ============================================================================= */ 3073 enum nk_text_align { 3074 NK_TEXT_ALIGN_LEFT = 0x01, 3075 NK_TEXT_ALIGN_CENTERED = 0x02, 3076 NK_TEXT_ALIGN_RIGHT = 0x04, 3077 NK_TEXT_ALIGN_TOP = 0x08, 3078 NK_TEXT_ALIGN_MIDDLE = 0x10, 3079 NK_TEXT_ALIGN_BOTTOM = 0x20 3080 }; 3081 enum nk_text_alignment { 3082 NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT, 3083 NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED, 3084 NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT 3085 }; 3086 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags); 3087 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color); 3088 NK_API void nk_text_wrap(struct nk_context*, const char*, int); 3089 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color); 3090 NK_API void nk_label(struct nk_context*, const char*, nk_flags align); 3091 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color); 3092 NK_API void nk_label_wrap(struct nk_context*, const char*); 3093 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color); 3094 NK_API void nk_image(struct nk_context*, struct nk_image); 3095 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color); 3096 #ifdef NK_INCLUDE_STANDARD_VARARGS 3097 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3); 3098 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); 3099 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2); 3100 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3); 3101 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3); 3102 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); 3103 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3104 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); 3105 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int); 3106 NK_API void nk_value_int(struct nk_context*, const char *prefix, int); 3107 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int); 3108 NK_API void nk_value_float(struct nk_context*, const char *prefix, float); 3109 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color); 3110 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color); 3111 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color); 3112 #endif 3113 /* ============================================================================= 3114 * 3115 * BUTTON 3116 * 3117 * ============================================================================= */ 3118 NK_API int nk_button_text(struct nk_context*, const char *title, int len); 3119 NK_API int nk_button_label(struct nk_context*, const char *title); 3120 NK_API int nk_button_color(struct nk_context*, struct nk_color); 3121 NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type); 3122 NK_API int nk_button_image(struct nk_context*, struct nk_image img); 3123 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment); 3124 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3125 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment); 3126 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment); 3127 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len); 3128 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title); 3129 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type); 3130 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img); 3131 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); 3132 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); 3133 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); 3134 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); 3135 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior); 3136 NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior); 3137 NK_API int nk_button_pop_behavior(struct nk_context*); 3138 /* ============================================================================= 3139 * 3140 * CHECKBOX 3141 * 3142 * ============================================================================= */ 3143 NK_API int nk_check_label(struct nk_context*, const char*, int active); 3144 NK_API int nk_check_text(struct nk_context*, const char*, int,int active); 3145 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value); 3146 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value); 3147 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active); 3148 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active); 3149 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value); 3150 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value); 3151 /* ============================================================================= 3152 * 3153 * RADIO BUTTON 3154 * 3155 * ============================================================================= */ 3156 NK_API int nk_radio_label(struct nk_context*, const char*, int *active); 3157 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active); 3158 NK_API int nk_option_label(struct nk_context*, const char*, int active); 3159 NK_API int nk_option_text(struct nk_context*, const char*, int, int active); 3160 /* ============================================================================= 3161 * 3162 * SELECTABLE 3163 * 3164 * ============================================================================= */ 3165 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value); 3166 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value); 3167 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value); 3168 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value); 3169 NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int *value); 3170 NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value); 3171 3172 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value); 3173 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value); 3174 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value); 3175 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value); 3176 NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int value); 3177 NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value); 3178 3179 /* ============================================================================= 3180 * 3181 * SLIDER 3182 * 3183 * ============================================================================= */ 3184 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step); 3185 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); 3186 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step); 3187 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step); 3188 /* ============================================================================= 3189 * 3190 * PROGRESSBAR 3191 * 3192 * ============================================================================= */ 3193 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable); 3194 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable); 3195 3196 /* ============================================================================= 3197 * 3198 * COLOR PICKER 3199 * 3200 * ============================================================================= */ 3201 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format); 3202 NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format); 3203 /* ============================================================================= 3204 * 3205 * PROPERTIES 3206 * 3207 * ============================================================================= 3208 /// ### Properties 3209 /// Properties are the main value modification widgets in Nuklear. Changing a value 3210 /// can be achieved by dragging, adding/removing incremental steps on button click 3211 /// or by directly typing a number. 3212 /// 3213 /// #### Usage 3214 /// Each property requires a unique name for identifaction that is also used for 3215 /// displaying a label. If you want to use the same name multiple times make sure 3216 /// add a '#' before your name. The '#' will not be shown but will generate a 3217 /// unique ID. Each propery also takes in a minimum and maximum value. If you want 3218 /// to make use of the complete number range of a type just use the provided 3219 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for 3220 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in 3221 /// a increment value that will be added or subtracted if either the increment 3222 /// decrement button is clicked. Finally there is a value for increment per pixel 3223 /// dragged that is added or subtracted from the value. 3224 /// 3225 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3226 /// int value = 0; 3227 /// struct nk_context ctx; 3228 /// nk_init_xxx(&ctx, ...); 3229 /// while (1) { 3230 /// // Input 3231 /// Event evt; 3232 /// nk_input_begin(&ctx); 3233 /// while (GetEvent(&evt)) { 3234 /// if (evt.type == MOUSE_MOVE) 3235 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 3236 /// else if (evt.type == [...]) { 3237 /// nk_input_xxx(...); 3238 /// } 3239 /// } 3240 /// nk_input_end(&ctx); 3241 /// // 3242 /// // Window 3243 /// if (nk_begin_xxx(...) { 3244 /// // Property 3245 /// nk_layout_row_dynamic(...); 3246 /// nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1); 3247 /// } 3248 /// nk_end(ctx); 3249 /// // 3250 /// // Draw 3251 /// const struct nk_command *cmd = 0; 3252 /// nk_foreach(cmd, &ctx) { 3253 /// switch (cmd->type) { 3254 /// case NK_COMMAND_LINE: 3255 /// your_draw_line_function(...) 3256 /// break; 3257 /// case NK_COMMAND_RECT 3258 /// your_draw_rect_function(...) 3259 /// break; 3260 /// case ...: 3261 /// // [...] 3262 /// } 3263 /// nk_clear(&ctx); 3264 /// } 3265 /// nk_free(&ctx); 3266 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3267 /// 3268 /// #### Reference 3269 /// Function | Description 3270 /// --------------------|------------------------------------------- 3271 /// nk_property_int | Integer property directly modifing a passed in value 3272 /// nk_property_float | Float property directly modifing a passed in value 3273 /// nk_property_double | Double property directly modifing a passed in value 3274 /// nk_propertyi | Integer property returning the modified int value 3275 /// nk_propertyf | Float property returning the modified float value 3276 /// nk_propertyd | Double property returning the modified double value 3277 /// 3278 */ 3279 /*/// #### nk_property_int 3280 /// Integer property directly modifing a passed in value 3281 /// !!! WARNING 3282 /// To generate a unique property ID using the same label make sure to insert 3283 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3284 /// 3285 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3286 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3287 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3288 /// 3289 /// Parameter | Description 3290 /// --------------------|----------------------------------------------------------- 3291 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3292 /// __name__ | String used both as a label as well as a unique identifier 3293 /// __min__ | Minimum value not allowed to be underflown 3294 /// __val__ | Integer pointer to be modified 3295 /// __max__ | Maximum value not allowed to be overflown 3296 /// __step__ | Increment added and subtracted on increment and decrement button 3297 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3298 */ 3299 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3300 /*/// #### nk_property_float 3301 /// Float property directly modifing a passed in value 3302 /// !!! WARNING 3303 /// To generate a unique property ID using the same label make sure to insert 3304 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3305 /// 3306 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3307 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3308 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3309 /// 3310 /// Parameter | Description 3311 /// --------------------|----------------------------------------------------------- 3312 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3313 /// __name__ | String used both as a label as well as a unique identifier 3314 /// __min__ | Minimum value not allowed to be underflown 3315 /// __val__ | Float pointer to be modified 3316 /// __max__ | Maximum value not allowed to be overflown 3317 /// __step__ | Increment added and subtracted on increment and decrement button 3318 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3319 */ 3320 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3321 /*/// #### nk_property_double 3322 /// Double property directly modifing a passed in value 3323 /// !!! WARNING 3324 /// To generate a unique property ID using the same label make sure to insert 3325 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3326 /// 3327 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3328 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel); 3329 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3330 /// 3331 /// Parameter | Description 3332 /// --------------------|----------------------------------------------------------- 3333 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3334 /// __name__ | String used both as a label as well as a unique identifier 3335 /// __min__ | Minimum value not allowed to be underflown 3336 /// __val__ | Double pointer to be modified 3337 /// __max__ | Maximum value not allowed to be overflown 3338 /// __step__ | Increment added and subtracted on increment and decrement button 3339 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3340 */ 3341 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel); 3342 /*/// #### nk_propertyi 3343 /// Integer property modifing a passed in value and returning the new value 3344 /// !!! WARNING 3345 /// To generate a unique property ID using the same label make sure to insert 3346 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3347 /// 3348 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3349 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3350 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3351 /// 3352 /// Parameter | Description 3353 /// --------------------|----------------------------------------------------------- 3354 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3355 /// __name__ | String used both as a label as well as a unique identifier 3356 /// __min__ | Minimum value not allowed to be underflown 3357 /// __val__ | Current integer value to be modified and returned 3358 /// __max__ | Maximum value not allowed to be overflown 3359 /// __step__ | Increment added and subtracted on increment and decrement button 3360 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3361 /// 3362 /// Returns the new modified integer value 3363 */ 3364 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3365 /*/// #### nk_propertyf 3366 /// Float property modifing a passed in value and returning the new value 3367 /// !!! WARNING 3368 /// To generate a unique property ID using the same label make sure to insert 3369 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3370 /// 3371 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3372 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3373 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3374 /// 3375 /// Parameter | Description 3376 /// --------------------|----------------------------------------------------------- 3377 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3378 /// __name__ | String used both as a label as well as a unique identifier 3379 /// __min__ | Minimum value not allowed to be underflown 3380 /// __val__ | Current float value to be modified and returned 3381 /// __max__ | Maximum value not allowed to be overflown 3382 /// __step__ | Increment added and subtracted on increment and decrement button 3383 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3384 /// 3385 /// Returns the new modified float value 3386 */ 3387 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3388 /*/// #### nk_propertyd 3389 /// Float property modifing a passed in value and returning the new value 3390 /// !!! WARNING 3391 /// To generate a unique property ID using the same label make sure to insert 3392 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3393 /// 3394 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3395 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel); 3396 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3397 /// 3398 /// Parameter | Description 3399 /// --------------------|----------------------------------------------------------- 3400 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3401 /// __name__ | String used both as a label as well as a unique identifier 3402 /// __min__ | Minimum value not allowed to be underflown 3403 /// __val__ | Current double value to be modified and returned 3404 /// __max__ | Maximum value not allowed to be overflown 3405 /// __step__ | Increment added and subtracted on increment and decrement button 3406 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3407 /// 3408 /// Returns the new modified double value 3409 */ 3410 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel); 3411 /* ============================================================================= 3412 * 3413 * TEXT EDIT 3414 * 3415 * ============================================================================= */ 3416 enum nk_edit_flags { 3417 NK_EDIT_DEFAULT = 0, 3418 NK_EDIT_READ_ONLY = NK_FLAG(0), 3419 NK_EDIT_AUTO_SELECT = NK_FLAG(1), 3420 NK_EDIT_SIG_ENTER = NK_FLAG(2), 3421 NK_EDIT_ALLOW_TAB = NK_FLAG(3), 3422 NK_EDIT_NO_CURSOR = NK_FLAG(4), 3423 NK_EDIT_SELECTABLE = NK_FLAG(5), 3424 NK_EDIT_CLIPBOARD = NK_FLAG(6), 3425 NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7), 3426 NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8), 3427 NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9), 3428 NK_EDIT_MULTILINE = NK_FLAG(10), 3429 NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(11) 3430 }; 3431 enum nk_edit_types { 3432 NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE, 3433 NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD, 3434 NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD, 3435 NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD 3436 }; 3437 enum nk_edit_events { 3438 NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */ 3439 NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */ 3440 NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */ 3441 NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */ 3442 NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */ 3443 }; 3444 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter); 3445 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter); 3446 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter); 3447 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags); 3448 NK_API void nk_edit_unfocus(struct nk_context*); 3449 /* ============================================================================= 3450 * 3451 * CHART 3452 * 3453 * ============================================================================= */ 3454 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max); 3455 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); 3456 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value); 3457 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); 3458 NK_API nk_flags nk_chart_push(struct nk_context*, float); 3459 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int); 3460 NK_API void nk_chart_end(struct nk_context*); 3461 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset); 3462 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); 3463 /* ============================================================================= 3464 * 3465 * POPUP 3466 * 3467 * ============================================================================= */ 3468 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); 3469 NK_API void nk_popup_close(struct nk_context*); 3470 NK_API void nk_popup_end(struct nk_context*); 3471 NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); 3472 NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); 3473 /* ============================================================================= 3474 * 3475 * COMBOBOX 3476 * 3477 * ============================================================================= */ 3478 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size); 3479 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); 3480 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); 3481 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); 3482 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); 3483 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); 3484 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); 3485 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); 3486 /* ============================================================================= 3487 * 3488 * ABSTRACT COMBOBOX 3489 * 3490 * ============================================================================= */ 3491 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size); 3492 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size); 3493 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size); 3494 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size); 3495 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size); 3496 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size); 3497 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size); 3498 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size); 3499 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size); 3500 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment); 3501 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment); 3502 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3503 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment); 3504 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3505 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3506 NK_API void nk_combo_close(struct nk_context*); 3507 NK_API void nk_combo_end(struct nk_context*); 3508 /* ============================================================================= 3509 * 3510 * CONTEXTUAL 3511 * 3512 * ============================================================================= */ 3513 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds); 3514 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align); 3515 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align); 3516 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3517 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3518 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3519 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3520 NK_API void nk_contextual_close(struct nk_context*); 3521 NK_API void nk_contextual_end(struct nk_context*); 3522 /* ============================================================================= 3523 * 3524 * TOOLTIP 3525 * 3526 * ============================================================================= */ 3527 NK_API void nk_tooltip(struct nk_context*, const char*); 3528 #ifdef NK_INCLUDE_STANDARD_VARARGS 3529 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2); 3530 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3531 #endif 3532 NK_API int nk_tooltip_begin(struct nk_context*, float width); 3533 NK_API void nk_tooltip_end(struct nk_context*); 3534 /* ============================================================================= 3535 * 3536 * MENU 3537 * 3538 * ============================================================================= */ 3539 NK_API void nk_menubar_begin(struct nk_context*); 3540 NK_API void nk_menubar_end(struct nk_context*); 3541 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size); 3542 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size); 3543 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size); 3544 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size); 3545 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size); 3546 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size); 3547 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); 3548 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3549 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align); 3550 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment); 3551 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3552 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3553 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3554 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3555 NK_API void nk_menu_close(struct nk_context*); 3556 NK_API void nk_menu_end(struct nk_context*); 3557 /* ============================================================================= 3558 * 3559 * STYLE 3560 * 3561 * ============================================================================= */ 3562 enum nk_style_colors { 3563 NK_COLOR_TEXT, 3564 NK_COLOR_WINDOW, 3565 NK_COLOR_HEADER, 3566 NK_COLOR_BORDER, 3567 NK_COLOR_BUTTON, 3568 NK_COLOR_BUTTON_HOVER, 3569 NK_COLOR_BUTTON_ACTIVE, 3570 NK_COLOR_TOGGLE, 3571 NK_COLOR_TOGGLE_HOVER, 3572 NK_COLOR_TOGGLE_CURSOR, 3573 NK_COLOR_SELECT, 3574 NK_COLOR_SELECT_ACTIVE, 3575 NK_COLOR_SLIDER, 3576 NK_COLOR_SLIDER_CURSOR, 3577 NK_COLOR_SLIDER_CURSOR_HOVER, 3578 NK_COLOR_SLIDER_CURSOR_ACTIVE, 3579 NK_COLOR_PROPERTY, 3580 NK_COLOR_EDIT, 3581 NK_COLOR_EDIT_CURSOR, 3582 NK_COLOR_COMBO, 3583 NK_COLOR_CHART, 3584 NK_COLOR_CHART_COLOR, 3585 NK_COLOR_CHART_COLOR_HIGHLIGHT, 3586 NK_COLOR_SCROLLBAR, 3587 NK_COLOR_SCROLLBAR_CURSOR, 3588 NK_COLOR_SCROLLBAR_CURSOR_HOVER, 3589 NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 3590 NK_COLOR_TAB_HEADER, 3591 NK_COLOR_COUNT 3592 }; 3593 enum nk_style_cursor { 3594 NK_CURSOR_ARROW, 3595 NK_CURSOR_TEXT, 3596 NK_CURSOR_MOVE, 3597 NK_CURSOR_RESIZE_VERTICAL, 3598 NK_CURSOR_RESIZE_HORIZONTAL, 3599 NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT, 3600 NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT, 3601 NK_CURSOR_COUNT 3602 }; 3603 NK_API void nk_style_default(struct nk_context*); 3604 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*); 3605 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*); 3606 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*); 3607 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors); 3608 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*); 3609 NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor); 3610 NK_API void nk_style_show_cursor(struct nk_context*); 3611 NK_API void nk_style_hide_cursor(struct nk_context*); 3612 3613 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*); 3614 NK_API int nk_style_push_float(struct nk_context*, float*, float); 3615 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2); 3616 NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item); 3617 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags); 3618 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color); 3619 3620 NK_API int nk_style_pop_font(struct nk_context*); 3621 NK_API int nk_style_pop_float(struct nk_context*); 3622 NK_API int nk_style_pop_vec2(struct nk_context*); 3623 NK_API int nk_style_pop_style_item(struct nk_context*); 3624 NK_API int nk_style_pop_flags(struct nk_context*); 3625 NK_API int nk_style_pop_color(struct nk_context*); 3626 /* ============================================================================= 3627 * 3628 * COLOR 3629 * 3630 * ============================================================================= */ 3631 NK_API struct nk_color nk_rgb(int r, int g, int b); 3632 NK_API struct nk_color nk_rgb_iv(const int *rgb); 3633 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb); 3634 NK_API struct nk_color nk_rgb_f(float r, float g, float b); 3635 NK_API struct nk_color nk_rgb_fv(const float *rgb); 3636 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c); 3637 NK_API struct nk_color nk_rgb_hex(const char *rgb); 3638 3639 NK_API struct nk_color nk_rgba(int r, int g, int b, int a); 3640 NK_API struct nk_color nk_rgba_u32(nk_uint); 3641 NK_API struct nk_color nk_rgba_iv(const int *rgba); 3642 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba); 3643 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a); 3644 NK_API struct nk_color nk_rgba_fv(const float *rgba); 3645 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c); 3646 NK_API struct nk_color nk_rgba_hex(const char *rgb); 3647 3648 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a); 3649 NK_API struct nk_colorf nk_hsva_colorfv(float *c); 3650 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in); 3651 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in); 3652 3653 NK_API struct nk_color nk_hsv(int h, int s, int v); 3654 NK_API struct nk_color nk_hsv_iv(const int *hsv); 3655 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv); 3656 NK_API struct nk_color nk_hsv_f(float h, float s, float v); 3657 NK_API struct nk_color nk_hsv_fv(const float *hsv); 3658 3659 NK_API struct nk_color nk_hsva(int h, int s, int v, int a); 3660 NK_API struct nk_color nk_hsva_iv(const int *hsva); 3661 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva); 3662 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a); 3663 NK_API struct nk_color nk_hsva_fv(const float *hsva); 3664 3665 /* color (conversion nuklear --> user) */ 3666 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color); 3667 NK_API void nk_color_fv(float *rgba_out, struct nk_color); 3668 NK_API struct nk_colorf nk_color_cf(struct nk_color); 3669 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color); 3670 NK_API void nk_color_dv(double *rgba_out, struct nk_color); 3671 3672 NK_API nk_uint nk_color_u32(struct nk_color); 3673 NK_API void nk_color_hex_rgba(char *output, struct nk_color); 3674 NK_API void nk_color_hex_rgb(char *output, struct nk_color); 3675 3676 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color); 3677 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color); 3678 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color); 3679 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color); 3680 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color); 3681 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color); 3682 3683 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color); 3684 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color); 3685 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color); 3686 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color); 3687 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color); 3688 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color); 3689 /* ============================================================================= 3690 * 3691 * IMAGE 3692 * 3693 * ============================================================================= */ 3694 NK_API nk_handle nk_handle_ptr(void*); 3695 NK_API nk_handle nk_handle_id(int); 3696 NK_API struct nk_image nk_image_handle(nk_handle); 3697 NK_API struct nk_image nk_image_ptr(void*); 3698 NK_API struct nk_image nk_image_id(int); 3699 NK_API int nk_image_is_subimage(const struct nk_image* img); 3700 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region); 3701 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region); 3702 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region); 3703 /* ============================================================================= 3704 * 3705 * MATH 3706 * 3707 * ============================================================================= */ 3708 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed); 3709 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading); 3710 3711 NK_API struct nk_vec2 nk_vec2(float x, float y); 3712 NK_API struct nk_vec2 nk_vec2i(int x, int y); 3713 NK_API struct nk_vec2 nk_vec2v(const float *xy); 3714 NK_API struct nk_vec2 nk_vec2iv(const int *xy); 3715 3716 NK_API struct nk_rect nk_get_null_rect(void); 3717 NK_API struct nk_rect nk_rect(float x, float y, float w, float h); 3718 NK_API struct nk_rect nk_recti(int x, int y, int w, int h); 3719 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size); 3720 NK_API struct nk_rect nk_rectv(const float *xywh); 3721 NK_API struct nk_rect nk_rectiv(const int *xywh); 3722 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect); 3723 NK_API struct nk_vec2 nk_rect_size(struct nk_rect); 3724 /* ============================================================================= 3725 * 3726 * STRING 3727 * 3728 * ============================================================================= */ 3729 NK_API int nk_strlen(const char *str); 3730 NK_API int nk_stricmp(const char *s1, const char *s2); 3731 NK_API int nk_stricmpn(const char *s1, const char *s2, int n); 3732 NK_API int nk_strtoi(const char *str, const char **endptr); 3733 NK_API float nk_strtof(const char *str, const char **endptr); 3734 NK_API double nk_strtod(const char *str, const char **endptr); 3735 NK_API int nk_strfilter(const char *text, const char *regexp); 3736 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score); 3737 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score); 3738 /* ============================================================================= 3739 * 3740 * UTF-8 3741 * 3742 * ============================================================================= */ 3743 NK_API int nk_utf_decode(const char*, nk_rune*, int); 3744 NK_API int nk_utf_encode(nk_rune, char*, int); 3745 NK_API int nk_utf_len(const char*, int byte_len); 3746 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len); 3747 /* =============================================================== 3748 * 3749 * FONT 3750 * 3751 * ===============================================================*/ 3752 /* Font handling in this library was designed to be quite customizable and lets 3753 you decide what you want to use and what you want to provide. There are three 3754 different ways to use the font atlas. The first two will use your font 3755 handling scheme and only requires essential data to run nuklear. The next 3756 slightly more advanced features is font handling with vertex buffer output. 3757 Finally the most complex API wise is using nuklear's font baking API. 3758 3759 1.) Using your own implementation without vertex buffer output 3760 -------------------------------------------------------------- 3761 So first up the easiest way to do font handling is by just providing a 3762 `nk_user_font` struct which only requires the height in pixel of the used 3763 font and a callback to calculate the width of a string. This way of handling 3764 fonts is best fitted for using the normal draw shape command API where you 3765 do all the text drawing yourself and the library does not require any kind 3766 of deeper knowledge about which font handling mechanism you use. 3767 IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist 3768 over the complete life time! I know this sucks but it is currently the only 3769 way to switch between fonts. 3770 3771 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3772 { 3773 your_font_type *type = handle.ptr; 3774 float text_width = ...; 3775 return text_width; 3776 } 3777 3778 struct nk_user_font font; 3779 font.userdata.ptr = &your_font_class_or_struct; 3780 font.height = your_font_height; 3781 font.width = your_text_width_calculation; 3782 3783 struct nk_context ctx; 3784 nk_init_default(&ctx, &font); 3785 3786 2.) Using your own implementation with vertex buffer output 3787 -------------------------------------------------------------- 3788 While the first approach works fine if you don't want to use the optional 3789 vertex buffer output it is not enough if you do. To get font handling working 3790 for these cases you have to provide two additional parameters inside the 3791 `nk_user_font`. First a texture atlas handle used to draw text as subimages 3792 of a bigger font atlas texture and a callback to query a character's glyph 3793 information (offset, size, ...). So it is still possible to provide your own 3794 font and use the vertex buffer output. 3795 3796 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3797 { 3798 your_font_type *type = handle.ptr; 3799 float text_width = ...; 3800 return text_width; 3801 } 3802 void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 3803 { 3804 your_font_type *type = handle.ptr; 3805 glyph.width = ...; 3806 glyph.height = ...; 3807 glyph.xadvance = ...; 3808 glyph.uv[0].x = ...; 3809 glyph.uv[0].y = ...; 3810 glyph.uv[1].x = ...; 3811 glyph.uv[1].y = ...; 3812 glyph.offset.x = ...; 3813 glyph.offset.y = ...; 3814 } 3815 3816 struct nk_user_font font; 3817 font.userdata.ptr = &your_font_class_or_struct; 3818 font.height = your_font_height; 3819 font.width = your_text_width_calculation; 3820 font.query = query_your_font_glyph; 3821 font.texture.id = your_font_texture; 3822 3823 struct nk_context ctx; 3824 nk_init_default(&ctx, &font); 3825 3826 3.) Nuklear font baker 3827 ------------------------------------ 3828 The final approach if you do not have a font handling functionality or don't 3829 want to use it in this library is by using the optional font baker. 3830 The font baker APIs can be used to create a font plus font atlas texture 3831 and can be used with or without the vertex buffer output. 3832 3833 It still uses the `nk_user_font` struct and the two different approaches 3834 previously stated still work. The font baker is not located inside 3835 `nk_context` like all other systems since it can be understood as more of 3836 an extension to nuklear and does not really depend on any `nk_context` state. 3837 3838 Font baker need to be initialized first by one of the nk_font_atlas_init_xxx 3839 functions. If you don't care about memory just call the default version 3840 `nk_font_atlas_init_default` which will allocate all memory from the standard library. 3841 If you want to control memory allocation but you don't care if the allocated 3842 memory is temporary and therefore can be freed directly after the baking process 3843 is over or permanent you can call `nk_font_atlas_init`. 3844 3845 After successfully initializing the font baker you can add Truetype(.ttf) fonts from 3846 different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`. 3847 functions. Adding font will permanently store each font, font config and ttf memory block(!) 3848 inside the font atlas and allows to reuse the font atlas. If you don't want to reuse 3849 the font baker by for example adding additional fonts you can call 3850 `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end). 3851 3852 As soon as you added all fonts you wanted you can now start the baking process 3853 for every selected glyph to image by calling `nk_font_atlas_bake`. 3854 The baking process returns image memory, width and height which can be used to 3855 either create your own image object or upload it to any graphics library. 3856 No matter which case you finally have to call `nk_font_atlas_end` which 3857 will free all temporary memory including the font atlas image so make sure 3858 you created our texture beforehand. `nk_font_atlas_end` requires a handle 3859 to your font texture or object and optionally fills a `struct nk_draw_null_texture` 3860 which can be used for the optional vertex output. If you don't want it just 3861 set the argument to `NULL`. 3862 3863 At this point you are done and if you don't want to reuse the font atlas you 3864 can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration 3865 memory. Finally if you don't use the font atlas and any of it's fonts anymore 3866 you need to call `nk_font_atlas_clear` to free all memory still being used. 3867 3868 struct nk_font_atlas atlas; 3869 nk_font_atlas_init_default(&atlas); 3870 nk_font_atlas_begin(&atlas); 3871 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0); 3872 nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0); 3873 const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32); 3874 nk_font_atlas_end(&atlas, nk_handle_id(texture), 0); 3875 3876 struct nk_context ctx; 3877 nk_init_default(&ctx, &font->handle); 3878 while (1) { 3879 3880 } 3881 nk_font_atlas_clear(&atlas); 3882 3883 The font baker API is probably the most complex API inside this library and 3884 I would suggest reading some of my examples `example/` to get a grip on how 3885 to use the font atlas. There are a number of details I left out. For example 3886 how to merge fonts, configure a font with `nk_font_config` to use other languages, 3887 use another texture coordinate format and a lot more: 3888 3889 struct nk_font_config cfg = nk_font_config(font_pixel_height); 3890 cfg.merge_mode = nk_false or nk_true; 3891 cfg.range = nk_font_korean_glyph_ranges(); 3892 cfg.coord_type = NK_COORD_PIXEL; 3893 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg); 3894 3895 */ 3896 struct nk_user_font_glyph; 3897 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len); 3898 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height, 3899 struct nk_user_font_glyph *glyph, 3900 nk_rune codepoint, nk_rune next_codepoint); 3901 3902 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT) 3903 struct nk_user_font_glyph { 3904 struct nk_vec2 uv[2]; 3905 /* texture coordinates */ 3906 struct nk_vec2 offset; 3907 /* offset between top left and glyph */ 3908 float width, height; 3909 /* size of the glyph */ 3910 float xadvance; 3911 /* offset to the next glyph */ 3912 }; 3913 #endif 3914 3915 struct nk_user_font { 3916 nk_handle userdata; 3917 /* user provided font handle */ 3918 float height; 3919 /* max height of the font */ 3920 nk_text_width_f width; 3921 /* font string width in pixel callback */ 3922 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 3923 nk_query_font_glyph_f query; 3924 /* font glyph callback to query drawing info */ 3925 nk_handle texture; 3926 /* texture handle to the used font atlas or texture */ 3927 #endif 3928 }; 3929 3930 #ifdef NK_INCLUDE_FONT_BAKING 3931 enum nk_font_coord_type { 3932 NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */ 3933 NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */ 3934 }; 3935 3936 struct nk_font; 3937 struct nk_baked_font { 3938 float height; 3939 /* height of the font */ 3940 float ascent, descent; 3941 /* font glyphs ascent and descent */ 3942 nk_rune glyph_offset; 3943 /* glyph array offset inside the font glyph baking output array */ 3944 nk_rune glyph_count; 3945 /* number of glyphs of this font inside the glyph baking array output */ 3946 const nk_rune *ranges; 3947 /* font codepoint ranges as pairs of (from/to) and 0 as last element */ 3948 }; 3949 3950 struct nk_font_config { 3951 struct nk_font_config *next; 3952 /* NOTE: only used internally */ 3953 void *ttf_blob; 3954 /* pointer to loaded TTF file memory block. 3955 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 3956 nk_size ttf_size; 3957 /* size of the loaded TTF file memory block 3958 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 3959 3960 unsigned char ttf_data_owned_by_atlas; 3961 /* used inside font atlas: default to: 0*/ 3962 unsigned char merge_mode; 3963 /* merges this font into the last font */ 3964 unsigned char pixel_snap; 3965 /* align every character to pixel boundary (if true set oversample (1,1)) */ 3966 unsigned char oversample_v, oversample_h; 3967 /* rasterize at hight quality for sub-pixel position */ 3968 unsigned char padding[3]; 3969 3970 float size; 3971 /* baked pixel height of the font */ 3972 enum nk_font_coord_type coord_type; 3973 /* texture coordinate format with either pixel or UV coordinates */ 3974 struct nk_vec2 spacing; 3975 /* extra pixel spacing between glyphs */ 3976 const nk_rune *range; 3977 /* list of unicode ranges (2 values per range, zero terminated) */ 3978 struct nk_baked_font *font; 3979 /* font to setup in the baking process: NOTE: not needed for font atlas */ 3980 nk_rune fallback_glyph; 3981 /* fallback glyph to use if a given rune is not found */ 3982 struct nk_font_config *n; 3983 struct nk_font_config *p; 3984 }; 3985 3986 struct nk_font_glyph { 3987 nk_rune codepoint; 3988 float xadvance; 3989 float x0, y0, x1, y1, w, h; 3990 float u0, v0, u1, v1; 3991 }; 3992 3993 struct nk_font { 3994 struct nk_font *next; 3995 struct nk_user_font handle; 3996 struct nk_baked_font info; 3997 float scale; 3998 struct nk_font_glyph *glyphs; 3999 const struct nk_font_glyph *fallback; 4000 nk_rune fallback_codepoint; 4001 nk_handle texture; 4002 struct nk_font_config *config; 4003 }; 4004 4005 enum nk_font_atlas_format { 4006 NK_FONT_ATLAS_ALPHA8, 4007 NK_FONT_ATLAS_RGBA32 4008 }; 4009 4010 struct nk_font_atlas { 4011 void *pixel; 4012 int tex_width; 4013 int tex_height; 4014 4015 struct nk_allocator permanent; 4016 struct nk_allocator temporary; 4017 4018 struct nk_recti custom; 4019 struct nk_cursor cursors[NK_CURSOR_COUNT]; 4020 4021 int glyph_count; 4022 struct nk_font_glyph *glyphs; 4023 struct nk_font *default_font; 4024 struct nk_font *fonts; 4025 struct nk_font_config *config; 4026 int font_num; 4027 }; 4028 4029 /* some language glyph codepoint ranges */ 4030 NK_API const nk_rune *nk_font_default_glyph_ranges(void); 4031 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void); 4032 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void); 4033 NK_API const nk_rune *nk_font_korean_glyph_ranges(void); 4034 4035 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4036 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*); 4037 #endif 4038 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*); 4039 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient); 4040 NK_API void nk_font_atlas_begin(struct nk_font_atlas*); 4041 NK_API struct nk_font_config nk_font_config(float pixel_height); 4042 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*); 4043 #ifdef NK_INCLUDE_DEFAULT_FONT 4044 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*); 4045 #endif 4046 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); 4047 #ifdef NK_INCLUDE_STANDARD_IO 4048 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*); 4049 #endif 4050 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*); 4051 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); 4052 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format); 4053 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*); 4054 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode); 4055 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas); 4056 NK_API void nk_font_atlas_clear(struct nk_font_atlas*); 4057 4058 #endif 4059 4060 /* ============================================================== 4061 * 4062 * MEMORY BUFFER 4063 * 4064 * ===============================================================*/ 4065 /* A basic (double)-buffer with linear allocation and resetting as only 4066 freeing policy. The buffer's main purpose is to control all memory management 4067 inside the GUI toolkit and still leave memory control as much as possible in 4068 the hand of the user while also making sure the library is easy to use if 4069 not as much control is needed. 4070 In general all memory inside this library can be provided from the user in 4071 three different ways. 4072 4073 The first way and the one providing most control is by just passing a fixed 4074 size memory block. In this case all control lies in the hand of the user 4075 since he can exactly control where the memory comes from and how much memory 4076 the library should consume. Of course using the fixed size API removes the 4077 ability to automatically resize a buffer if not enough memory is provided so 4078 you have to take over the resizing. While being a fixed sized buffer sounds 4079 quite limiting, it is very effective in this library since the actual memory 4080 consumption is quite stable and has a fixed upper bound for a lot of cases. 4081 4082 If you don't want to think about how much memory the library should allocate 4083 at all time or have a very dynamic UI with unpredictable memory consumption 4084 habits but still want control over memory allocation you can use the dynamic 4085 allocator based API. The allocator consists of two callbacks for allocating 4086 and freeing memory and optional userdata so you can plugin your own allocator. 4087 4088 The final and easiest way can be used by defining 4089 NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory 4090 allocation functions malloc and free and takes over complete control over 4091 memory in this library. 4092 */ 4093 struct nk_memory_status { 4094 void *memory; 4095 unsigned int type; 4096 nk_size size; 4097 nk_size allocated; 4098 nk_size needed; 4099 nk_size calls; 4100 }; 4101 4102 enum nk_allocation_type { 4103 NK_BUFFER_FIXED, 4104 NK_BUFFER_DYNAMIC 4105 }; 4106 4107 enum nk_buffer_allocation_type { 4108 NK_BUFFER_FRONT, 4109 NK_BUFFER_BACK, 4110 NK_BUFFER_MAX 4111 }; 4112 4113 struct nk_buffer_marker { 4114 int active; 4115 nk_size offset; 4116 }; 4117 4118 struct nk_memory {void *ptr;nk_size size;}; 4119 struct nk_buffer { 4120 struct nk_buffer_marker marker[NK_BUFFER_MAX]; 4121 /* buffer marker to free a buffer to a certain offset */ 4122 struct nk_allocator pool; 4123 /* allocator callback for dynamic buffers */ 4124 enum nk_allocation_type type; 4125 /* memory management type */ 4126 struct nk_memory memory; 4127 /* memory and size of the current memory block */ 4128 float grow_factor; 4129 /* growing factor for dynamic memory management */ 4130 nk_size allocated; 4131 /* total amount of memory allocated */ 4132 nk_size needed; 4133 /* totally consumed memory given that enough memory is present */ 4134 nk_size calls; 4135 /* number of allocation calls */ 4136 nk_size size; 4137 /* current size of the buffer */ 4138 }; 4139 4140 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4141 NK_API void nk_buffer_init_default(struct nk_buffer*); 4142 #endif 4143 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size); 4144 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size); 4145 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*); 4146 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align); 4147 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type); 4148 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type); 4149 NK_API void nk_buffer_clear(struct nk_buffer*); 4150 NK_API void nk_buffer_free(struct nk_buffer*); 4151 NK_API void *nk_buffer_memory(struct nk_buffer*); 4152 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*); 4153 NK_API nk_size nk_buffer_total(struct nk_buffer*); 4154 4155 /* ============================================================== 4156 * 4157 * STRING 4158 * 4159 * ===============================================================*/ 4160 /* Basic string buffer which is only used in context with the text editor 4161 * to manage and manipulate dynamic or fixed size string content. This is _NOT_ 4162 * the default string handling method. The only instance you should have any contact 4163 * with this API is if you interact with an `nk_text_edit` object inside one of the 4164 * copy and paste functions and even there only for more advanced cases. */ 4165 struct nk_str { 4166 struct nk_buffer buffer; 4167 int len; /* in codepoints/runes/glyphs */ 4168 }; 4169 4170 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4171 NK_API void nk_str_init_default(struct nk_str*); 4172 #endif 4173 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size); 4174 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size); 4175 NK_API void nk_str_clear(struct nk_str*); 4176 NK_API void nk_str_free(struct nk_str*); 4177 4178 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int); 4179 NK_API int nk_str_append_str_char(struct nk_str*, const char*); 4180 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int); 4181 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*); 4182 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int); 4183 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*); 4184 4185 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int); 4186 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int); 4187 4188 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int); 4189 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*); 4190 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int); 4191 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*); 4192 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int); 4193 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*); 4194 4195 NK_API void nk_str_remove_chars(struct nk_str*, int len); 4196 NK_API void nk_str_remove_runes(struct nk_str *str, int len); 4197 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len); 4198 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len); 4199 4200 NK_API char *nk_str_at_char(struct nk_str*, int pos); 4201 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len); 4202 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos); 4203 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos); 4204 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len); 4205 4206 NK_API char *nk_str_get(struct nk_str*); 4207 NK_API const char *nk_str_get_const(const struct nk_str*); 4208 NK_API int nk_str_len(struct nk_str*); 4209 NK_API int nk_str_len_char(struct nk_str*); 4210 4211 /*=============================================================== 4212 * 4213 * TEXT EDITOR 4214 * 4215 * ===============================================================*/ 4216 /* Editing text in this library is handled by either `nk_edit_string` or 4217 * `nk_edit_buffer`. But like almost everything in this library there are multiple 4218 * ways of doing it and a balance between control and ease of use with memory 4219 * as well as functionality controlled by flags. 4220 * 4221 * This library generally allows three different levels of memory control: 4222 * First of is the most basic way of just providing a simple char array with 4223 * string length. This method is probably the easiest way of handling simple 4224 * user text input. Main upside is complete control over memory while the biggest 4225 * downside in comparison with the other two approaches is missing undo/redo. 4226 * 4227 * For UIs that require undo/redo the second way was created. It is based on 4228 * a fixed size nk_text_edit struct, which has an internal undo/redo stack. 4229 * This is mainly useful if you want something more like a text editor but don't want 4230 * to have a dynamically growing buffer. 4231 * 4232 * The final way is using a dynamically growing nk_text_edit struct, which 4233 * has both a default version if you don't care where memory comes from and an 4234 * allocator version if you do. While the text editor is quite powerful for its 4235 * complexity I would not recommend editing gigabytes of data with it. 4236 * It is rather designed for uses cases which make sense for a GUI library not for 4237 * an full blown text editor. 4238 */ 4239 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT 4240 #define NK_TEXTEDIT_UNDOSTATECOUNT 99 4241 #endif 4242 4243 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT 4244 #define NK_TEXTEDIT_UNDOCHARCOUNT 999 4245 #endif 4246 4247 struct nk_text_edit; 4248 struct nk_clipboard { 4249 nk_handle userdata; 4250 nk_plugin_paste paste; 4251 nk_plugin_copy copy; 4252 }; 4253 4254 struct nk_text_undo_record { 4255 int where; 4256 short insert_length; 4257 short delete_length; 4258 short char_storage; 4259 }; 4260 4261 struct nk_text_undo_state { 4262 struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]; 4263 nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]; 4264 short undo_point; 4265 short redo_point; 4266 short undo_char_point; 4267 short redo_char_point; 4268 }; 4269 4270 enum nk_text_edit_type { 4271 NK_TEXT_EDIT_SINGLE_LINE, 4272 NK_TEXT_EDIT_MULTI_LINE 4273 }; 4274 4275 enum nk_text_edit_mode { 4276 NK_TEXT_EDIT_MODE_VIEW, 4277 NK_TEXT_EDIT_MODE_INSERT, 4278 NK_TEXT_EDIT_MODE_REPLACE 4279 }; 4280 4281 struct nk_text_edit { 4282 struct nk_clipboard clip; 4283 struct nk_str string; 4284 nk_plugin_filter filter; 4285 struct nk_vec2 scrollbar; 4286 4287 int cursor; 4288 int select_start; 4289 int select_end; 4290 unsigned char mode; 4291 unsigned char cursor_at_end_of_line; 4292 unsigned char initialized; 4293 unsigned char has_preferred_x; 4294 unsigned char single_line; 4295 unsigned char active; 4296 unsigned char padding1; 4297 float preferred_x; 4298 struct nk_text_undo_state undo; 4299 }; 4300 4301 /* filter function */ 4302 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode); 4303 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode); 4304 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode); 4305 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode); 4306 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode); 4307 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode); 4308 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode); 4309 4310 /* text editor */ 4311 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4312 NK_API void nk_textedit_init_default(struct nk_text_edit*); 4313 #endif 4314 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size); 4315 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size); 4316 NK_API void nk_textedit_free(struct nk_text_edit*); 4317 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len); 4318 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len); 4319 NK_API void nk_textedit_delete_selection(struct nk_text_edit*); 4320 NK_API void nk_textedit_select_all(struct nk_text_edit*); 4321 NK_API int nk_textedit_cut(struct nk_text_edit*); 4322 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len); 4323 NK_API void nk_textedit_undo(struct nk_text_edit*); 4324 NK_API void nk_textedit_redo(struct nk_text_edit*); 4325 4326 /* =============================================================== 4327 * 4328 * DRAWING 4329 * 4330 * ===============================================================*/ 4331 /* This library was designed to be render backend agnostic so it does 4332 not draw anything to screen. Instead all drawn shapes, widgets 4333 are made of, are buffered into memory and make up a command queue. 4334 Each frame therefore fills the command buffer with draw commands 4335 that then need to be executed by the user and his own render backend. 4336 After that the command buffer needs to be cleared and a new frame can be 4337 started. It is probably important to note that the command buffer is the main 4338 drawing API and the optional vertex buffer API only takes this format and 4339 converts it into a hardware accessible format. 4340 4341 To use the command queue to draw your own widgets you can access the 4342 command buffer of each window by calling `nk_window_get_canvas` after 4343 previously having called `nk_begin`: 4344 4345 void draw_red_rectangle_widget(struct nk_context *ctx) 4346 { 4347 struct nk_command_buffer *canvas; 4348 struct nk_input *input = &ctx->input; 4349 canvas = nk_window_get_canvas(ctx); 4350 4351 struct nk_rect space; 4352 enum nk_widget_layout_states state; 4353 state = nk_widget(&space, ctx); 4354 if (!state) return; 4355 4356 if (state != NK_WIDGET_ROM) 4357 update_your_widget_by_user_input(...); 4358 nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0)); 4359 } 4360 4361 if (nk_begin(...)) { 4362 nk_layout_row_dynamic(ctx, 25, 1); 4363 draw_red_rectangle_widget(ctx); 4364 } 4365 nk_end(..) 4366 4367 Important to know if you want to create your own widgets is the `nk_widget` 4368 call. It allocates space on the panel reserved for this widget to be used, 4369 but also returns the state of the widget space. If your widget is not seen and does 4370 not have to be updated it is '0' and you can just return. If it only has 4371 to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both 4372 update and draw your widget. The reason for separating is to only draw and 4373 update what is actually necessary which is crucial for performance. 4374 */ 4375 enum nk_command_type { 4376 NK_COMMAND_NOP, 4377 NK_COMMAND_SCISSOR, 4378 NK_COMMAND_LINE, 4379 NK_COMMAND_CURVE, 4380 NK_COMMAND_RECT, 4381 NK_COMMAND_RECT_FILLED, 4382 NK_COMMAND_RECT_MULTI_COLOR, 4383 NK_COMMAND_CIRCLE, 4384 NK_COMMAND_CIRCLE_FILLED, 4385 NK_COMMAND_ARC, 4386 NK_COMMAND_ARC_FILLED, 4387 NK_COMMAND_TRIANGLE, 4388 NK_COMMAND_TRIANGLE_FILLED, 4389 NK_COMMAND_POLYGON, 4390 NK_COMMAND_POLYGON_FILLED, 4391 NK_COMMAND_POLYLINE, 4392 NK_COMMAND_TEXT, 4393 NK_COMMAND_IMAGE, 4394 NK_COMMAND_CUSTOM 4395 }; 4396 4397 /* command base and header of every command inside the buffer */ 4398 struct nk_command { 4399 enum nk_command_type type; 4400 nk_size next; 4401 #ifdef NK_INCLUDE_COMMAND_USERDATA 4402 nk_handle userdata; 4403 #endif 4404 }; 4405 4406 struct nk_command_scissor { 4407 struct nk_command header; 4408 short x, y; 4409 unsigned short w, h; 4410 }; 4411 4412 struct nk_command_line { 4413 struct nk_command header; 4414 unsigned short line_thickness; 4415 struct nk_vec2i begin; 4416 struct nk_vec2i end; 4417 struct nk_color color; 4418 }; 4419 4420 struct nk_command_curve { 4421 struct nk_command header; 4422 unsigned short line_thickness; 4423 struct nk_vec2i begin; 4424 struct nk_vec2i end; 4425 struct nk_vec2i ctrl[2]; 4426 struct nk_color color; 4427 }; 4428 4429 struct nk_command_rect { 4430 struct nk_command header; 4431 unsigned short rounding; 4432 unsigned short line_thickness; 4433 short x, y; 4434 unsigned short w, h; 4435 struct nk_color color; 4436 }; 4437 4438 struct nk_command_rect_filled { 4439 struct nk_command header; 4440 unsigned short rounding; 4441 short x, y; 4442 unsigned short w, h; 4443 struct nk_color color; 4444 }; 4445 4446 struct nk_command_rect_multi_color { 4447 struct nk_command header; 4448 short x, y; 4449 unsigned short w, h; 4450 struct nk_color left; 4451 struct nk_color top; 4452 struct nk_color bottom; 4453 struct nk_color right; 4454 }; 4455 4456 struct nk_command_triangle { 4457 struct nk_command header; 4458 unsigned short line_thickness; 4459 struct nk_vec2i a; 4460 struct nk_vec2i b; 4461 struct nk_vec2i c; 4462 struct nk_color color; 4463 }; 4464 4465 struct nk_command_triangle_filled { 4466 struct nk_command header; 4467 struct nk_vec2i a; 4468 struct nk_vec2i b; 4469 struct nk_vec2i c; 4470 struct nk_color color; 4471 }; 4472 4473 struct nk_command_circle { 4474 struct nk_command header; 4475 short x, y; 4476 unsigned short line_thickness; 4477 unsigned short w, h; 4478 struct nk_color color; 4479 }; 4480 4481 struct nk_command_circle_filled { 4482 struct nk_command header; 4483 short x, y; 4484 unsigned short w, h; 4485 struct nk_color color; 4486 }; 4487 4488 struct nk_command_arc { 4489 struct nk_command header; 4490 short cx, cy; 4491 unsigned short r; 4492 unsigned short line_thickness; 4493 float a[2]; 4494 struct nk_color color; 4495 }; 4496 4497 struct nk_command_arc_filled { 4498 struct nk_command header; 4499 short cx, cy; 4500 unsigned short r; 4501 float a[2]; 4502 struct nk_color color; 4503 }; 4504 4505 struct nk_command_polygon { 4506 struct nk_command header; 4507 struct nk_color color; 4508 unsigned short line_thickness; 4509 unsigned short point_count; 4510 struct nk_vec2i points[1]; 4511 }; 4512 4513 struct nk_command_polygon_filled { 4514 struct nk_command header; 4515 struct nk_color color; 4516 unsigned short point_count; 4517 struct nk_vec2i points[1]; 4518 }; 4519 4520 struct nk_command_polyline { 4521 struct nk_command header; 4522 struct nk_color color; 4523 unsigned short line_thickness; 4524 unsigned short point_count; 4525 struct nk_vec2i points[1]; 4526 }; 4527 4528 struct nk_command_image { 4529 struct nk_command header; 4530 short x, y; 4531 unsigned short w, h; 4532 struct nk_image img; 4533 struct nk_color col; 4534 }; 4535 4536 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y, 4537 unsigned short w, unsigned short h, nk_handle callback_data); 4538 struct nk_command_custom { 4539 struct nk_command header; 4540 short x, y; 4541 unsigned short w, h; 4542 nk_handle callback_data; 4543 nk_command_custom_callback callback; 4544 }; 4545 4546 struct nk_command_text { 4547 struct nk_command header; 4548 const struct nk_user_font *font; 4549 struct nk_color background; 4550 struct nk_color foreground; 4551 short x, y; 4552 unsigned short w, h; 4553 float height; 4554 int length; 4555 char string[1]; 4556 }; 4557 4558 enum nk_command_clipping { 4559 NK_CLIPPING_OFF = nk_false, 4560 NK_CLIPPING_ON = nk_true 4561 }; 4562 4563 struct nk_command_buffer { 4564 struct nk_buffer *base; 4565 struct nk_rect clip; 4566 int use_clipping; 4567 nk_handle userdata; 4568 nk_size begin, end, last; 4569 }; 4570 4571 /* shape outlines */ 4572 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); 4573 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color); 4574 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color); 4575 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color); 4576 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); 4577 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color); 4578 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col); 4579 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color); 4580 4581 /* filled shades */ 4582 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color); 4583 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); 4584 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color); 4585 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); 4586 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); 4587 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color); 4588 4589 /* misc */ 4590 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color); 4591 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); 4592 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect); 4593 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr); 4594 4595 /* =============================================================== 4596 * 4597 * INPUT 4598 * 4599 * ===============================================================*/ 4600 struct nk_mouse_button { 4601 int down; 4602 unsigned int clicked; 4603 struct nk_vec2 clicked_pos; 4604 }; 4605 struct nk_mouse { 4606 struct nk_mouse_button buttons[NK_BUTTON_MAX]; 4607 struct nk_vec2 pos; 4608 struct nk_vec2 prev; 4609 struct nk_vec2 delta; 4610 struct nk_vec2 scroll_delta; 4611 unsigned char grab; 4612 unsigned char grabbed; 4613 unsigned char ungrab; 4614 }; 4615 4616 struct nk_key { 4617 int down; 4618 unsigned int clicked; 4619 }; 4620 struct nk_keyboard { 4621 struct nk_key keys[NK_KEY_MAX]; 4622 char text[NK_INPUT_MAX]; 4623 int text_len; 4624 }; 4625 4626 struct nk_input { 4627 struct nk_keyboard keyboard; 4628 struct nk_mouse mouse; 4629 }; 4630 4631 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons); 4632 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4633 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down); 4634 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4635 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); 4636 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect); 4637 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect); 4638 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect); 4639 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect); 4640 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons); 4641 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons); 4642 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons); 4643 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys); 4644 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys); 4645 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys); 4646 4647 /* =============================================================== 4648 * 4649 * DRAW LIST 4650 * 4651 * ===============================================================*/ 4652 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 4653 /* The optional vertex buffer draw list provides a 2D drawing context 4654 with antialiasing functionality which takes basic filled or outlined shapes 4655 or a path and outputs vertexes, elements and draw commands. 4656 The actual draw list API is not required to be used directly while using this 4657 library since converting the default library draw command output is done by 4658 just calling `nk_convert` but I decided to still make this library accessible 4659 since it can be useful. 4660 4661 The draw list is based on a path buffering and polygon and polyline 4662 rendering API which allows a lot of ways to draw 2D content to screen. 4663 In fact it is probably more powerful than needed but allows even more crazy 4664 things than this library provides by default. 4665 */ 4666 #ifdef NK_UINT_DRAW_INDEX 4667 typedef nk_uint nk_draw_index; 4668 #else 4669 typedef nk_ushort nk_draw_index; 4670 #endif 4671 enum nk_draw_list_stroke { 4672 NK_STROKE_OPEN = nk_false, 4673 /* build up path has no connection back to the beginning */ 4674 NK_STROKE_CLOSED = nk_true 4675 /* build up path has a connection back to the beginning */ 4676 }; 4677 4678 enum nk_draw_vertex_layout_attribute { 4679 NK_VERTEX_POSITION, 4680 NK_VERTEX_COLOR, 4681 NK_VERTEX_TEXCOORD, 4682 NK_VERTEX_ATTRIBUTE_COUNT 4683 }; 4684 4685 enum nk_draw_vertex_layout_format { 4686 NK_FORMAT_SCHAR, 4687 NK_FORMAT_SSHORT, 4688 NK_FORMAT_SINT, 4689 NK_FORMAT_UCHAR, 4690 NK_FORMAT_USHORT, 4691 NK_FORMAT_UINT, 4692 NK_FORMAT_FLOAT, 4693 NK_FORMAT_DOUBLE, 4694 4695 NK_FORMAT_COLOR_BEGIN, 4696 NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN, 4697 NK_FORMAT_R16G15B16, 4698 NK_FORMAT_R32G32B32, 4699 4700 NK_FORMAT_R8G8B8A8, 4701 NK_FORMAT_B8G8R8A8, 4702 NK_FORMAT_R16G15B16A16, 4703 NK_FORMAT_R32G32B32A32, 4704 NK_FORMAT_R32G32B32A32_FLOAT, 4705 NK_FORMAT_R32G32B32A32_DOUBLE, 4706 4707 NK_FORMAT_RGB32, 4708 NK_FORMAT_RGBA32, 4709 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32, 4710 NK_FORMAT_COUNT 4711 }; 4712 4713 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0 4714 struct nk_draw_vertex_layout_element { 4715 enum nk_draw_vertex_layout_attribute attribute; 4716 enum nk_draw_vertex_layout_format format; 4717 nk_size offset; 4718 }; 4719 4720 struct nk_draw_command { 4721 unsigned int elem_count; 4722 /* number of elements in the current draw batch */ 4723 struct nk_rect clip_rect; 4724 /* current screen clipping rectangle */ 4725 nk_handle texture; 4726 /* current texture to set */ 4727 #ifdef NK_INCLUDE_COMMAND_USERDATA 4728 nk_handle userdata; 4729 #endif 4730 }; 4731 4732 struct nk_draw_list { 4733 struct nk_rect clip_rect; 4734 struct nk_vec2 circle_vtx[12]; 4735 struct nk_convert_config config; 4736 4737 struct nk_buffer *buffer; 4738 struct nk_buffer *vertices; 4739 struct nk_buffer *elements; 4740 4741 unsigned int element_count; 4742 unsigned int vertex_count; 4743 unsigned int cmd_count; 4744 nk_size cmd_offset; 4745 4746 unsigned int path_count; 4747 unsigned int path_offset; 4748 4749 enum nk_anti_aliasing line_AA; 4750 enum nk_anti_aliasing shape_AA; 4751 4752 #ifdef NK_INCLUDE_COMMAND_USERDATA 4753 nk_handle userdata; 4754 #endif 4755 }; 4756 4757 /* draw list */ 4758 NK_API void nk_draw_list_init(struct nk_draw_list*); 4759 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); 4760 4761 /* drawing */ 4762 #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)) 4763 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*); 4764 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*); 4765 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*); 4766 4767 /* path */ 4768 NK_API void nk_draw_list_path_clear(struct nk_draw_list*); 4769 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos); 4770 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); 4771 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); 4772 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding); 4773 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); 4774 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color); 4775 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness); 4776 4777 /* stroke */ 4778 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); 4779 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness); 4780 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); 4781 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); 4782 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); 4783 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); 4784 4785 /* fill */ 4786 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding); 4787 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); 4788 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); 4789 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); 4790 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); 4791 4792 /* misc */ 4793 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color); 4794 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); 4795 #ifdef NK_INCLUDE_COMMAND_USERDATA 4796 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata); 4797 #endif 4798 4799 #endif 4800 4801 /* =============================================================== 4802 * 4803 * GUI 4804 * 4805 * ===============================================================*/ 4806 enum nk_style_item_type { 4807 NK_STYLE_ITEM_COLOR, 4808 NK_STYLE_ITEM_IMAGE 4809 }; 4810 4811 union nk_style_item_data { 4812 struct nk_image image; 4813 struct nk_color color; 4814 }; 4815 4816 struct nk_style_item { 4817 enum nk_style_item_type type; 4818 union nk_style_item_data data; 4819 }; 4820 4821 struct nk_style_text { 4822 struct nk_color color; 4823 struct nk_vec2 padding; 4824 }; 4825 4826 struct nk_style_button { 4827 /* background */ 4828 struct nk_style_item normal; 4829 struct nk_style_item hover; 4830 struct nk_style_item active; 4831 struct nk_color border_color; 4832 4833 /* text */ 4834 struct nk_color text_background; 4835 struct nk_color text_normal; 4836 struct nk_color text_hover; 4837 struct nk_color text_active; 4838 nk_flags text_alignment; 4839 4840 /* properties */ 4841 float border; 4842 float rounding; 4843 struct nk_vec2 padding; 4844 struct nk_vec2 image_padding; 4845 struct nk_vec2 touch_padding; 4846 4847 /* optional user callbacks */ 4848 nk_handle userdata; 4849 void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata); 4850 void(*draw_end)(struct nk_command_buffer*, nk_handle userdata); 4851 }; 4852 4853 struct nk_style_toggle { 4854 /* background */ 4855 struct nk_style_item normal; 4856 struct nk_style_item hover; 4857 struct nk_style_item active; 4858 struct nk_color border_color; 4859 4860 /* cursor */ 4861 struct nk_style_item cursor_normal; 4862 struct nk_style_item cursor_hover; 4863 4864 /* text */ 4865 struct nk_color text_normal; 4866 struct nk_color text_hover; 4867 struct nk_color text_active; 4868 struct nk_color text_background; 4869 nk_flags text_alignment; 4870 4871 /* properties */ 4872 struct nk_vec2 padding; 4873 struct nk_vec2 touch_padding; 4874 float spacing; 4875 float border; 4876 4877 /* optional user callbacks */ 4878 nk_handle userdata; 4879 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4880 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4881 }; 4882 4883 struct nk_style_selectable { 4884 /* background (inactive) */ 4885 struct nk_style_item normal; 4886 struct nk_style_item hover; 4887 struct nk_style_item pressed; 4888 4889 /* background (active) */ 4890 struct nk_style_item normal_active; 4891 struct nk_style_item hover_active; 4892 struct nk_style_item pressed_active; 4893 4894 /* text color (inactive) */ 4895 struct nk_color text_normal; 4896 struct nk_color text_hover; 4897 struct nk_color text_pressed; 4898 4899 /* text color (active) */ 4900 struct nk_color text_normal_active; 4901 struct nk_color text_hover_active; 4902 struct nk_color text_pressed_active; 4903 struct nk_color text_background; 4904 nk_flags text_alignment; 4905 4906 /* properties */ 4907 float rounding; 4908 struct nk_vec2 padding; 4909 struct nk_vec2 touch_padding; 4910 struct nk_vec2 image_padding; 4911 4912 /* optional user callbacks */ 4913 nk_handle userdata; 4914 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4915 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4916 }; 4917 4918 struct nk_style_slider { 4919 /* background */ 4920 struct nk_style_item normal; 4921 struct nk_style_item hover; 4922 struct nk_style_item active; 4923 struct nk_color border_color; 4924 4925 /* background bar */ 4926 struct nk_color bar_normal; 4927 struct nk_color bar_hover; 4928 struct nk_color bar_active; 4929 struct nk_color bar_filled; 4930 4931 /* cursor */ 4932 struct nk_style_item cursor_normal; 4933 struct nk_style_item cursor_hover; 4934 struct nk_style_item cursor_active; 4935 4936 /* properties */ 4937 float border; 4938 float rounding; 4939 float bar_height; 4940 struct nk_vec2 padding; 4941 struct nk_vec2 spacing; 4942 struct nk_vec2 cursor_size; 4943 4944 /* optional buttons */ 4945 int show_buttons; 4946 struct nk_style_button inc_button; 4947 struct nk_style_button dec_button; 4948 enum nk_symbol_type inc_symbol; 4949 enum nk_symbol_type dec_symbol; 4950 4951 /* optional user callbacks */ 4952 nk_handle userdata; 4953 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4954 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4955 }; 4956 4957 struct nk_style_progress { 4958 /* background */ 4959 struct nk_style_item normal; 4960 struct nk_style_item hover; 4961 struct nk_style_item active; 4962 struct nk_color border_color; 4963 4964 /* cursor */ 4965 struct nk_style_item cursor_normal; 4966 struct nk_style_item cursor_hover; 4967 struct nk_style_item cursor_active; 4968 struct nk_color cursor_border_color; 4969 4970 /* properties */ 4971 float rounding; 4972 float border; 4973 float cursor_border; 4974 float cursor_rounding; 4975 struct nk_vec2 padding; 4976 4977 /* optional user callbacks */ 4978 nk_handle userdata; 4979 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4980 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4981 }; 4982 4983 struct nk_style_scrollbar { 4984 /* background */ 4985 struct nk_style_item normal; 4986 struct nk_style_item hover; 4987 struct nk_style_item active; 4988 struct nk_color border_color; 4989 4990 /* cursor */ 4991 struct nk_style_item cursor_normal; 4992 struct nk_style_item cursor_hover; 4993 struct nk_style_item cursor_active; 4994 struct nk_color cursor_border_color; 4995 4996 /* properties */ 4997 float border; 4998 float rounding; 4999 float border_cursor; 5000 float rounding_cursor; 5001 struct nk_vec2 padding; 5002 5003 /* optional buttons */ 5004 int show_buttons; 5005 struct nk_style_button inc_button; 5006 struct nk_style_button dec_button; 5007 enum nk_symbol_type inc_symbol; 5008 enum nk_symbol_type dec_symbol; 5009 5010 /* optional user callbacks */ 5011 nk_handle userdata; 5012 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5013 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5014 }; 5015 5016 struct nk_style_edit { 5017 /* background */ 5018 struct nk_style_item normal; 5019 struct nk_style_item hover; 5020 struct nk_style_item active; 5021 struct nk_color border_color; 5022 struct nk_style_scrollbar scrollbar; 5023 5024 /* cursor */ 5025 struct nk_color cursor_normal; 5026 struct nk_color cursor_hover; 5027 struct nk_color cursor_text_normal; 5028 struct nk_color cursor_text_hover; 5029 5030 /* text (unselected) */ 5031 struct nk_color text_normal; 5032 struct nk_color text_hover; 5033 struct nk_color text_active; 5034 5035 /* text (selected) */ 5036 struct nk_color selected_normal; 5037 struct nk_color selected_hover; 5038 struct nk_color selected_text_normal; 5039 struct nk_color selected_text_hover; 5040 5041 /* properties */ 5042 float border; 5043 float rounding; 5044 float cursor_size; 5045 struct nk_vec2 scrollbar_size; 5046 struct nk_vec2 padding; 5047 float row_padding; 5048 }; 5049 5050 struct nk_style_property { 5051 /* background */ 5052 struct nk_style_item normal; 5053 struct nk_style_item hover; 5054 struct nk_style_item active; 5055 struct nk_color border_color; 5056 5057 /* text */ 5058 struct nk_color label_normal; 5059 struct nk_color label_hover; 5060 struct nk_color label_active; 5061 5062 /* symbols */ 5063 enum nk_symbol_type sym_left; 5064 enum nk_symbol_type sym_right; 5065 5066 /* properties */ 5067 float border; 5068 float rounding; 5069 struct nk_vec2 padding; 5070 5071 struct nk_style_edit edit; 5072 struct nk_style_button inc_button; 5073 struct nk_style_button dec_button; 5074 5075 /* optional user callbacks */ 5076 nk_handle userdata; 5077 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5078 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5079 }; 5080 5081 struct nk_style_chart { 5082 /* colors */ 5083 struct nk_style_item background; 5084 struct nk_color border_color; 5085 struct nk_color selected_color; 5086 struct nk_color color; 5087 5088 /* properties */ 5089 float border; 5090 float rounding; 5091 struct nk_vec2 padding; 5092 }; 5093 5094 struct nk_style_combo { 5095 /* background */ 5096 struct nk_style_item normal; 5097 struct nk_style_item hover; 5098 struct nk_style_item active; 5099 struct nk_color border_color; 5100 5101 /* label */ 5102 struct nk_color label_normal; 5103 struct nk_color label_hover; 5104 struct nk_color label_active; 5105 5106 /* symbol */ 5107 struct nk_color symbol_normal; 5108 struct nk_color symbol_hover; 5109 struct nk_color symbol_active; 5110 5111 /* button */ 5112 struct nk_style_button button; 5113 enum nk_symbol_type sym_normal; 5114 enum nk_symbol_type sym_hover; 5115 enum nk_symbol_type sym_active; 5116 5117 /* properties */ 5118 float border; 5119 float rounding; 5120 struct nk_vec2 content_padding; 5121 struct nk_vec2 button_padding; 5122 struct nk_vec2 spacing; 5123 }; 5124 5125 struct nk_style_tab { 5126 /* background */ 5127 struct nk_style_item background; 5128 struct nk_color border_color; 5129 struct nk_color text; 5130 5131 /* button */ 5132 struct nk_style_button tab_maximize_button; 5133 struct nk_style_button tab_minimize_button; 5134 struct nk_style_button node_maximize_button; 5135 struct nk_style_button node_minimize_button; 5136 enum nk_symbol_type sym_minimize; 5137 enum nk_symbol_type sym_maximize; 5138 5139 /* properties */ 5140 float border; 5141 float rounding; 5142 float indent; 5143 struct nk_vec2 padding; 5144 struct nk_vec2 spacing; 5145 }; 5146 5147 enum nk_style_header_align { 5148 NK_HEADER_LEFT, 5149 NK_HEADER_RIGHT 5150 }; 5151 struct nk_style_window_header { 5152 /* background */ 5153 struct nk_style_item normal; 5154 struct nk_style_item hover; 5155 struct nk_style_item active; 5156 5157 /* button */ 5158 struct nk_style_button close_button; 5159 struct nk_style_button minimize_button; 5160 enum nk_symbol_type close_symbol; 5161 enum nk_symbol_type minimize_symbol; 5162 enum nk_symbol_type maximize_symbol; 5163 5164 /* title */ 5165 struct nk_color label_normal; 5166 struct nk_color label_hover; 5167 struct nk_color label_active; 5168 5169 /* properties */ 5170 enum nk_style_header_align align; 5171 struct nk_vec2 padding; 5172 struct nk_vec2 label_padding; 5173 struct nk_vec2 spacing; 5174 }; 5175 5176 struct nk_style_window { 5177 struct nk_style_window_header header; 5178 struct nk_style_item fixed_background; 5179 struct nk_color background; 5180 5181 struct nk_color border_color; 5182 struct nk_color popup_border_color; 5183 struct nk_color combo_border_color; 5184 struct nk_color contextual_border_color; 5185 struct nk_color menu_border_color; 5186 struct nk_color group_border_color; 5187 struct nk_color tooltip_border_color; 5188 struct nk_style_item scaler; 5189 5190 float border; 5191 float combo_border; 5192 float contextual_border; 5193 float menu_border; 5194 float group_border; 5195 float tooltip_border; 5196 float popup_border; 5197 float min_row_height_padding; 5198 5199 float rounding; 5200 struct nk_vec2 spacing; 5201 struct nk_vec2 scrollbar_size; 5202 struct nk_vec2 min_size; 5203 5204 struct nk_vec2 padding; 5205 struct nk_vec2 group_padding; 5206 struct nk_vec2 popup_padding; 5207 struct nk_vec2 combo_padding; 5208 struct nk_vec2 contextual_padding; 5209 struct nk_vec2 menu_padding; 5210 struct nk_vec2 tooltip_padding; 5211 }; 5212 5213 struct nk_style { 5214 const struct nk_user_font *font; 5215 const struct nk_cursor *cursors[NK_CURSOR_COUNT]; 5216 const struct nk_cursor *cursor_active; 5217 struct nk_cursor *cursor_last; 5218 int cursor_visible; 5219 5220 struct nk_style_text text; 5221 struct nk_style_button button; 5222 struct nk_style_button contextual_button; 5223 struct nk_style_button menu_button; 5224 struct nk_style_toggle option; 5225 struct nk_style_toggle checkbox; 5226 struct nk_style_selectable selectable; 5227 struct nk_style_slider slider; 5228 struct nk_style_progress progress; 5229 struct nk_style_property property; 5230 struct nk_style_edit edit; 5231 struct nk_style_chart chart; 5232 struct nk_style_scrollbar scrollh; 5233 struct nk_style_scrollbar scrollv; 5234 struct nk_style_tab tab; 5235 struct nk_style_combo combo; 5236 struct nk_style_window window; 5237 }; 5238 5239 NK_API struct nk_style_item nk_style_item_image(struct nk_image img); 5240 NK_API struct nk_style_item nk_style_item_color(struct nk_color); 5241 NK_API struct nk_style_item nk_style_item_hide(void); 5242 5243 /*============================================================== 5244 * PANEL 5245 * =============================================================*/ 5246 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 5247 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16 5248 #endif 5249 #ifndef NK_CHART_MAX_SLOT 5250 #define NK_CHART_MAX_SLOT 4 5251 #endif 5252 5253 enum nk_panel_type { 5254 NK_PANEL_NONE = 0, 5255 NK_PANEL_WINDOW = NK_FLAG(0), 5256 NK_PANEL_GROUP = NK_FLAG(1), 5257 NK_PANEL_POPUP = NK_FLAG(2), 5258 NK_PANEL_CONTEXTUAL = NK_FLAG(4), 5259 NK_PANEL_COMBO = NK_FLAG(5), 5260 NK_PANEL_MENU = NK_FLAG(6), 5261 NK_PANEL_TOOLTIP = NK_FLAG(7) 5262 }; 5263 enum nk_panel_set { 5264 NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP, 5265 NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP, 5266 NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP 5267 }; 5268 5269 struct nk_chart_slot { 5270 enum nk_chart_type type; 5271 struct nk_color color; 5272 struct nk_color highlight; 5273 float min, max, range; 5274 int count; 5275 struct nk_vec2 last; 5276 int index; 5277 }; 5278 5279 struct nk_chart { 5280 int slot; 5281 float x, y, w, h; 5282 struct nk_chart_slot slots[NK_CHART_MAX_SLOT]; 5283 }; 5284 5285 enum nk_panel_row_layout_type { 5286 NK_LAYOUT_DYNAMIC_FIXED = 0, 5287 NK_LAYOUT_DYNAMIC_ROW, 5288 NK_LAYOUT_DYNAMIC_FREE, 5289 NK_LAYOUT_DYNAMIC, 5290 NK_LAYOUT_STATIC_FIXED, 5291 NK_LAYOUT_STATIC_ROW, 5292 NK_LAYOUT_STATIC_FREE, 5293 NK_LAYOUT_STATIC, 5294 NK_LAYOUT_TEMPLATE, 5295 NK_LAYOUT_COUNT 5296 }; 5297 struct nk_row_layout { 5298 enum nk_panel_row_layout_type type; 5299 int index; 5300 float height; 5301 float min_height; 5302 int columns; 5303 const float *ratio; 5304 float item_width; 5305 float item_height; 5306 float item_offset; 5307 float filled; 5308 struct nk_rect item; 5309 int tree_depth; 5310 float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]; 5311 }; 5312 5313 struct nk_popup_buffer { 5314 nk_size begin; 5315 nk_size parent; 5316 nk_size last; 5317 nk_size end; 5318 int active; 5319 }; 5320 5321 struct nk_menu_state { 5322 float x, y, w, h; 5323 struct nk_scroll offset; 5324 }; 5325 5326 struct nk_panel { 5327 enum nk_panel_type type; 5328 nk_flags flags; 5329 struct nk_rect bounds; 5330 nk_uint *offset_x; 5331 nk_uint *offset_y; 5332 float at_x, at_y, max_x; 5333 float footer_height; 5334 float header_height; 5335 float border; 5336 unsigned int has_scrolling; 5337 struct nk_rect clip; 5338 struct nk_menu_state menu; 5339 struct nk_row_layout row; 5340 struct nk_chart chart; 5341 struct nk_command_buffer *buffer; 5342 struct nk_panel *parent; 5343 }; 5344 5345 /*============================================================== 5346 * WINDOW 5347 * =============================================================*/ 5348 #ifndef NK_WINDOW_MAX_NAME 5349 #define NK_WINDOW_MAX_NAME 64 5350 #endif 5351 5352 struct nk_table; 5353 enum nk_window_flags { 5354 NK_WINDOW_PRIVATE = NK_FLAG(11), 5355 NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE, 5356 /* special window type growing up in height while being filled to a certain maximum height */ 5357 NK_WINDOW_ROM = NK_FLAG(12), 5358 /* sets window widgets into a read only mode and does not allow input changes */ 5359 NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT, 5360 /* prevents all interaction caused by input to either window or widgets inside */ 5361 NK_WINDOW_HIDDEN = NK_FLAG(13), 5362 /* Hides window and stops any window interaction and drawing */ 5363 NK_WINDOW_CLOSED = NK_FLAG(14), 5364 /* Directly closes and frees the window at the end of the frame */ 5365 NK_WINDOW_MINIMIZED = NK_FLAG(15), 5366 /* marks the window as minimized */ 5367 NK_WINDOW_REMOVE_ROM = NK_FLAG(16) 5368 /* Removes read only mode at the end of the window */ 5369 }; 5370 5371 struct nk_popup_state { 5372 struct nk_window *win; 5373 enum nk_panel_type type; 5374 struct nk_popup_buffer buf; 5375 nk_hash name; 5376 int active; 5377 unsigned combo_count; 5378 unsigned con_count, con_old; 5379 unsigned active_con; 5380 struct nk_rect header; 5381 }; 5382 5383 struct nk_edit_state { 5384 nk_hash name; 5385 unsigned int seq; 5386 unsigned int old; 5387 int active, prev; 5388 int cursor; 5389 int sel_start; 5390 int sel_end; 5391 struct nk_scroll scrollbar; 5392 unsigned char mode; 5393 unsigned char single_line; 5394 }; 5395 5396 struct nk_property_state { 5397 int active, prev; 5398 char buffer[NK_MAX_NUMBER_BUFFER]; 5399 int length; 5400 int cursor; 5401 int select_start; 5402 int select_end; 5403 nk_hash name; 5404 unsigned int seq; 5405 unsigned int old; 5406 int state; 5407 }; 5408 5409 struct nk_window { 5410 unsigned int seq; 5411 nk_hash name; 5412 char name_string[NK_WINDOW_MAX_NAME]; 5413 nk_flags flags; 5414 5415 struct nk_rect bounds; 5416 struct nk_scroll scrollbar; 5417 struct nk_command_buffer buffer; 5418 struct nk_panel *layout; 5419 float scrollbar_hiding_timer; 5420 5421 /* persistent widget state */ 5422 struct nk_property_state property; 5423 struct nk_popup_state popup; 5424 struct nk_edit_state edit; 5425 unsigned int scrolled; 5426 5427 struct nk_table *tables; 5428 unsigned int table_count; 5429 5430 /* window list hooks */ 5431 struct nk_window *next; 5432 struct nk_window *prev; 5433 struct nk_window *parent; 5434 }; 5435 5436 /*============================================================== 5437 * STACK 5438 * =============================================================*/ 5439 /* The style modifier stack can be used to temporarily change a 5440 * property inside `nk_style`. For example if you want a special 5441 * red button you can temporarily push the old button color onto a stack 5442 * draw the button with a red color and then you just pop the old color 5443 * back from the stack: 5444 * 5445 * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0))); 5446 * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0))); 5447 * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0))); 5448 * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2)); 5449 * 5450 * nk_button(...); 5451 * 5452 * nk_style_pop_style_item(ctx); 5453 * nk_style_pop_style_item(ctx); 5454 * nk_style_pop_style_item(ctx); 5455 * nk_style_pop_vec2(ctx); 5456 * 5457 * Nuklear has a stack for style_items, float properties, vector properties, 5458 * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack 5459 * which can be changed at compile time. 5460 */ 5461 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE 5462 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8 5463 #endif 5464 5465 #ifndef NK_FONT_STACK_SIZE 5466 #define NK_FONT_STACK_SIZE 8 5467 #endif 5468 5469 #ifndef NK_STYLE_ITEM_STACK_SIZE 5470 #define NK_STYLE_ITEM_STACK_SIZE 16 5471 #endif 5472 5473 #ifndef NK_FLOAT_STACK_SIZE 5474 #define NK_FLOAT_STACK_SIZE 32 5475 #endif 5476 5477 #ifndef NK_VECTOR_STACK_SIZE 5478 #define NK_VECTOR_STACK_SIZE 16 5479 #endif 5480 5481 #ifndef NK_FLAGS_STACK_SIZE 5482 #define NK_FLAGS_STACK_SIZE 32 5483 #endif 5484 5485 #ifndef NK_COLOR_STACK_SIZE 5486 #define NK_COLOR_STACK_SIZE 32 5487 #endif 5488 5489 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\ 5490 struct nk_config_stack_##name##_element {\ 5491 prefix##_##type *address;\ 5492 prefix##_##type old_value;\ 5493 } 5494 #define NK_CONFIG_STACK(type,size)\ 5495 struct nk_config_stack_##type {\ 5496 int head;\ 5497 struct nk_config_stack_##type##_element elements[size];\ 5498 } 5499 5500 #define nk_float float 5501 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item); 5502 NK_CONFIGURATION_STACK_TYPE(nk ,float, float); 5503 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2); 5504 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags); 5505 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color); 5506 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*); 5507 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior); 5508 5509 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE); 5510 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE); 5511 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE); 5512 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE); 5513 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE); 5514 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE); 5515 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE); 5516 5517 struct nk_configuration_stacks { 5518 struct nk_config_stack_style_item style_items; 5519 struct nk_config_stack_float floats; 5520 struct nk_config_stack_vec2 vectors; 5521 struct nk_config_stack_flags flags; 5522 struct nk_config_stack_color colors; 5523 struct nk_config_stack_user_font fonts; 5524 struct nk_config_stack_button_behavior button_behaviors; 5525 }; 5526 5527 /*============================================================== 5528 * CONTEXT 5529 * =============================================================*/ 5530 #define NK_VALUE_PAGE_CAPACITY \ 5531 (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2) 5532 5533 struct nk_table { 5534 unsigned int seq; 5535 unsigned int size; 5536 nk_hash keys[NK_VALUE_PAGE_CAPACITY]; 5537 nk_uint values[NK_VALUE_PAGE_CAPACITY]; 5538 struct nk_table *next, *prev; 5539 }; 5540 5541 union nk_page_data { 5542 struct nk_table tbl; 5543 struct nk_panel pan; 5544 struct nk_window win; 5545 }; 5546 5547 struct nk_page_element { 5548 union nk_page_data data; 5549 struct nk_page_element *next; 5550 struct nk_page_element *prev; 5551 }; 5552 5553 struct nk_page { 5554 unsigned int size; 5555 struct nk_page *next; 5556 struct nk_page_element win[1]; 5557 }; 5558 5559 struct nk_pool { 5560 struct nk_allocator alloc; 5561 enum nk_allocation_type type; 5562 unsigned int page_count; 5563 struct nk_page *pages; 5564 struct nk_page_element *freelist; 5565 unsigned capacity; 5566 nk_size size; 5567 nk_size cap; 5568 }; 5569 5570 struct nk_context { 5571 /* public: can be accessed freely */ 5572 struct nk_input input; 5573 struct nk_style style; 5574 struct nk_buffer memory; 5575 struct nk_clipboard clip; 5576 nk_flags last_widget_state; 5577 enum nk_button_behavior button_behavior; 5578 struct nk_configuration_stacks stacks; 5579 float delta_time_seconds; 5580 5581 /* private: 5582 should only be accessed if you 5583 know what you are doing */ 5584 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 5585 struct nk_draw_list draw_list; 5586 #endif 5587 #ifdef NK_INCLUDE_COMMAND_USERDATA 5588 nk_handle userdata; 5589 #endif 5590 /* text editor objects are quite big because of an internal 5591 * undo/redo stack. Therefore it does not make sense to have one for 5592 * each window for temporary use cases, so I only provide *one* instance 5593 * for all windows. This works because the content is cleared anyway */ 5594 struct nk_text_edit text_edit; 5595 /* draw buffer used for overlay drawing operation like cursor */ 5596 struct nk_command_buffer overlay; 5597 5598 /* windows */ 5599 int build; 5600 int use_pool; 5601 struct nk_pool pool; 5602 struct nk_window *begin; 5603 struct nk_window *end; 5604 struct nk_window *active; 5605 struct nk_window *current; 5606 struct nk_page_element *freelist; 5607 unsigned int count; 5608 unsigned int seq; 5609 }; 5610 5611 /* ============================================================== 5612 * MATH 5613 * =============================================================== */ 5614 #define NK_PI 3.141592654f 5615 #define NK_UTF_INVALID 0xFFFD 5616 #define NK_MAX_FLOAT_PRECISION 2 5617 5618 #define NK_UNUSED(x) ((void)(x)) 5619 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x))) 5620 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0]) 5621 #define NK_ABS(a) (((a) < 0) ? -(a) : (a)) 5622 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b)) 5623 #define NK_INBOX(px, py, x, y, w, h)\ 5624 (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h)) 5625 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \ 5626 (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0))) 5627 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\ 5628 (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh)) 5629 5630 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y) 5631 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y) 5632 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y) 5633 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t)) 5634 5635 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i)))) 5636 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i)))) 5637 #define nk_zero_struct(s) nk_zero(&s, sizeof(s)) 5638 5639 /* ============================================================== 5640 * ALIGNMENT 5641 * =============================================================== */ 5642 /* Pointer to Integer type conversion for pointer alignment */ 5643 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/ 5644 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x)) 5645 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x)) 5646 #elif !defined(__GNUC__) /* works for compilers other than LLVM */ 5647 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x]) 5648 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0)) 5649 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */ 5650 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) 5651 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x)) 5652 #else /* generates warning but works */ 5653 # define NK_UINT_TO_PTR(x) ((void*)(x)) 5654 # define NK_PTR_TO_UINT(x) ((nk_size)(x)) 5655 #endif 5656 5657 #define NK_ALIGN_PTR(x, mask)\ 5658 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1)))) 5659 #define NK_ALIGN_PTR_BACK(x, mask)\ 5660 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1)))) 5661 5662 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) 5663 #define NK_CONTAINER_OF(ptr,type,member)\ 5664 (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) 5665 5666 #ifdef __cplusplus 5667 } 5668 #endif 5669 5670 #ifdef __cplusplus 5671 template<typename T> struct nk_alignof; 5672 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};}; 5673 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};}; 5674 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum { 5675 diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};}; 5676 #define NK_ALIGNOF(t) (nk_alignof<t>::value) 5677 #elif defined(_MSC_VER) 5678 #define NK_ALIGNOF(t) (__alignof(t)) 5679 #else 5680 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) 5681 #endif 5682 5683 #endif /* NK_NUKLEAR_H_ */ 5684 5685 #ifdef NK_IMPLEMENTATION 5686 5687 #ifndef NK_INTERNAL_H 5688 #define NK_INTERNAL_H 5689 5690 #ifndef NK_POOL_DEFAULT_CAPACITY 5691 #define NK_POOL_DEFAULT_CAPACITY 16 5692 #endif 5693 5694 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE 5695 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) 5696 #endif 5697 5698 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE 5699 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024) 5700 #endif 5701 5702 /* standard library headers */ 5703 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5704 #include <stdlib.h> /* malloc, free */ 5705 #endif 5706 #ifdef NK_INCLUDE_STANDARD_IO 5707 #include <stdio.h> /* fopen, fclose,... */ 5708 #endif 5709 #ifndef NK_ASSERT 5710 #include <assert.h> 5711 #define NK_ASSERT(expr) assert(expr) 5712 #endif 5713 5714 #ifndef NK_MEMSET 5715 #define NK_MEMSET nk_memset 5716 #endif 5717 #ifndef NK_MEMCPY 5718 #define NK_MEMCPY nk_memcopy 5719 #endif 5720 #ifndef NK_SQRT 5721 #define NK_SQRT nk_sqrt 5722 #endif 5723 #ifndef NK_SIN 5724 #define NK_SIN nk_sin 5725 #endif 5726 #ifndef NK_COS 5727 #define NK_COS nk_cos 5728 #endif 5729 #ifndef NK_STRTOD 5730 #define NK_STRTOD nk_strtod 5731 #endif 5732 #ifndef NK_DTOA 5733 #define NK_DTOA nk_dtoa 5734 #endif 5735 5736 #define NK_DEFAULT (-1) 5737 5738 #ifndef NK_VSNPRINTF 5739 /* If your compiler does support `vsnprintf` I would highly recommend 5740 * defining this to vsnprintf instead since `vsprintf` is basically 5741 * unbelievable unsafe and should *NEVER* be used. But I have to support 5742 * it since C89 only provides this unsafe version. */ 5743 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\ 5744 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 5745 (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\ 5746 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\ 5747 defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE) 5748 #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a) 5749 #else 5750 #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a) 5751 #endif 5752 #endif 5753 5754 #define NK_SCHAR_MIN (-127) 5755 #define NK_SCHAR_MAX 127 5756 #define NK_UCHAR_MIN 0 5757 #define NK_UCHAR_MAX 256 5758 #define NK_SSHORT_MIN (-32767) 5759 #define NK_SSHORT_MAX 32767 5760 #define NK_USHORT_MIN 0 5761 #define NK_USHORT_MAX 65535 5762 #define NK_SINT_MIN (-2147483647) 5763 #define NK_SINT_MAX 2147483647 5764 #define NK_UINT_MIN 0 5765 #define NK_UINT_MAX 4294967295u 5766 5767 /* Make sure correct type size: 5768 * This will fire with a negative subscript error if the type sizes 5769 * are set incorrectly by the compiler, and compile out if not */ 5770 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 5771 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*)); 5772 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 5773 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 5774 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 5775 NK_STATIC_ASSERT(sizeof(nk_short) == 2); 5776 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 5777 NK_STATIC_ASSERT(sizeof(nk_int) == 4); 5778 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 5779 5780 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384}; 5781 #define NK_FLOAT_PRECISION 0.00000000000001 5782 5783 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255}; 5784 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255}; 5785 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255}; 5786 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255}; 5787 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255}; 5788 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255}; 5789 5790 /* widget */ 5791 #define nk_widget_state_reset(s)\ 5792 if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\ 5793 (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\ 5794 else (*(s)) = NK_WIDGET_STATE_INACTIVE; 5795 5796 /* math */ 5797 NK_LIB float nk_inv_sqrt(float n); 5798 NK_LIB float nk_sqrt(float x); 5799 NK_LIB float nk_sin(float x); 5800 NK_LIB float nk_cos(float x); 5801 NK_LIB nk_uint nk_round_up_pow2(nk_uint v); 5802 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount); 5803 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad); 5804 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1); 5805 NK_LIB double nk_pow(double x, int n); 5806 NK_LIB int nk_ifloord(double x); 5807 NK_LIB int nk_ifloorf(float x); 5808 NK_LIB int nk_iceilf(float x); 5809 NK_LIB int nk_log10(double n); 5810 5811 /* util */ 5812 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE}; 5813 NK_LIB int nk_is_lower(int c); 5814 NK_LIB int nk_is_upper(int c); 5815 NK_LIB int nk_to_upper(int c); 5816 NK_LIB int nk_to_lower(int c); 5817 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); 5818 NK_LIB void nk_memset(void *ptr, int c0, nk_size size); 5819 NK_LIB void nk_zero(void *ptr, nk_size size); 5820 NK_LIB char *nk_itoa(char *s, long n); 5821 NK_LIB int nk_string_float_limit(char *string, int prec); 5822 NK_LIB char *nk_dtoa(char *s, double n); 5823 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); 5824 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); 5825 #ifdef NK_INCLUDE_STANDARD_VARARGS 5826 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args); 5827 #endif 5828 #ifdef NK_INCLUDE_STANDARD_IO 5829 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc); 5830 #endif 5831 5832 /* buffer */ 5833 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5834 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size); 5835 NK_LIB void nk_mfree(nk_handle unused, void *ptr); 5836 #endif 5837 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type); 5838 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align); 5839 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size); 5840 5841 /* draw */ 5842 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip); 5843 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b); 5844 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size); 5845 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); 5846 5847 /* buffering */ 5848 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5849 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win); 5850 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win); 5851 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*); 5852 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5853 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w); 5854 NK_LIB void nk_build(struct nk_context *ctx); 5855 5856 /* text editor */ 5857 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter); 5858 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5859 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5860 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); 5861 5862 /* window */ 5863 enum nk_window_insert_location { 5864 NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */ 5865 NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */ 5866 }; 5867 NK_LIB void *nk_create_window(struct nk_context *ctx); 5868 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*); 5869 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win); 5870 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name); 5871 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc); 5872 5873 /* pool */ 5874 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity); 5875 NK_LIB void nk_pool_free(struct nk_pool *pool); 5876 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size); 5877 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool); 5878 5879 /* page-element */ 5880 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx); 5881 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem); 5882 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem); 5883 5884 /* table */ 5885 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx); 5886 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl); 5887 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl); 5888 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl); 5889 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value); 5890 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name); 5891 5892 /* panel */ 5893 NK_LIB void *nk_create_panel(struct nk_context *ctx); 5894 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan); 5895 NK_LIB int nk_panel_has_header(nk_flags flags, const char *title); 5896 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type); 5897 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type); 5898 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type); 5899 NK_LIB int nk_panel_is_sub(enum nk_panel_type type); 5900 NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type); 5901 NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type); 5902 NK_LIB void nk_panel_end(struct nk_context *ctx); 5903 5904 /* layout */ 5905 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns); 5906 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols); 5907 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width); 5908 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win); 5909 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify); 5910 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx); 5911 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx); 5912 5913 /* popup */ 5914 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); 5915 5916 /* text */ 5917 struct nk_text { 5918 struct nk_vec2 padding; 5919 struct nk_color background; 5920 struct nk_color text; 5921 }; 5922 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); 5923 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); 5924 5925 /* button */ 5926 NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior); 5927 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); 5928 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); 5929 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); 5930 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); 5931 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); 5932 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); 5933 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); 5934 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); 5935 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); 5936 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); 5937 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); 5938 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); 5939 5940 /* toggle */ 5941 enum nk_toggle_type { 5942 NK_TOGGLE_CHECK, 5943 NK_TOGGLE_OPTION 5944 }; 5945 NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active); 5946 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); 5947 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); 5948 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); 5949 5950 /* progress */ 5951 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); 5952 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); 5953 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); 5954 5955 /* slider */ 5956 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); 5957 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); 5958 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); 5959 5960 /* scrollbar */ 5961 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); 5962 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); 5963 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); 5964 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); 5965 5966 /* selectable */ 5967 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); 5968 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); 5969 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); 5970 5971 /* edit */ 5972 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); 5973 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); 5974 5975 /* color-picker */ 5976 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); 5977 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); 5978 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); 5979 5980 /* property */ 5981 enum nk_property_status { 5982 NK_PROPERTY_DEFAULT, 5983 NK_PROPERTY_EDIT, 5984 NK_PROPERTY_DRAG 5985 }; 5986 enum nk_property_filter { 5987 NK_FILTER_INT, 5988 NK_FILTER_FLOAT 5989 }; 5990 enum nk_property_kind { 5991 NK_PROPERTY_INT, 5992 NK_PROPERTY_FLOAT, 5993 NK_PROPERTY_DOUBLE 5994 }; 5995 union nk_property { 5996 int i; 5997 float f; 5998 double d; 5999 }; 6000 struct nk_property_variant { 6001 enum nk_property_kind kind; 6002 union nk_property value; 6003 union nk_property min_value; 6004 union nk_property max_value; 6005 union nk_property step; 6006 }; 6007 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step); 6008 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step); 6009 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step); 6010 6011 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); 6012 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); 6013 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); 6014 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); 6015 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); 6016 6017 #endif 6018 6019 6020 6021 6022 6023 /* =============================================================== 6024 * 6025 * MATH 6026 * 6027 * ===============================================================*/ 6028 /* Since nuklear is supposed to work on all systems providing floating point 6029 math without any dependencies I also had to implement my own math functions 6030 for sqrt, sin and cos. Since the actual highly accurate implementations for 6031 the standard library functions are quite complex and I do not need high 6032 precision for my use cases I use approximations. 6033 6034 Sqrt 6035 ---- 6036 For square root nuklear uses the famous fast inverse square root: 6037 https://en.wikipedia.org/wiki/Fast_inverse_square_root with 6038 slightly tweaked magic constant. While on today's hardware it is 6039 probably not faster it is still fast and accurate enough for 6040 nuklear's use cases. IMPORTANT: this requires float format IEEE 754 6041 6042 Sine/Cosine 6043 ----------- 6044 All constants inside both function are generated Remez's minimax 6045 approximations for value range 0...2*PI. The reason why I decided to 6046 approximate exactly that range is that nuklear only needs sine and 6047 cosine to generate circles which only requires that exact range. 6048 In addition I used Remez instead of Taylor for additional precision: 6049 www.lolengine.net/blog/2011/12/21/better-function-approximations. 6050 6051 The tool I used to generate constants for both sine and cosine 6052 (it can actually approximate a lot more functions) can be 6053 found here: www.lolengine.net/wiki/oss/lolremez 6054 */ 6055 NK_LIB float 6056 nk_inv_sqrt(float n) 6057 { 6058 float x2; 6059 const float threehalfs = 1.5f; 6060 union {nk_uint i; float f;} conv = {0}; 6061 conv.f = n; 6062 x2 = n * 0.5f; 6063 conv.i = 0x5f375A84 - (conv.i >> 1); 6064 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f)); 6065 return conv.f; 6066 } 6067 NK_LIB float 6068 nk_sqrt(float x) 6069 { 6070 return x * nk_inv_sqrt(x); 6071 } 6072 NK_LIB float 6073 nk_sin(float x) 6074 { 6075 NK_STORAGE const float a0 = +1.91059300966915117e-31f; 6076 NK_STORAGE const float a1 = +1.00086760103908896f; 6077 NK_STORAGE const float a2 = -1.21276126894734565e-2f; 6078 NK_STORAGE const float a3 = -1.38078780785773762e-1f; 6079 NK_STORAGE const float a4 = -2.67353392911981221e-2f; 6080 NK_STORAGE const float a5 = +2.08026600266304389e-2f; 6081 NK_STORAGE const float a6 = -3.03996055049204407e-3f; 6082 NK_STORAGE const float a7 = +1.38235642404333740e-4f; 6083 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); 6084 } 6085 NK_LIB float 6086 nk_cos(float x) 6087 { 6088 /* New implementation. Also generated using lolremez. */ 6089 /* Old version significantly deviated from expected results. */ 6090 NK_STORAGE const float a0 = 9.9995999154986614e-1f; 6091 NK_STORAGE const float a1 = 1.2548995793001028e-3f; 6092 NK_STORAGE const float a2 = -5.0648546280678015e-1f; 6093 NK_STORAGE const float a3 = 1.2942246466519995e-2f; 6094 NK_STORAGE const float a4 = 2.8668384702547972e-2f; 6095 NK_STORAGE const float a5 = 7.3726485210586547e-3f; 6096 NK_STORAGE const float a6 = -3.8510875386947414e-3f; 6097 NK_STORAGE const float a7 = 4.7196604604366623e-4f; 6098 NK_STORAGE const float a8 = -1.8776444013090451e-5f; 6099 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8))))))); 6100 } 6101 NK_LIB nk_uint 6102 nk_round_up_pow2(nk_uint v) 6103 { 6104 v--; 6105 v |= v >> 1; 6106 v |= v >> 2; 6107 v |= v >> 4; 6108 v |= v >> 8; 6109 v |= v >> 16; 6110 v++; 6111 return v; 6112 } 6113 NK_LIB double 6114 nk_pow(double x, int n) 6115 { 6116 /* check the sign of n */ 6117 double r = 1; 6118 int plus = n >= 0; 6119 n = (plus) ? n : -n; 6120 while (n > 0) { 6121 if ((n & 1) == 1) 6122 r *= x; 6123 n /= 2; 6124 x *= x; 6125 } 6126 return plus ? r : 1.0 / r; 6127 } 6128 NK_LIB int 6129 nk_ifloord(double x) 6130 { 6131 x = (double)((int)x - ((x < 0.0) ? 1 : 0)); 6132 return (int)x; 6133 } 6134 NK_LIB int 6135 nk_ifloorf(float x) 6136 { 6137 x = (float)((int)x - ((x < 0.0f) ? 1 : 0)); 6138 return (int)x; 6139 } 6140 NK_LIB int 6141 nk_iceilf(float x) 6142 { 6143 if (x >= 0) { 6144 int i = (int)x; 6145 return (x > i) ? i+1: i; 6146 } else { 6147 int t = (int)x; 6148 float r = x - (float)t; 6149 return (r > 0.0f) ? t+1: t; 6150 } 6151 } 6152 NK_LIB int 6153 nk_log10(double n) 6154 { 6155 int neg; 6156 int ret; 6157 int exp = 0; 6158 6159 neg = (n < 0) ? 1 : 0; 6160 ret = (neg) ? (int)-n : (int)n; 6161 while ((ret / 10) > 0) { 6162 ret /= 10; 6163 exp++; 6164 } 6165 if (neg) exp = -exp; 6166 return exp; 6167 } 6168 NK_API struct nk_rect 6169 nk_get_null_rect(void) 6170 { 6171 return nk_null_rect; 6172 } 6173 NK_API struct nk_rect 6174 nk_rect(float x, float y, float w, float h) 6175 { 6176 struct nk_rect r; 6177 r.x = x; r.y = y; 6178 r.w = w; r.h = h; 6179 return r; 6180 } 6181 NK_API struct nk_rect 6182 nk_recti(int x, int y, int w, int h) 6183 { 6184 struct nk_rect r; 6185 r.x = (float)x; 6186 r.y = (float)y; 6187 r.w = (float)w; 6188 r.h = (float)h; 6189 return r; 6190 } 6191 NK_API struct nk_rect 6192 nk_recta(struct nk_vec2 pos, struct nk_vec2 size) 6193 { 6194 return nk_rect(pos.x, pos.y, size.x, size.y); 6195 } 6196 NK_API struct nk_rect 6197 nk_rectv(const float *r) 6198 { 6199 return nk_rect(r[0], r[1], r[2], r[3]); 6200 } 6201 NK_API struct nk_rect 6202 nk_rectiv(const int *r) 6203 { 6204 return nk_recti(r[0], r[1], r[2], r[3]); 6205 } 6206 NK_API struct nk_vec2 6207 nk_rect_pos(struct nk_rect r) 6208 { 6209 struct nk_vec2 ret; 6210 ret.x = r.x; ret.y = r.y; 6211 return ret; 6212 } 6213 NK_API struct nk_vec2 6214 nk_rect_size(struct nk_rect r) 6215 { 6216 struct nk_vec2 ret; 6217 ret.x = r.w; ret.y = r.h; 6218 return ret; 6219 } 6220 NK_LIB struct nk_rect 6221 nk_shrink_rect(struct nk_rect r, float amount) 6222 { 6223 struct nk_rect res; 6224 r.w = NK_MAX(r.w, 2 * amount); 6225 r.h = NK_MAX(r.h, 2 * amount); 6226 res.x = r.x + amount; 6227 res.y = r.y + amount; 6228 res.w = r.w - 2 * amount; 6229 res.h = r.h - 2 * amount; 6230 return res; 6231 } 6232 NK_LIB struct nk_rect 6233 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad) 6234 { 6235 r.w = NK_MAX(r.w, 2 * pad.x); 6236 r.h = NK_MAX(r.h, 2 * pad.y); 6237 r.x += pad.x; r.y += pad.y; 6238 r.w -= 2 * pad.x; 6239 r.h -= 2 * pad.y; 6240 return r; 6241 } 6242 NK_API struct nk_vec2 6243 nk_vec2(float x, float y) 6244 { 6245 struct nk_vec2 ret; 6246 ret.x = x; ret.y = y; 6247 return ret; 6248 } 6249 NK_API struct nk_vec2 6250 nk_vec2i(int x, int y) 6251 { 6252 struct nk_vec2 ret; 6253 ret.x = (float)x; 6254 ret.y = (float)y; 6255 return ret; 6256 } 6257 NK_API struct nk_vec2 6258 nk_vec2v(const float *v) 6259 { 6260 return nk_vec2(v[0], v[1]); 6261 } 6262 NK_API struct nk_vec2 6263 nk_vec2iv(const int *v) 6264 { 6265 return nk_vec2i(v[0], v[1]); 6266 } 6267 NK_LIB void 6268 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, 6269 float x1, float y1) 6270 { 6271 NK_ASSERT(a); 6272 NK_ASSERT(clip); 6273 clip->x = NK_MAX(a->x, x0); 6274 clip->y = NK_MAX(a->y, y0); 6275 clip->w = NK_MIN(a->x + a->w, x1) - clip->x; 6276 clip->h = NK_MIN(a->y + a->h, y1) - clip->y; 6277 clip->w = NK_MAX(0, clip->w); 6278 clip->h = NK_MAX(0, clip->h); 6279 } 6280 6281 NK_API void 6282 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, 6283 float pad_x, float pad_y, enum nk_heading direction) 6284 { 6285 float w_half, h_half; 6286 NK_ASSERT(result); 6287 6288 r.w = NK_MAX(2 * pad_x, r.w); 6289 r.h = NK_MAX(2 * pad_y, r.h); 6290 r.w = r.w - 2 * pad_x; 6291 r.h = r.h - 2 * pad_y; 6292 6293 r.x = r.x + pad_x; 6294 r.y = r.y + pad_y; 6295 6296 w_half = r.w / 2.0f; 6297 h_half = r.h / 2.0f; 6298 6299 if (direction == NK_UP) { 6300 result[0] = nk_vec2(r.x + w_half, r.y); 6301 result[1] = nk_vec2(r.x + r.w, r.y + r.h); 6302 result[2] = nk_vec2(r.x, r.y + r.h); 6303 } else if (direction == NK_RIGHT) { 6304 result[0] = nk_vec2(r.x, r.y); 6305 result[1] = nk_vec2(r.x + r.w, r.y + h_half); 6306 result[2] = nk_vec2(r.x, r.y + r.h); 6307 } else if (direction == NK_DOWN) { 6308 result[0] = nk_vec2(r.x, r.y); 6309 result[1] = nk_vec2(r.x + r.w, r.y); 6310 result[2] = nk_vec2(r.x + w_half, r.y + r.h); 6311 } else { 6312 result[0] = nk_vec2(r.x, r.y + h_half); 6313 result[1] = nk_vec2(r.x + r.w, r.y); 6314 result[2] = nk_vec2(r.x + r.w, r.y + r.h); 6315 } 6316 } 6317 6318 6319 6320 6321 6322 /* =============================================================== 6323 * 6324 * UTIL 6325 * 6326 * ===============================================================*/ 6327 NK_INTERN int nk_str_match_here(const char *regexp, const char *text); 6328 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text); 6329 NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);} 6330 NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);} 6331 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;} 6332 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;} 6333 6334 NK_LIB void* 6335 nk_memcopy(void *dst0, const void *src0, nk_size length) 6336 { 6337 nk_ptr t; 6338 char *dst = (char*)dst0; 6339 const char *src = (const char*)src0; 6340 if (length == 0 || dst == src) 6341 goto done; 6342 6343 #define nk_word int 6344 #define nk_wsize sizeof(nk_word) 6345 #define nk_wmask (nk_wsize-1) 6346 #define NK_TLOOP(s) if (t) NK_TLOOP1(s) 6347 #define NK_TLOOP1(s) do { s; } while (--t) 6348 6349 if (dst < src) { 6350 t = (nk_ptr)src; /* only need low bits */ 6351 if ((t | (nk_ptr)dst) & nk_wmask) { 6352 if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize) 6353 t = length; 6354 else 6355 t = nk_wsize - (t & nk_wmask); 6356 length -= t; 6357 NK_TLOOP1(*dst++ = *src++); 6358 } 6359 t = length / nk_wsize; 6360 NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src; 6361 src += nk_wsize; dst += nk_wsize); 6362 t = length & nk_wmask; 6363 NK_TLOOP(*dst++ = *src++); 6364 } else { 6365 src += length; 6366 dst += length; 6367 t = (nk_ptr)src; 6368 if ((t | (nk_ptr)dst) & nk_wmask) { 6369 if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize) 6370 t = length; 6371 else 6372 t &= nk_wmask; 6373 length -= t; 6374 NK_TLOOP1(*--dst = *--src); 6375 } 6376 t = length / nk_wsize; 6377 NK_TLOOP(src -= nk_wsize; dst -= nk_wsize; 6378 *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src); 6379 t = length & nk_wmask; 6380 NK_TLOOP(*--dst = *--src); 6381 } 6382 #undef nk_word 6383 #undef nk_wsize 6384 #undef nk_wmask 6385 #undef NK_TLOOP 6386 #undef NK_TLOOP1 6387 done: 6388 return (dst0); 6389 } 6390 NK_LIB void 6391 nk_memset(void *ptr, int c0, nk_size size) 6392 { 6393 #define nk_word unsigned 6394 #define nk_wsize sizeof(nk_word) 6395 #define nk_wmask (nk_wsize - 1) 6396 nk_byte *dst = (nk_byte*)ptr; 6397 unsigned c = 0; 6398 nk_size t = 0; 6399 6400 if ((c = (nk_byte)c0) != 0) { 6401 c = (c << 8) | c; /* at least 16-bits */ 6402 if (sizeof(unsigned int) > 2) 6403 c = (c << 16) | c; /* at least 32-bits*/ 6404 } 6405 6406 /* too small of a word count */ 6407 dst = (nk_byte*)ptr; 6408 if (size < 3 * nk_wsize) { 6409 while (size--) *dst++ = (nk_byte)c0; 6410 return; 6411 } 6412 6413 /* align destination */ 6414 if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) { 6415 t = nk_wsize -t; 6416 size -= t; 6417 do { 6418 *dst++ = (nk_byte)c0; 6419 } while (--t != 0); 6420 } 6421 6422 /* fill word */ 6423 t = size / nk_wsize; 6424 do { 6425 *(nk_word*)((void*)dst) = c; 6426 dst += nk_wsize; 6427 } while (--t != 0); 6428 6429 /* fill trailing bytes */ 6430 t = (size & nk_wmask); 6431 if (t != 0) { 6432 do { 6433 *dst++ = (nk_byte)c0; 6434 } while (--t != 0); 6435 } 6436 6437 #undef nk_word 6438 #undef nk_wsize 6439 #undef nk_wmask 6440 } 6441 NK_LIB void 6442 nk_zero(void *ptr, nk_size size) 6443 { 6444 NK_ASSERT(ptr); 6445 NK_MEMSET(ptr, 0, size); 6446 } 6447 NK_API int 6448 nk_strlen(const char *str) 6449 { 6450 int siz = 0; 6451 NK_ASSERT(str); 6452 while (str && *str++ != '\0') siz++; 6453 return siz; 6454 } 6455 NK_API int 6456 nk_strtoi(const char *str, const char **endptr) 6457 { 6458 int neg = 1; 6459 const char *p = str; 6460 int value = 0; 6461 6462 NK_ASSERT(str); 6463 if (!str) return 0; 6464 6465 /* skip whitespace */ 6466 while (*p == ' ') p++; 6467 if (*p == '-') { 6468 neg = -1; 6469 p++; 6470 } 6471 while (*p && *p >= '0' && *p <= '9') { 6472 value = value * 10 + (int) (*p - '0'); 6473 p++; 6474 } 6475 if (endptr) 6476 *endptr = p; 6477 return neg*value; 6478 } 6479 NK_API double 6480 nk_strtod(const char *str, const char **endptr) 6481 { 6482 double m; 6483 double neg = 1.0; 6484 const char *p = str; 6485 double value = 0; 6486 double number = 0; 6487 6488 NK_ASSERT(str); 6489 if (!str) return 0; 6490 6491 /* skip whitespace */ 6492 while (*p == ' ') p++; 6493 if (*p == '-') { 6494 neg = -1.0; 6495 p++; 6496 } 6497 6498 while (*p && *p != '.' && *p != 'e') { 6499 value = value * 10.0 + (double) (*p - '0'); 6500 p++; 6501 } 6502 6503 if (*p == '.') { 6504 p++; 6505 for(m = 0.1; *p && *p != 'e'; p++ ) { 6506 value = value + (double) (*p - '0') * m; 6507 m *= 0.1; 6508 } 6509 } 6510 if (*p == 'e') { 6511 int i, pow, div; 6512 p++; 6513 if (*p == '-') { 6514 div = nk_true; 6515 p++; 6516 } else if (*p == '+') { 6517 div = nk_false; 6518 p++; 6519 } else div = nk_false; 6520 6521 for (pow = 0; *p; p++) 6522 pow = pow * 10 + (int) (*p - '0'); 6523 6524 for (m = 1.0, i = 0; i < pow; i++) 6525 m *= 10.0; 6526 6527 if (div) 6528 value /= m; 6529 else value *= m; 6530 } 6531 number = value * neg; 6532 if (endptr) 6533 *endptr = p; 6534 return number; 6535 } 6536 NK_API float 6537 nk_strtof(const char *str, const char **endptr) 6538 { 6539 float float_value; 6540 double double_value; 6541 double_value = NK_STRTOD(str, endptr); 6542 float_value = (float)double_value; 6543 return float_value; 6544 } 6545 NK_API int 6546 nk_stricmp(const char *s1, const char *s2) 6547 { 6548 nk_int c1,c2,d; 6549 do { 6550 c1 = *s1++; 6551 c2 = *s2++; 6552 d = c1 - c2; 6553 while (d) { 6554 if (c1 <= 'Z' && c1 >= 'A') { 6555 d += ('a' - 'A'); 6556 if (!d) break; 6557 } 6558 if (c2 <= 'Z' && c2 >= 'A') { 6559 d -= ('a' - 'A'); 6560 if (!d) break; 6561 } 6562 return ((d >= 0) << 1) - 1; 6563 } 6564 } while (c1); 6565 return 0; 6566 } 6567 NK_API int 6568 nk_stricmpn(const char *s1, const char *s2, int n) 6569 { 6570 int c1,c2,d; 6571 NK_ASSERT(n >= 0); 6572 do { 6573 c1 = *s1++; 6574 c2 = *s2++; 6575 if (!n--) return 0; 6576 6577 d = c1 - c2; 6578 while (d) { 6579 if (c1 <= 'Z' && c1 >= 'A') { 6580 d += ('a' - 'A'); 6581 if (!d) break; 6582 } 6583 if (c2 <= 'Z' && c2 >= 'A') { 6584 d -= ('a' - 'A'); 6585 if (!d) break; 6586 } 6587 return ((d >= 0) << 1) - 1; 6588 } 6589 } while (c1); 6590 return 0; 6591 } 6592 NK_INTERN int 6593 nk_str_match_here(const char *regexp, const char *text) 6594 { 6595 if (regexp[0] == '\0') 6596 return 1; 6597 if (regexp[1] == '*') 6598 return nk_str_match_star(regexp[0], regexp+2, text); 6599 if (regexp[0] == '$' && regexp[1] == '\0') 6600 return *text == '\0'; 6601 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) 6602 return nk_str_match_here(regexp+1, text+1); 6603 return 0; 6604 } 6605 NK_INTERN int 6606 nk_str_match_star(int c, const char *regexp, const char *text) 6607 { 6608 do {/* a '* matches zero or more instances */ 6609 if (nk_str_match_here(regexp, text)) 6610 return 1; 6611 } while (*text != '\0' && (*text++ == c || c == '.')); 6612 return 0; 6613 } 6614 NK_API int 6615 nk_strfilter(const char *text, const char *regexp) 6616 { 6617 /* 6618 c matches any literal character c 6619 . matches any single character 6620 ^ matches the beginning of the input string 6621 $ matches the end of the input string 6622 * matches zero or more occurrences of the previous character*/ 6623 if (regexp[0] == '^') 6624 return nk_str_match_here(regexp+1, text); 6625 do { /* must look even if string is empty */ 6626 if (nk_str_match_here(regexp, text)) 6627 return 1; 6628 } while (*text++ != '\0'); 6629 return 0; 6630 } 6631 NK_API int 6632 nk_strmatch_fuzzy_text(const char *str, int str_len, 6633 const char *pattern, int *out_score) 6634 { 6635 /* Returns true if each character in pattern is found sequentially within str 6636 * if found then out_score is also set. Score value has no intrinsic meaning. 6637 * Range varies with pattern. Can only compare scores with same search pattern. */ 6638 6639 /* bonus for adjacent matches */ 6640 #define NK_ADJACENCY_BONUS 5 6641 /* bonus if match occurs after a separator */ 6642 #define NK_SEPARATOR_BONUS 10 6643 /* bonus if match is uppercase and prev is lower */ 6644 #define NK_CAMEL_BONUS 10 6645 /* penalty applied for every letter in str before the first match */ 6646 #define NK_LEADING_LETTER_PENALTY (-3) 6647 /* maximum penalty for leading letters */ 6648 #define NK_MAX_LEADING_LETTER_PENALTY (-9) 6649 /* penalty for every letter that doesn't matter */ 6650 #define NK_UNMATCHED_LETTER_PENALTY (-1) 6651 6652 /* loop variables */ 6653 int score = 0; 6654 char const * pattern_iter = pattern; 6655 int str_iter = 0; 6656 int prev_matched = nk_false; 6657 int prev_lower = nk_false; 6658 /* true so if first letter match gets separator bonus*/ 6659 int prev_separator = nk_true; 6660 6661 /* use "best" matched letter if multiple string letters match the pattern */ 6662 char const * best_letter = 0; 6663 int best_letter_score = 0; 6664 6665 /* loop over strings */ 6666 NK_ASSERT(str); 6667 NK_ASSERT(pattern); 6668 if (!str || !str_len || !pattern) return 0; 6669 while (str_iter < str_len) 6670 { 6671 const char pattern_letter = *pattern_iter; 6672 const char str_letter = str[str_iter]; 6673 6674 int next_match = *pattern_iter != '\0' && 6675 nk_to_lower(pattern_letter) == nk_to_lower(str_letter); 6676 int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter); 6677 6678 int advanced = next_match && best_letter; 6679 int pattern_repeat = best_letter && *pattern_iter != '\0'; 6680 pattern_repeat = pattern_repeat && 6681 nk_to_lower(*best_letter) == nk_to_lower(pattern_letter); 6682 6683 if (advanced || pattern_repeat) { 6684 score += best_letter_score; 6685 best_letter = 0; 6686 best_letter_score = 0; 6687 } 6688 6689 if (next_match || rematch) 6690 { 6691 int new_score = 0; 6692 /* Apply penalty for each letter before the first pattern match */ 6693 if (pattern_iter == pattern) { 6694 int count = (int)(&str[str_iter] - str); 6695 int penalty = NK_LEADING_LETTER_PENALTY * count; 6696 if (penalty < NK_MAX_LEADING_LETTER_PENALTY) 6697 penalty = NK_MAX_LEADING_LETTER_PENALTY; 6698 6699 score += penalty; 6700 } 6701 6702 /* apply bonus for consecutive bonuses */ 6703 if (prev_matched) 6704 new_score += NK_ADJACENCY_BONUS; 6705 6706 /* apply bonus for matches after a separator */ 6707 if (prev_separator) 6708 new_score += NK_SEPARATOR_BONUS; 6709 6710 /* apply bonus across camel case boundaries */ 6711 if (prev_lower && nk_is_upper(str_letter)) 6712 new_score += NK_CAMEL_BONUS; 6713 6714 /* update pattern iter IFF the next pattern letter was matched */ 6715 if (next_match) 6716 ++pattern_iter; 6717 6718 /* update best letter in str which may be for a "next" letter or a rematch */ 6719 if (new_score >= best_letter_score) { 6720 /* apply penalty for now skipped letter */ 6721 if (best_letter != 0) 6722 score += NK_UNMATCHED_LETTER_PENALTY; 6723 6724 best_letter = &str[str_iter]; 6725 best_letter_score = new_score; 6726 } 6727 prev_matched = nk_true; 6728 } else { 6729 score += NK_UNMATCHED_LETTER_PENALTY; 6730 prev_matched = nk_false; 6731 } 6732 6733 /* separators should be more easily defined */ 6734 prev_lower = nk_is_lower(str_letter) != 0; 6735 prev_separator = str_letter == '_' || str_letter == ' '; 6736 6737 ++str_iter; 6738 } 6739 6740 /* apply score for last match */ 6741 if (best_letter) 6742 score += best_letter_score; 6743 6744 /* did not match full pattern */ 6745 if (*pattern_iter != '\0') 6746 return nk_false; 6747 6748 if (out_score) 6749 *out_score = score; 6750 return nk_true; 6751 } 6752 NK_API int 6753 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score) 6754 { 6755 return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score); 6756 } 6757 NK_LIB int 6758 nk_string_float_limit(char *string, int prec) 6759 { 6760 int dot = 0; 6761 char *c = string; 6762 while (*c) { 6763 if (*c == '.') { 6764 dot = 1; 6765 c++; 6766 continue; 6767 } 6768 if (dot == (prec+1)) { 6769 *c = 0; 6770 break; 6771 } 6772 if (dot > 0) dot++; 6773 c++; 6774 } 6775 return (int)(c - string); 6776 } 6777 NK_INTERN void 6778 nk_strrev_ascii(char *s) 6779 { 6780 int len = nk_strlen(s); 6781 int end = len / 2; 6782 int i = 0; 6783 char t; 6784 for (; i < end; ++i) { 6785 t = s[i]; 6786 s[i] = s[len - 1 - i]; 6787 s[len -1 - i] = t; 6788 } 6789 } 6790 NK_LIB char* 6791 nk_itoa(char *s, long n) 6792 { 6793 long i = 0; 6794 if (n == 0) { 6795 s[i++] = '0'; 6796 s[i] = 0; 6797 return s; 6798 } 6799 if (n < 0) { 6800 s[i++] = '-'; 6801 n = -n; 6802 } 6803 while (n > 0) { 6804 s[i++] = (char)('0' + (n % 10)); 6805 n /= 10; 6806 } 6807 s[i] = 0; 6808 if (s[0] == '-') 6809 ++s; 6810 6811 nk_strrev_ascii(s); 6812 return s; 6813 } 6814 NK_LIB char* 6815 nk_dtoa(char *s, double n) 6816 { 6817 int useExp = 0; 6818 int digit = 0, m = 0, m1 = 0; 6819 char *c = s; 6820 int neg = 0; 6821 6822 NK_ASSERT(s); 6823 if (!s) return 0; 6824 6825 if (n == 0.0) { 6826 s[0] = '0'; s[1] = '\0'; 6827 return s; 6828 } 6829 6830 neg = (n < 0); 6831 if (neg) n = -n; 6832 6833 /* calculate magnitude */ 6834 m = nk_log10(n); 6835 useExp = (m >= 14 || (neg && m >= 9) || m <= -9); 6836 if (neg) *(c++) = '-'; 6837 6838 /* set up for scientific notation */ 6839 if (useExp) { 6840 if (m < 0) 6841 m -= 1; 6842 n = n / (double)nk_pow(10.0, m); 6843 m1 = m; 6844 m = 0; 6845 } 6846 if (m < 1.0) { 6847 m = 0; 6848 } 6849 6850 /* convert the number */ 6851 while (n > NK_FLOAT_PRECISION || m >= 0) { 6852 double weight = nk_pow(10.0, m); 6853 if (weight > 0) { 6854 double t = (double)n / weight; 6855 digit = nk_ifloord(t); 6856 n -= ((double)digit * weight); 6857 *(c++) = (char)('0' + (char)digit); 6858 } 6859 if (m == 0 && n > 0) 6860 *(c++) = '.'; 6861 m--; 6862 } 6863 6864 if (useExp) { 6865 /* convert the exponent */ 6866 int i, j; 6867 *(c++) = 'e'; 6868 if (m1 > 0) { 6869 *(c++) = '+'; 6870 } else { 6871 *(c++) = '-'; 6872 m1 = -m1; 6873 } 6874 m = 0; 6875 while (m1 > 0) { 6876 *(c++) = (char)('0' + (char)(m1 % 10)); 6877 m1 /= 10; 6878 m++; 6879 } 6880 c -= m; 6881 for (i = 0, j = m-1; i<j; i++, j--) { 6882 /* swap without temporary */ 6883 c[i] ^= c[j]; 6884 c[j] ^= c[i]; 6885 c[i] ^= c[j]; 6886 } 6887 c += m; 6888 } 6889 *(c) = '\0'; 6890 return s; 6891 } 6892 #ifdef NK_INCLUDE_STANDARD_VARARGS 6893 #ifndef NK_INCLUDE_STANDARD_IO 6894 NK_INTERN int 6895 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args) 6896 { 6897 enum nk_arg_type { 6898 NK_ARG_TYPE_CHAR, 6899 NK_ARG_TYPE_SHORT, 6900 NK_ARG_TYPE_DEFAULT, 6901 NK_ARG_TYPE_LONG 6902 }; 6903 enum nk_arg_flags { 6904 NK_ARG_FLAG_LEFT = 0x01, 6905 NK_ARG_FLAG_PLUS = 0x02, 6906 NK_ARG_FLAG_SPACE = 0x04, 6907 NK_ARG_FLAG_NUM = 0x10, 6908 NK_ARG_FLAG_ZERO = 0x20 6909 }; 6910 6911 char number_buffer[NK_MAX_NUMBER_BUFFER]; 6912 enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT; 6913 int precision = NK_DEFAULT; 6914 int width = NK_DEFAULT; 6915 nk_flags flag = 0; 6916 6917 int len = 0; 6918 int result = -1; 6919 const char *iter = fmt; 6920 6921 NK_ASSERT(buf); 6922 NK_ASSERT(buf_size); 6923 if (!buf || !buf_size || !fmt) return 0; 6924 for (iter = fmt; *iter && len < buf_size; iter++) { 6925 /* copy all non-format characters */ 6926 while (*iter && (*iter != '%') && (len < buf_size)) 6927 buf[len++] = *iter++; 6928 if (!(*iter) || len >= buf_size) break; 6929 iter++; 6930 6931 /* flag arguments */ 6932 while (*iter) { 6933 if (*iter == '-') flag |= NK_ARG_FLAG_LEFT; 6934 else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS; 6935 else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE; 6936 else if (*iter == '#') flag |= NK_ARG_FLAG_NUM; 6937 else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO; 6938 else break; 6939 iter++; 6940 } 6941 6942 /* width argument */ 6943 width = NK_DEFAULT; 6944 if (*iter >= '1' && *iter <= '9') { 6945 const char *end; 6946 width = nk_strtoi(iter, &end); 6947 if (end == iter) 6948 width = -1; 6949 else iter = end; 6950 } else if (*iter == '*') { 6951 width = va_arg(args, int); 6952 iter++; 6953 } 6954 6955 /* precision argument */ 6956 precision = NK_DEFAULT; 6957 if (*iter == '.') { 6958 iter++; 6959 if (*iter == '*') { 6960 precision = va_arg(args, int); 6961 iter++; 6962 } else { 6963 const char *end; 6964 precision = nk_strtoi(iter, &end); 6965 if (end == iter) 6966 precision = -1; 6967 else iter = end; 6968 } 6969 } 6970 6971 /* length modifier */ 6972 if (*iter == 'h') { 6973 if (*(iter+1) == 'h') { 6974 arg_type = NK_ARG_TYPE_CHAR; 6975 iter++; 6976 } else arg_type = NK_ARG_TYPE_SHORT; 6977 iter++; 6978 } else if (*iter == 'l') { 6979 arg_type = NK_ARG_TYPE_LONG; 6980 iter++; 6981 } else arg_type = NK_ARG_TYPE_DEFAULT; 6982 6983 /* specifier */ 6984 if (*iter == '%') { 6985 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 6986 NK_ASSERT(precision == NK_DEFAULT); 6987 NK_ASSERT(width == NK_DEFAULT); 6988 if (len < buf_size) 6989 buf[len++] = '%'; 6990 } else if (*iter == 's') { 6991 /* string */ 6992 const char *str = va_arg(args, const char*); 6993 NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!"); 6994 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 6995 NK_ASSERT(precision == NK_DEFAULT); 6996 NK_ASSERT(width == NK_DEFAULT); 6997 if (str == buf) return -1; 6998 while (str && *str && len < buf_size) 6999 buf[len++] = *str++; 7000 } else if (*iter == 'n') { 7001 /* current length callback */ 7002 signed int *n = va_arg(args, int*); 7003 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7004 NK_ASSERT(precision == NK_DEFAULT); 7005 NK_ASSERT(width == NK_DEFAULT); 7006 if (n) *n = len; 7007 } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') { 7008 /* signed integer */ 7009 long value = 0; 7010 const char *num_iter; 7011 int num_len, num_print, padding; 7012 int cur_precision = NK_MAX(precision, 1); 7013 int cur_width = NK_MAX(width, 0); 7014 7015 /* retrieve correct value type */ 7016 if (arg_type == NK_ARG_TYPE_CHAR) 7017 value = (signed char)va_arg(args, int); 7018 else if (arg_type == NK_ARG_TYPE_SHORT) 7019 value = (signed short)va_arg(args, int); 7020 else if (arg_type == NK_ARG_TYPE_LONG) 7021 value = va_arg(args, signed long); 7022 else if (*iter == 'c') 7023 value = (unsigned char)va_arg(args, int); 7024 else value = va_arg(args, signed int); 7025 7026 /* convert number to string */ 7027 nk_itoa(number_buffer, value); 7028 num_len = nk_strlen(number_buffer); 7029 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7030 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7031 padding = NK_MAX(padding-1, 0); 7032 7033 /* fill left padding up to a total of `width` characters */ 7034 if (!(flag & NK_ARG_FLAG_LEFT)) { 7035 while (padding-- > 0 && (len < buf_size)) { 7036 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7037 buf[len++] = '0'; 7038 else buf[len++] = ' '; 7039 } 7040 } 7041 7042 /* copy string value representation into buffer */ 7043 if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size) 7044 buf[len++] = '+'; 7045 else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size) 7046 buf[len++] = ' '; 7047 7048 /* fill up to precision number of digits with '0' */ 7049 num_print = NK_MAX(cur_precision, num_len); 7050 while (precision && (num_print > num_len) && (len < buf_size)) { 7051 buf[len++] = '0'; 7052 num_print--; 7053 } 7054 7055 /* copy string value representation into buffer */ 7056 num_iter = number_buffer; 7057 while (precision && *num_iter && len < buf_size) 7058 buf[len++] = *num_iter++; 7059 7060 /* fill right padding up to width characters */ 7061 if (flag & NK_ARG_FLAG_LEFT) { 7062 while ((padding-- > 0) && (len < buf_size)) 7063 buf[len++] = ' '; 7064 } 7065 } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') { 7066 /* unsigned integer */ 7067 unsigned long value = 0; 7068 int num_len = 0, num_print, padding = 0; 7069 int cur_precision = NK_MAX(precision, 1); 7070 int cur_width = NK_MAX(width, 0); 7071 unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16; 7072 7073 /* print oct/hex/dec value */ 7074 const char *upper_output_format = "0123456789ABCDEF"; 7075 const char *lower_output_format = "0123456789abcdef"; 7076 const char *output_format = (*iter == 'x') ? 7077 lower_output_format: upper_output_format; 7078 7079 /* retrieve correct value type */ 7080 if (arg_type == NK_ARG_TYPE_CHAR) 7081 value = (unsigned char)va_arg(args, int); 7082 else if (arg_type == NK_ARG_TYPE_SHORT) 7083 value = (unsigned short)va_arg(args, int); 7084 else if (arg_type == NK_ARG_TYPE_LONG) 7085 value = va_arg(args, unsigned long); 7086 else value = va_arg(args, unsigned int); 7087 7088 do { 7089 /* convert decimal number into hex/oct number */ 7090 int digit = output_format[value % base]; 7091 if (num_len < NK_MAX_NUMBER_BUFFER) 7092 number_buffer[num_len++] = (char)digit; 7093 value /= base; 7094 } while (value > 0); 7095 7096 num_print = NK_MAX(cur_precision, num_len); 7097 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7098 if (flag & NK_ARG_FLAG_NUM) 7099 padding = NK_MAX(padding-1, 0); 7100 7101 /* fill left padding up to a total of `width` characters */ 7102 if (!(flag & NK_ARG_FLAG_LEFT)) { 7103 while ((padding-- > 0) && (len < buf_size)) { 7104 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7105 buf[len++] = '0'; 7106 else buf[len++] = ' '; 7107 } 7108 } 7109 7110 /* fill up to precision number of digits */ 7111 if (num_print && (flag & NK_ARG_FLAG_NUM)) { 7112 if ((*iter == 'o') && (len < buf_size)) { 7113 buf[len++] = '0'; 7114 } else if ((*iter == 'x') && ((len+1) < buf_size)) { 7115 buf[len++] = '0'; 7116 buf[len++] = 'x'; 7117 } else if ((*iter == 'X') && ((len+1) < buf_size)) { 7118 buf[len++] = '0'; 7119 buf[len++] = 'X'; 7120 } 7121 } 7122 while (precision && (num_print > num_len) && (len < buf_size)) { 7123 buf[len++] = '0'; 7124 num_print--; 7125 } 7126 7127 /* reverse number direction */ 7128 while (num_len > 0) { 7129 if (precision && (len < buf_size)) 7130 buf[len++] = number_buffer[num_len-1]; 7131 num_len--; 7132 } 7133 7134 /* fill right padding up to width characters */ 7135 if (flag & NK_ARG_FLAG_LEFT) { 7136 while ((padding-- > 0) && (len < buf_size)) 7137 buf[len++] = ' '; 7138 } 7139 } else if (*iter == 'f') { 7140 /* floating point */ 7141 const char *num_iter; 7142 int cur_precision = (precision < 0) ? 6: precision; 7143 int prefix, cur_width = NK_MAX(width, 0); 7144 double value = va_arg(args, double); 7145 int num_len = 0, frac_len = 0, dot = 0; 7146 int padding = 0; 7147 7148 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7149 NK_DTOA(number_buffer, value); 7150 num_len = nk_strlen(number_buffer); 7151 7152 /* calculate padding */ 7153 num_iter = number_buffer; 7154 while (*num_iter && *num_iter != '.') 7155 num_iter++; 7156 7157 prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0; 7158 padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0); 7159 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7160 padding = NK_MAX(padding-1, 0); 7161 7162 /* fill left padding up to a total of `width` characters */ 7163 if (!(flag & NK_ARG_FLAG_LEFT)) { 7164 while (padding-- > 0 && (len < buf_size)) { 7165 if (flag & NK_ARG_FLAG_ZERO) 7166 buf[len++] = '0'; 7167 else buf[len++] = ' '; 7168 } 7169 } 7170 7171 /* copy string value representation into buffer */ 7172 num_iter = number_buffer; 7173 if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size)) 7174 buf[len++] = '+'; 7175 else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size)) 7176 buf[len++] = ' '; 7177 while (*num_iter) { 7178 if (dot) frac_len++; 7179 if (len < buf_size) 7180 buf[len++] = *num_iter; 7181 if (*num_iter == '.') dot = 1; 7182 if (frac_len >= cur_precision) break; 7183 num_iter++; 7184 } 7185 7186 /* fill number up to precision */ 7187 while (frac_len < cur_precision) { 7188 if (!dot && len < buf_size) { 7189 buf[len++] = '.'; 7190 dot = 1; 7191 } 7192 if (len < buf_size) 7193 buf[len++] = '0'; 7194 frac_len++; 7195 } 7196 7197 /* fill right padding up to width characters */ 7198 if (flag & NK_ARG_FLAG_LEFT) { 7199 while ((padding-- > 0) && (len < buf_size)) 7200 buf[len++] = ' '; 7201 } 7202 } else { 7203 /* Specifier not supported: g,G,e,E,p,z */ 7204 NK_ASSERT(0 && "specifier is not supported!"); 7205 return result; 7206 } 7207 } 7208 buf[(len >= buf_size)?(buf_size-1):len] = 0; 7209 result = (len >= buf_size)?-1:len; 7210 return result; 7211 } 7212 #endif 7213 NK_LIB int 7214 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args) 7215 { 7216 int result = -1; 7217 NK_ASSERT(buf); 7218 NK_ASSERT(buf_size); 7219 if (!buf || !buf_size || !fmt) return 0; 7220 #ifdef NK_INCLUDE_STANDARD_IO 7221 result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args); 7222 result = (result >= buf_size) ? -1: result; 7223 buf[buf_size-1] = 0; 7224 #else 7225 result = nk_vsnprintf(buf, buf_size, fmt, args); 7226 #endif 7227 return result; 7228 } 7229 #endif 7230 NK_API nk_hash 7231 nk_murmur_hash(const void * key, int len, nk_hash seed) 7232 { 7233 /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ 7234 #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) 7235 7236 nk_uint h1 = seed; 7237 nk_uint k1; 7238 const nk_byte *data = (const nk_byte*)key; 7239 const nk_byte *keyptr = data; 7240 nk_byte *k1ptr; 7241 const int bsize = sizeof(k1); 7242 const int nblocks = len/4; 7243 7244 const nk_uint c1 = 0xcc9e2d51; 7245 const nk_uint c2 = 0x1b873593; 7246 const nk_byte *tail; 7247 int i; 7248 7249 /* body */ 7250 if (!key) return 0; 7251 for (i = 0; i < nblocks; ++i, keyptr += bsize) { 7252 k1ptr = (nk_byte*)&k1; 7253 k1ptr[0] = keyptr[0]; 7254 k1ptr[1] = keyptr[1]; 7255 k1ptr[2] = keyptr[2]; 7256 k1ptr[3] = keyptr[3]; 7257 7258 k1 *= c1; 7259 k1 = NK_ROTL(k1,15); 7260 k1 *= c2; 7261 7262 h1 ^= k1; 7263 h1 = NK_ROTL(h1,13); 7264 h1 = h1*5+0xe6546b64; 7265 } 7266 7267 /* tail */ 7268 tail = (const nk_byte*)(data + nblocks*4); 7269 k1 = 0; 7270 switch (len & 3) { 7271 case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */ 7272 case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */ 7273 case 1: k1 ^= tail[0]; 7274 k1 *= c1; 7275 k1 = NK_ROTL(k1,15); 7276 k1 *= c2; 7277 h1 ^= k1; 7278 break; 7279 default: break; 7280 } 7281 7282 /* finalization */ 7283 h1 ^= (nk_uint)len; 7284 /* fmix32 */ 7285 h1 ^= h1 >> 16; 7286 h1 *= 0x85ebca6b; 7287 h1 ^= h1 >> 13; 7288 h1 *= 0xc2b2ae35; 7289 h1 ^= h1 >> 16; 7290 7291 #undef NK_ROTL 7292 return h1; 7293 } 7294 #ifdef NK_INCLUDE_STANDARD_IO 7295 NK_LIB char* 7296 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc) 7297 { 7298 char *buf; 7299 FILE *fd; 7300 long ret; 7301 7302 NK_ASSERT(path); 7303 NK_ASSERT(siz); 7304 NK_ASSERT(alloc); 7305 if (!path || !siz || !alloc) 7306 return 0; 7307 7308 fd = fopen(path, "rb"); 7309 if (!fd) return 0; 7310 fseek(fd, 0, SEEK_END); 7311 ret = ftell(fd); 7312 if (ret < 0) { 7313 fclose(fd); 7314 return 0; 7315 } 7316 *siz = (nk_size)ret; 7317 fseek(fd, 0, SEEK_SET); 7318 buf = (char*)alloc->alloc(alloc->userdata,0, *siz); 7319 NK_ASSERT(buf); 7320 if (!buf) { 7321 fclose(fd); 7322 return 0; 7323 } 7324 *siz = (nk_size)fread(buf, 1,*siz, fd); 7325 fclose(fd); 7326 return buf; 7327 } 7328 #endif 7329 NK_LIB int 7330 nk_text_clamp(const struct nk_user_font *font, const char *text, 7331 int text_len, float space, int *glyphs, float *text_width, 7332 nk_rune *sep_list, int sep_count) 7333 { 7334 int i = 0; 7335 int glyph_len = 0; 7336 float last_width = 0; 7337 nk_rune unicode = 0; 7338 float width = 0; 7339 int len = 0; 7340 int g = 0; 7341 float s; 7342 7343 int sep_len = 0; 7344 int sep_g = 0; 7345 float sep_width = 0; 7346 sep_count = NK_MAX(sep_count,0); 7347 7348 glyph_len = nk_utf_decode(text, &unicode, text_len); 7349 while (glyph_len && (width < space) && (len < text_len)) { 7350 len += glyph_len; 7351 s = font->width(font->userdata, font->height, text, len); 7352 for (i = 0; i < sep_count; ++i) { 7353 if (unicode != sep_list[i]) continue; 7354 sep_width = last_width = width; 7355 sep_g = g+1; 7356 sep_len = len; 7357 break; 7358 } 7359 if (i == sep_count){ 7360 last_width = sep_width = width; 7361 sep_g = g+1; 7362 } 7363 width = s; 7364 glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len); 7365 g++; 7366 } 7367 if (len >= text_len) { 7368 *glyphs = g; 7369 *text_width = last_width; 7370 return len; 7371 } else { 7372 *glyphs = sep_g; 7373 *text_width = sep_width; 7374 return (!sep_len) ? len: sep_len; 7375 } 7376 } 7377 NK_LIB struct nk_vec2 7378 nk_text_calculate_text_bounds(const struct nk_user_font *font, 7379 const char *begin, int byte_len, float row_height, const char **remaining, 7380 struct nk_vec2 *out_offset, int *glyphs, int op) 7381 { 7382 float line_height = row_height; 7383 struct nk_vec2 text_size = nk_vec2(0,0); 7384 float line_width = 0.0f; 7385 7386 float glyph_width; 7387 int glyph_len = 0; 7388 nk_rune unicode = 0; 7389 int text_len = 0; 7390 if (!begin || byte_len <= 0 || !font) 7391 return nk_vec2(0,row_height); 7392 7393 glyph_len = nk_utf_decode(begin, &unicode, byte_len); 7394 if (!glyph_len) return text_size; 7395 glyph_width = font->width(font->userdata, font->height, begin, glyph_len); 7396 7397 *glyphs = 0; 7398 while ((text_len < byte_len) && glyph_len) { 7399 if (unicode == '\n') { 7400 text_size.x = NK_MAX(text_size.x, line_width); 7401 text_size.y += line_height; 7402 line_width = 0; 7403 *glyphs+=1; 7404 if (op == NK_STOP_ON_NEW_LINE) 7405 break; 7406 7407 text_len++; 7408 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7409 continue; 7410 } 7411 7412 if (unicode == '\r') { 7413 text_len++; 7414 *glyphs+=1; 7415 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7416 continue; 7417 } 7418 7419 *glyphs = *glyphs + 1; 7420 text_len += glyph_len; 7421 line_width += (float)glyph_width; 7422 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7423 glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len); 7424 continue; 7425 } 7426 7427 if (text_size.x < line_width) 7428 text_size.x = line_width; 7429 if (out_offset) 7430 *out_offset = nk_vec2(line_width, text_size.y + line_height); 7431 if (line_width > 0 || text_size.y == 0.0f) 7432 text_size.y += line_height; 7433 if (remaining) 7434 *remaining = begin+text_len; 7435 return text_size; 7436 } 7437 7438 7439 7440 7441 7442 /* ============================================================== 7443 * 7444 * COLOR 7445 * 7446 * ===============================================================*/ 7447 NK_INTERN int 7448 nk_parse_hex(const char *p, int length) 7449 { 7450 int i = 0; 7451 int len = 0; 7452 while (len < length) { 7453 i <<= 4; 7454 if (p[len] >= 'a' && p[len] <= 'f') 7455 i += ((p[len] - 'a') + 10); 7456 else if (p[len] >= 'A' && p[len] <= 'F') 7457 i += ((p[len] - 'A') + 10); 7458 else i += (p[len] - '0'); 7459 len++; 7460 } 7461 return i; 7462 } 7463 NK_API struct nk_color 7464 nk_rgba(int r, int g, int b, int a) 7465 { 7466 struct nk_color ret; 7467 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7468 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7469 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7470 ret.a = (nk_byte)NK_CLAMP(0, a, 255); 7471 return ret; 7472 } 7473 NK_API struct nk_color 7474 nk_rgb_hex(const char *rgb) 7475 { 7476 struct nk_color col; 7477 const char *c = rgb; 7478 if (*c == '#') c++; 7479 col.r = (nk_byte)nk_parse_hex(c, 2); 7480 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7481 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7482 col.a = 255; 7483 return col; 7484 } 7485 NK_API struct nk_color 7486 nk_rgba_hex(const char *rgb) 7487 { 7488 struct nk_color col; 7489 const char *c = rgb; 7490 if (*c == '#') c++; 7491 col.r = (nk_byte)nk_parse_hex(c, 2); 7492 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7493 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7494 col.a = (nk_byte)nk_parse_hex(c+6, 2); 7495 return col; 7496 } 7497 NK_API void 7498 nk_color_hex_rgba(char *output, struct nk_color col) 7499 { 7500 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7501 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7502 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7503 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7504 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7505 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7506 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7507 output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4); 7508 output[7] = (char)NK_TO_HEX((col.a & 0x0F)); 7509 output[8] = '\0'; 7510 #undef NK_TO_HEX 7511 } 7512 NK_API void 7513 nk_color_hex_rgb(char *output, struct nk_color col) 7514 { 7515 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7516 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7517 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7518 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7519 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7520 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7521 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7522 output[6] = '\0'; 7523 #undef NK_TO_HEX 7524 } 7525 NK_API struct nk_color 7526 nk_rgba_iv(const int *c) 7527 { 7528 return nk_rgba(c[0], c[1], c[2], c[3]); 7529 } 7530 NK_API struct nk_color 7531 nk_rgba_bv(const nk_byte *c) 7532 { 7533 return nk_rgba(c[0], c[1], c[2], c[3]); 7534 } 7535 NK_API struct nk_color 7536 nk_rgb(int r, int g, int b) 7537 { 7538 struct nk_color ret; 7539 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7540 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7541 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7542 ret.a = (nk_byte)255; 7543 return ret; 7544 } 7545 NK_API struct nk_color 7546 nk_rgb_iv(const int *c) 7547 { 7548 return nk_rgb(c[0], c[1], c[2]); 7549 } 7550 NK_API struct nk_color 7551 nk_rgb_bv(const nk_byte* c) 7552 { 7553 return nk_rgb(c[0], c[1], c[2]); 7554 } 7555 NK_API struct nk_color 7556 nk_rgba_u32(nk_uint in) 7557 { 7558 struct nk_color ret; 7559 ret.r = (in & 0xFF); 7560 ret.g = ((in >> 8) & 0xFF); 7561 ret.b = ((in >> 16) & 0xFF); 7562 ret.a = (nk_byte)((in >> 24) & 0xFF); 7563 return ret; 7564 } 7565 NK_API struct nk_color 7566 nk_rgba_f(float r, float g, float b, float a) 7567 { 7568 struct nk_color ret; 7569 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7570 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7571 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7572 ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f); 7573 return ret; 7574 } 7575 NK_API struct nk_color 7576 nk_rgba_fv(const float *c) 7577 { 7578 return nk_rgba_f(c[0], c[1], c[2], c[3]); 7579 } 7580 NK_API struct nk_color 7581 nk_rgba_cf(struct nk_colorf c) 7582 { 7583 return nk_rgba_f(c.r, c.g, c.b, c.a); 7584 } 7585 NK_API struct nk_color 7586 nk_rgb_f(float r, float g, float b) 7587 { 7588 struct nk_color ret; 7589 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7590 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7591 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7592 ret.a = 255; 7593 return ret; 7594 } 7595 NK_API struct nk_color 7596 nk_rgb_fv(const float *c) 7597 { 7598 return nk_rgb_f(c[0], c[1], c[2]); 7599 } 7600 NK_API struct nk_color 7601 nk_rgb_cf(struct nk_colorf c) 7602 { 7603 return nk_rgb_f(c.r, c.g, c.b); 7604 } 7605 NK_API struct nk_color 7606 nk_hsv(int h, int s, int v) 7607 { 7608 return nk_hsva(h, s, v, 255); 7609 } 7610 NK_API struct nk_color 7611 nk_hsv_iv(const int *c) 7612 { 7613 return nk_hsv(c[0], c[1], c[2]); 7614 } 7615 NK_API struct nk_color 7616 nk_hsv_bv(const nk_byte *c) 7617 { 7618 return nk_hsv(c[0], c[1], c[2]); 7619 } 7620 NK_API struct nk_color 7621 nk_hsv_f(float h, float s, float v) 7622 { 7623 return nk_hsva_f(h, s, v, 1.0f); 7624 } 7625 NK_API struct nk_color 7626 nk_hsv_fv(const float *c) 7627 { 7628 return nk_hsv_f(c[0], c[1], c[2]); 7629 } 7630 NK_API struct nk_color 7631 nk_hsva(int h, int s, int v, int a) 7632 { 7633 float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f; 7634 float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f; 7635 float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f; 7636 float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f; 7637 return nk_hsva_f(hf, sf, vf, af); 7638 } 7639 NK_API struct nk_color 7640 nk_hsva_iv(const int *c) 7641 { 7642 return nk_hsva(c[0], c[1], c[2], c[3]); 7643 } 7644 NK_API struct nk_color 7645 nk_hsva_bv(const nk_byte *c) 7646 { 7647 return nk_hsva(c[0], c[1], c[2], c[3]); 7648 } 7649 NK_API struct nk_colorf 7650 nk_hsva_colorf(float h, float s, float v, float a) 7651 { 7652 int i; 7653 float p, q, t, f; 7654 struct nk_colorf out = {0,0,0,0}; 7655 if (s <= 0.0f) { 7656 out.r = v; out.g = v; out.b = v; out.a = a; 7657 return out; 7658 } 7659 h = h / (60.0f/360.0f); 7660 i = (int)h; 7661 f = h - (float)i; 7662 p = v * (1.0f - s); 7663 q = v * (1.0f - (s * f)); 7664 t = v * (1.0f - s * (1.0f - f)); 7665 7666 switch (i) { 7667 case 0: default: out.r = v; out.g = t; out.b = p; break; 7668 case 1: out.r = q; out.g = v; out.b = p; break; 7669 case 2: out.r = p; out.g = v; out.b = t; break; 7670 case 3: out.r = p; out.g = q; out.b = v; break; 7671 case 4: out.r = t; out.g = p; out.b = v; break; 7672 case 5: out.r = v; out.g = p; out.b = q; break;} 7673 out.a = a; 7674 return out; 7675 } 7676 NK_API struct nk_colorf 7677 nk_hsva_colorfv(float *c) 7678 { 7679 return nk_hsva_colorf(c[0], c[1], c[2], c[3]); 7680 } 7681 NK_API struct nk_color 7682 nk_hsva_f(float h, float s, float v, float a) 7683 { 7684 struct nk_colorf c = nk_hsva_colorf(h, s, v, a); 7685 return nk_rgba_f(c.r, c.g, c.b, c.a); 7686 } 7687 NK_API struct nk_color 7688 nk_hsva_fv(const float *c) 7689 { 7690 return nk_hsva_f(c[0], c[1], c[2], c[3]); 7691 } 7692 NK_API nk_uint 7693 nk_color_u32(struct nk_color in) 7694 { 7695 nk_uint out = (nk_uint)in.r; 7696 out |= ((nk_uint)in.g << 8); 7697 out |= ((nk_uint)in.b << 16); 7698 out |= ((nk_uint)in.a << 24); 7699 return out; 7700 } 7701 NK_API void 7702 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in) 7703 { 7704 NK_STORAGE const float s = 1.0f/255.0f; 7705 *r = (float)in.r * s; 7706 *g = (float)in.g * s; 7707 *b = (float)in.b * s; 7708 *a = (float)in.a * s; 7709 } 7710 NK_API void 7711 nk_color_fv(float *c, struct nk_color in) 7712 { 7713 nk_color_f(&c[0], &c[1], &c[2], &c[3], in); 7714 } 7715 NK_API struct nk_colorf 7716 nk_color_cf(struct nk_color in) 7717 { 7718 struct nk_colorf o; 7719 nk_color_f(&o.r, &o.g, &o.b, &o.a, in); 7720 return o; 7721 } 7722 NK_API void 7723 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in) 7724 { 7725 NK_STORAGE const double s = 1.0/255.0; 7726 *r = (double)in.r * s; 7727 *g = (double)in.g * s; 7728 *b = (double)in.b * s; 7729 *a = (double)in.a * s; 7730 } 7731 NK_API void 7732 nk_color_dv(double *c, struct nk_color in) 7733 { 7734 nk_color_d(&c[0], &c[1], &c[2], &c[3], in); 7735 } 7736 NK_API void 7737 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in) 7738 { 7739 float a; 7740 nk_color_hsva_f(out_h, out_s, out_v, &a, in); 7741 } 7742 NK_API void 7743 nk_color_hsv_fv(float *out, struct nk_color in) 7744 { 7745 float a; 7746 nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in); 7747 } 7748 NK_API void 7749 nk_colorf_hsva_f(float *out_h, float *out_s, 7750 float *out_v, float *out_a, struct nk_colorf in) 7751 { 7752 float chroma; 7753 float K = 0.0f; 7754 if (in.g < in.b) { 7755 const float t = in.g; in.g = in.b; in.b = t; 7756 K = -1.f; 7757 } 7758 if (in.r < in.g) { 7759 const float t = in.r; in.r = in.g; in.g = t; 7760 K = -2.f/6.0f - K; 7761 } 7762 chroma = in.r - ((in.g < in.b) ? in.g: in.b); 7763 *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f)); 7764 *out_s = chroma / (in.r + 1e-20f); 7765 *out_v = in.r; 7766 *out_a = in.a; 7767 7768 } 7769 NK_API void 7770 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in) 7771 { 7772 nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in); 7773 } 7774 NK_API void 7775 nk_color_hsva_f(float *out_h, float *out_s, 7776 float *out_v, float *out_a, struct nk_color in) 7777 { 7778 struct nk_colorf col; 7779 nk_color_f(&col.r,&col.g,&col.b,&col.a, in); 7780 nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col); 7781 } 7782 NK_API void 7783 nk_color_hsva_fv(float *out, struct nk_color in) 7784 { 7785 nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in); 7786 } 7787 NK_API void 7788 nk_color_hsva_i(int *out_h, int *out_s, int *out_v, 7789 int *out_a, struct nk_color in) 7790 { 7791 float h,s,v,a; 7792 nk_color_hsva_f(&h, &s, &v, &a, in); 7793 *out_h = (nk_byte)(h * 255.0f); 7794 *out_s = (nk_byte)(s * 255.0f); 7795 *out_v = (nk_byte)(v * 255.0f); 7796 *out_a = (nk_byte)(a * 255.0f); 7797 } 7798 NK_API void 7799 nk_color_hsva_iv(int *out, struct nk_color in) 7800 { 7801 nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in); 7802 } 7803 NK_API void 7804 nk_color_hsva_bv(nk_byte *out, struct nk_color in) 7805 { 7806 int tmp[4]; 7807 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7808 out[0] = (nk_byte)tmp[0]; 7809 out[1] = (nk_byte)tmp[1]; 7810 out[2] = (nk_byte)tmp[2]; 7811 out[3] = (nk_byte)tmp[3]; 7812 } 7813 NK_API void 7814 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in) 7815 { 7816 int tmp[4]; 7817 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7818 *h = (nk_byte)tmp[0]; 7819 *s = (nk_byte)tmp[1]; 7820 *v = (nk_byte)tmp[2]; 7821 *a = (nk_byte)tmp[3]; 7822 } 7823 NK_API void 7824 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in) 7825 { 7826 int a; 7827 nk_color_hsva_i(out_h, out_s, out_v, &a, in); 7828 } 7829 NK_API void 7830 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in) 7831 { 7832 int tmp[4]; 7833 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7834 *out_h = (nk_byte)tmp[0]; 7835 *out_s = (nk_byte)tmp[1]; 7836 *out_v = (nk_byte)tmp[2]; 7837 } 7838 NK_API void 7839 nk_color_hsv_iv(int *out, struct nk_color in) 7840 { 7841 nk_color_hsv_i(&out[0], &out[1], &out[2], in); 7842 } 7843 NK_API void 7844 nk_color_hsv_bv(nk_byte *out, struct nk_color in) 7845 { 7846 int tmp[4]; 7847 nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in); 7848 out[0] = (nk_byte)tmp[0]; 7849 out[1] = (nk_byte)tmp[1]; 7850 out[2] = (nk_byte)tmp[2]; 7851 } 7852 7853 7854 7855 7856 7857 /* =============================================================== 7858 * 7859 * UTF-8 7860 * 7861 * ===============================================================*/ 7862 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 7863 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 7864 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000}; 7865 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 7866 7867 NK_INTERN int 7868 nk_utf_validate(nk_rune *u, int i) 7869 { 7870 NK_ASSERT(u); 7871 if (!u) return 0; 7872 if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) || 7873 NK_BETWEEN(*u, 0xD800, 0xDFFF)) 7874 *u = NK_UTF_INVALID; 7875 for (i = 1; *u > nk_utfmax[i]; ++i); 7876 return i; 7877 } 7878 NK_INTERN nk_rune 7879 nk_utf_decode_byte(char c, int *i) 7880 { 7881 NK_ASSERT(i); 7882 if (!i) return 0; 7883 for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) { 7884 if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i]) 7885 return (nk_byte)(c & ~nk_utfmask[*i]); 7886 } 7887 return 0; 7888 } 7889 NK_API int 7890 nk_utf_decode(const char *c, nk_rune *u, int clen) 7891 { 7892 int i, j, len, type=0; 7893 nk_rune udecoded; 7894 7895 NK_ASSERT(c); 7896 NK_ASSERT(u); 7897 7898 if (!c || !u) return 0; 7899 if (!clen) return 0; 7900 *u = NK_UTF_INVALID; 7901 7902 udecoded = nk_utf_decode_byte(c[0], &len); 7903 if (!NK_BETWEEN(len, 1, NK_UTF_SIZE)) 7904 return 1; 7905 7906 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 7907 udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type); 7908 if (type != 0) 7909 return j; 7910 } 7911 if (j < len) 7912 return 0; 7913 *u = udecoded; 7914 nk_utf_validate(u, len); 7915 return len; 7916 } 7917 NK_INTERN char 7918 nk_utf_encode_byte(nk_rune u, int i) 7919 { 7920 return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i])); 7921 } 7922 NK_API int 7923 nk_utf_encode(nk_rune u, char *c, int clen) 7924 { 7925 int len, i; 7926 len = nk_utf_validate(&u, 0); 7927 if (clen < len || !len || len > NK_UTF_SIZE) 7928 return 0; 7929 7930 for (i = len - 1; i != 0; --i) { 7931 c[i] = nk_utf_encode_byte(u, 0); 7932 u >>= 6; 7933 } 7934 c[0] = nk_utf_encode_byte(u, len); 7935 return len; 7936 } 7937 NK_API int 7938 nk_utf_len(const char *str, int len) 7939 { 7940 const char *text; 7941 int glyphs = 0; 7942 int text_len; 7943 int glyph_len; 7944 int src_len = 0; 7945 nk_rune unicode; 7946 7947 NK_ASSERT(str); 7948 if (!str || !len) return 0; 7949 7950 text = str; 7951 text_len = len; 7952 glyph_len = nk_utf_decode(text, &unicode, text_len); 7953 while (glyph_len && src_len < len) { 7954 glyphs++; 7955 src_len = src_len + glyph_len; 7956 glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len); 7957 } 7958 return glyphs; 7959 } 7960 NK_API const char* 7961 nk_utf_at(const char *buffer, int length, int index, 7962 nk_rune *unicode, int *len) 7963 { 7964 int i = 0; 7965 int src_len = 0; 7966 int glyph_len = 0; 7967 const char *text; 7968 int text_len; 7969 7970 NK_ASSERT(buffer); 7971 NK_ASSERT(unicode); 7972 NK_ASSERT(len); 7973 7974 if (!buffer || !unicode || !len) return 0; 7975 if (index < 0) { 7976 *unicode = NK_UTF_INVALID; 7977 *len = 0; 7978 return 0; 7979 } 7980 7981 text = buffer; 7982 text_len = length; 7983 glyph_len = nk_utf_decode(text, unicode, text_len); 7984 while (glyph_len) { 7985 if (i == index) { 7986 *len = glyph_len; 7987 break; 7988 } 7989 7990 i++; 7991 src_len = src_len + glyph_len; 7992 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 7993 } 7994 if (i != index) return 0; 7995 return buffer + src_len; 7996 } 7997 7998 7999 8000 8001 8002 /* ============================================================== 8003 * 8004 * BUFFER 8005 * 8006 * ===============================================================*/ 8007 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8008 NK_LIB void* 8009 nk_malloc(nk_handle unused, void *old,nk_size size) 8010 { 8011 NK_UNUSED(unused); 8012 NK_UNUSED(old); 8013 return malloc(size); 8014 } 8015 NK_LIB void 8016 nk_mfree(nk_handle unused, void *ptr) 8017 { 8018 NK_UNUSED(unused); 8019 free(ptr); 8020 } 8021 NK_API void 8022 nk_buffer_init_default(struct nk_buffer *buffer) 8023 { 8024 struct nk_allocator alloc; 8025 alloc.userdata.ptr = 0; 8026 alloc.alloc = nk_malloc; 8027 alloc.free = nk_mfree; 8028 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE); 8029 } 8030 #endif 8031 8032 NK_API void 8033 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a, 8034 nk_size initial_size) 8035 { 8036 NK_ASSERT(b); 8037 NK_ASSERT(a); 8038 NK_ASSERT(initial_size); 8039 if (!b || !a || !initial_size) return; 8040 8041 nk_zero(b, sizeof(*b)); 8042 b->type = NK_BUFFER_DYNAMIC; 8043 b->memory.ptr = a->alloc(a->userdata,0, initial_size); 8044 b->memory.size = initial_size; 8045 b->size = initial_size; 8046 b->grow_factor = 2.0f; 8047 b->pool = *a; 8048 } 8049 NK_API void 8050 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size) 8051 { 8052 NK_ASSERT(b); 8053 NK_ASSERT(m); 8054 NK_ASSERT(size); 8055 if (!b || !m || !size) return; 8056 8057 nk_zero(b, sizeof(*b)); 8058 b->type = NK_BUFFER_FIXED; 8059 b->memory.ptr = m; 8060 b->memory.size = size; 8061 b->size = size; 8062 } 8063 NK_LIB void* 8064 nk_buffer_align(void *unaligned, 8065 nk_size align, nk_size *alignment, 8066 enum nk_buffer_allocation_type type) 8067 { 8068 void *memory = 0; 8069 switch (type) { 8070 default: 8071 case NK_BUFFER_MAX: 8072 case NK_BUFFER_FRONT: 8073 if (align) { 8074 memory = NK_ALIGN_PTR(unaligned, align); 8075 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8076 } else { 8077 memory = unaligned; 8078 *alignment = 0; 8079 } 8080 break; 8081 case NK_BUFFER_BACK: 8082 if (align) { 8083 memory = NK_ALIGN_PTR_BACK(unaligned, align); 8084 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory); 8085 } else { 8086 memory = unaligned; 8087 *alignment = 0; 8088 } 8089 break; 8090 } 8091 return memory; 8092 } 8093 NK_LIB void* 8094 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size) 8095 { 8096 void *temp; 8097 nk_size buffer_size; 8098 8099 NK_ASSERT(b); 8100 NK_ASSERT(size); 8101 if (!b || !size || !b->pool.alloc || !b->pool.free) 8102 return 0; 8103 8104 buffer_size = b->memory.size; 8105 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity); 8106 NK_ASSERT(temp); 8107 if (!temp) return 0; 8108 8109 *size = capacity; 8110 if (temp != b->memory.ptr) { 8111 NK_MEMCPY(temp, b->memory.ptr, buffer_size); 8112 b->pool.free(b->pool.userdata, b->memory.ptr); 8113 } 8114 8115 if (b->size == buffer_size) { 8116 /* no back buffer so just set correct size */ 8117 b->size = capacity; 8118 return temp; 8119 } else { 8120 /* copy back buffer to the end of the new buffer */ 8121 void *dst, *src; 8122 nk_size back_size; 8123 back_size = buffer_size - b->size; 8124 dst = nk_ptr_add(void, temp, capacity - back_size); 8125 src = nk_ptr_add(void, temp, b->size); 8126 NK_MEMCPY(dst, src, back_size); 8127 b->size = capacity - back_size; 8128 } 8129 return temp; 8130 } 8131 NK_LIB void* 8132 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8133 nk_size size, nk_size align) 8134 { 8135 int full; 8136 nk_size alignment; 8137 void *unaligned; 8138 void *memory; 8139 8140 NK_ASSERT(b); 8141 NK_ASSERT(size); 8142 if (!b || !size) return 0; 8143 b->needed += size; 8144 8145 /* calculate total size with needed alignment + size */ 8146 if (type == NK_BUFFER_FRONT) 8147 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8148 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8149 memory = nk_buffer_align(unaligned, align, &alignment, type); 8150 8151 /* check if buffer has enough memory*/ 8152 if (type == NK_BUFFER_FRONT) 8153 full = ((b->allocated + size + alignment) > b->size); 8154 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated); 8155 8156 if (full) { 8157 nk_size capacity; 8158 if (b->type != NK_BUFFER_DYNAMIC) 8159 return 0; 8160 NK_ASSERT(b->pool.alloc && b->pool.free); 8161 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free) 8162 return 0; 8163 8164 /* buffer is full so allocate bigger buffer if dynamic */ 8165 capacity = (nk_size)((float)b->memory.size * b->grow_factor); 8166 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size))); 8167 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size); 8168 if (!b->memory.ptr) return 0; 8169 8170 /* align newly allocated pointer */ 8171 if (type == NK_BUFFER_FRONT) 8172 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8173 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8174 memory = nk_buffer_align(unaligned, align, &alignment, type); 8175 } 8176 if (type == NK_BUFFER_FRONT) 8177 b->allocated += size + alignment; 8178 else b->size -= (size + alignment); 8179 b->needed += alignment; 8180 b->calls++; 8181 return memory; 8182 } 8183 NK_API void 8184 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8185 const void *memory, nk_size size, nk_size align) 8186 { 8187 void *mem = nk_buffer_alloc(b, type, size, align); 8188 if (!mem) return; 8189 NK_MEMCPY(mem, memory, size); 8190 } 8191 NK_API void 8192 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8193 { 8194 NK_ASSERT(buffer); 8195 if (!buffer) return; 8196 buffer->marker[type].active = nk_true; 8197 if (type == NK_BUFFER_BACK) 8198 buffer->marker[type].offset = buffer->size; 8199 else buffer->marker[type].offset = buffer->allocated; 8200 } 8201 NK_API void 8202 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8203 { 8204 NK_ASSERT(buffer); 8205 if (!buffer) return; 8206 if (type == NK_BUFFER_BACK) { 8207 /* reset back buffer either back to marker or empty */ 8208 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset); 8209 if (buffer->marker[type].active) 8210 buffer->size = buffer->marker[type].offset; 8211 else buffer->size = buffer->memory.size; 8212 buffer->marker[type].active = nk_false; 8213 } else { 8214 /* reset front buffer either back to back marker or empty */ 8215 buffer->needed -= (buffer->allocated - buffer->marker[type].offset); 8216 if (buffer->marker[type].active) 8217 buffer->allocated = buffer->marker[type].offset; 8218 else buffer->allocated = 0; 8219 buffer->marker[type].active = nk_false; 8220 } 8221 } 8222 NK_API void 8223 nk_buffer_clear(struct nk_buffer *b) 8224 { 8225 NK_ASSERT(b); 8226 if (!b) return; 8227 b->allocated = 0; 8228 b->size = b->memory.size; 8229 b->calls = 0; 8230 b->needed = 0; 8231 } 8232 NK_API void 8233 nk_buffer_free(struct nk_buffer *b) 8234 { 8235 NK_ASSERT(b); 8236 if (!b || !b->memory.ptr) return; 8237 if (b->type == NK_BUFFER_FIXED) return; 8238 if (!b->pool.free) return; 8239 NK_ASSERT(b->pool.free); 8240 b->pool.free(b->pool.userdata, b->memory.ptr); 8241 } 8242 NK_API void 8243 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b) 8244 { 8245 NK_ASSERT(b); 8246 NK_ASSERT(s); 8247 if (!s || !b) return; 8248 s->allocated = b->allocated; 8249 s->size = b->memory.size; 8250 s->needed = b->needed; 8251 s->memory = b->memory.ptr; 8252 s->calls = b->calls; 8253 } 8254 NK_API void* 8255 nk_buffer_memory(struct nk_buffer *buffer) 8256 { 8257 NK_ASSERT(buffer); 8258 if (!buffer) return 0; 8259 return buffer->memory.ptr; 8260 } 8261 NK_API const void* 8262 nk_buffer_memory_const(const struct nk_buffer *buffer) 8263 { 8264 NK_ASSERT(buffer); 8265 if (!buffer) return 0; 8266 return buffer->memory.ptr; 8267 } 8268 NK_API nk_size 8269 nk_buffer_total(struct nk_buffer *buffer) 8270 { 8271 NK_ASSERT(buffer); 8272 if (!buffer) return 0; 8273 return buffer->memory.size; 8274 } 8275 8276 8277 8278 8279 8280 /* =============================================================== 8281 * 8282 * STRING 8283 * 8284 * ===============================================================*/ 8285 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8286 NK_API void 8287 nk_str_init_default(struct nk_str *str) 8288 { 8289 struct nk_allocator alloc; 8290 alloc.userdata.ptr = 0; 8291 alloc.alloc = nk_malloc; 8292 alloc.free = nk_mfree; 8293 nk_buffer_init(&str->buffer, &alloc, 32); 8294 str->len = 0; 8295 } 8296 #endif 8297 8298 NK_API void 8299 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size) 8300 { 8301 nk_buffer_init(&str->buffer, alloc, size); 8302 str->len = 0; 8303 } 8304 NK_API void 8305 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size) 8306 { 8307 nk_buffer_init_fixed(&str->buffer, memory, size); 8308 str->len = 0; 8309 } 8310 NK_API int 8311 nk_str_append_text_char(struct nk_str *s, const char *str, int len) 8312 { 8313 char *mem; 8314 NK_ASSERT(s); 8315 NK_ASSERT(str); 8316 if (!s || !str || !len) return 0; 8317 mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8318 if (!mem) return 0; 8319 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8320 s->len += nk_utf_len(str, len); 8321 return len; 8322 } 8323 NK_API int 8324 nk_str_append_str_char(struct nk_str *s, const char *str) 8325 { 8326 return nk_str_append_text_char(s, str, nk_strlen(str)); 8327 } 8328 NK_API int 8329 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len) 8330 { 8331 int i = 0; 8332 int byte_len = 0; 8333 nk_rune unicode; 8334 if (!str || !text || !len) return 0; 8335 for (i = 0; i < len; ++i) 8336 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8337 nk_str_append_text_char(str, text, byte_len); 8338 return len; 8339 } 8340 NK_API int 8341 nk_str_append_str_utf8(struct nk_str *str, const char *text) 8342 { 8343 int runes = 0; 8344 int byte_len = 0; 8345 int num_runes = 0; 8346 int glyph_len = 0; 8347 nk_rune unicode; 8348 if (!str || !text) return 0; 8349 8350 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8351 while (unicode != '\0' && glyph_len) { 8352 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8353 byte_len += glyph_len; 8354 num_runes++; 8355 } 8356 nk_str_append_text_char(str, text, byte_len); 8357 return runes; 8358 } 8359 NK_API int 8360 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) 8361 { 8362 int i = 0; 8363 int byte_len = 0; 8364 nk_glyph glyph; 8365 8366 NK_ASSERT(str); 8367 if (!str || !text || !len) return 0; 8368 for (i = 0; i < len; ++i) { 8369 byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE); 8370 if (!byte_len) break; 8371 nk_str_append_text_char(str, glyph, byte_len); 8372 } 8373 return len; 8374 } 8375 NK_API int 8376 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes) 8377 { 8378 int i = 0; 8379 nk_glyph glyph; 8380 int byte_len; 8381 NK_ASSERT(str); 8382 if (!str || !runes) return 0; 8383 while (runes[i] != '\0') { 8384 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8385 nk_str_append_text_char(str, glyph, byte_len); 8386 i++; 8387 } 8388 return i; 8389 } 8390 NK_API int 8391 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len) 8392 { 8393 int i; 8394 void *mem; 8395 char *src; 8396 char *dst; 8397 8398 int copylen; 8399 NK_ASSERT(s); 8400 NK_ASSERT(str); 8401 NK_ASSERT(len >= 0); 8402 if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0; 8403 if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) && 8404 (s->buffer.type == NK_BUFFER_FIXED)) return 0; 8405 8406 copylen = (int)s->buffer.allocated - pos; 8407 if (!copylen) { 8408 nk_str_append_text_char(s, str, len); 8409 return 1; 8410 } 8411 mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8412 if (!mem) return 0; 8413 8414 /* memmove */ 8415 NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0); 8416 NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0); 8417 dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1)); 8418 src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1)); 8419 for (i = 0; i < copylen; ++i) *dst-- = *src--; 8420 mem = nk_ptr_add(void, s->buffer.memory.ptr, pos); 8421 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8422 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8423 return 1; 8424 } 8425 NK_API int 8426 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len) 8427 { 8428 int glyph_len; 8429 nk_rune unicode; 8430 const char *begin; 8431 const char *buffer; 8432 8433 NK_ASSERT(str); 8434 NK_ASSERT(cstr); 8435 NK_ASSERT(len); 8436 if (!str || !cstr || !len) return 0; 8437 begin = nk_str_at_rune(str, pos, &unicode, &glyph_len); 8438 if (!str->len) 8439 return nk_str_append_text_char(str, cstr, len); 8440 buffer = nk_str_get_const(str); 8441 if (!begin) return 0; 8442 return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len); 8443 } 8444 NK_API int 8445 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len) 8446 { 8447 return nk_str_insert_text_utf8(str, pos, text, len); 8448 } 8449 NK_API int 8450 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text) 8451 { 8452 return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text)); 8453 } 8454 NK_API int 8455 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len) 8456 { 8457 int i = 0; 8458 int byte_len = 0; 8459 nk_rune unicode; 8460 8461 NK_ASSERT(str); 8462 NK_ASSERT(text); 8463 if (!str || !text || !len) return 0; 8464 for (i = 0; i < len; ++i) 8465 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8466 nk_str_insert_at_rune(str, pos, text, byte_len); 8467 return len; 8468 } 8469 NK_API int 8470 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) 8471 { 8472 int runes = 0; 8473 int byte_len = 0; 8474 int num_runes = 0; 8475 int glyph_len = 0; 8476 nk_rune unicode; 8477 if (!str || !text) return 0; 8478 8479 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8480 while (unicode != '\0' && glyph_len) { 8481 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8482 byte_len += glyph_len; 8483 num_runes++; 8484 } 8485 nk_str_insert_at_rune(str, pos, text, byte_len); 8486 return runes; 8487 } 8488 NK_API int 8489 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) 8490 { 8491 int i = 0; 8492 int byte_len = 0; 8493 nk_glyph glyph; 8494 8495 NK_ASSERT(str); 8496 if (!str || !runes || !len) return 0; 8497 for (i = 0; i < len; ++i) { 8498 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8499 if (!byte_len) break; 8500 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8501 } 8502 return len; 8503 } 8504 NK_API int 8505 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes) 8506 { 8507 int i = 0; 8508 nk_glyph glyph; 8509 int byte_len; 8510 NK_ASSERT(str); 8511 if (!str || !runes) return 0; 8512 while (runes[i] != '\0') { 8513 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8514 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8515 i++; 8516 } 8517 return i; 8518 } 8519 NK_API void 8520 nk_str_remove_chars(struct nk_str *s, int len) 8521 { 8522 NK_ASSERT(s); 8523 NK_ASSERT(len >= 0); 8524 if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return; 8525 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8526 s->buffer.allocated -= (nk_size)len; 8527 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8528 } 8529 NK_API void 8530 nk_str_remove_runes(struct nk_str *str, int len) 8531 { 8532 int index; 8533 const char *begin; 8534 const char *end; 8535 nk_rune unicode; 8536 8537 NK_ASSERT(str); 8538 NK_ASSERT(len >= 0); 8539 if (!str || len < 0) return; 8540 if (len >= str->len) { 8541 str->len = 0; 8542 return; 8543 } 8544 8545 index = str->len - len; 8546 begin = nk_str_at_rune(str, index, &unicode, &len); 8547 end = (const char*)str->buffer.memory.ptr + str->buffer.allocated; 8548 nk_str_remove_chars(str, (int)(end-begin)+1); 8549 } 8550 NK_API void 8551 nk_str_delete_chars(struct nk_str *s, int pos, int len) 8552 { 8553 NK_ASSERT(s); 8554 if (!s || !len || (nk_size)pos > s->buffer.allocated || 8555 (nk_size)(pos + len) > s->buffer.allocated) return; 8556 8557 if ((nk_size)(pos + len) < s->buffer.allocated) { 8558 /* memmove */ 8559 char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos); 8560 char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len); 8561 NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len)); 8562 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8563 s->buffer.allocated -= (nk_size)len; 8564 } else nk_str_remove_chars(s, len); 8565 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8566 } 8567 NK_API void 8568 nk_str_delete_runes(struct nk_str *s, int pos, int len) 8569 { 8570 char *temp; 8571 nk_rune unicode; 8572 char *begin; 8573 char *end; 8574 int unused; 8575 8576 NK_ASSERT(s); 8577 NK_ASSERT(s->len >= pos + len); 8578 if (s->len < pos + len) 8579 len = NK_CLAMP(0, (s->len - pos), s->len); 8580 if (!len) return; 8581 8582 temp = (char *)s->buffer.memory.ptr; 8583 begin = nk_str_at_rune(s, pos, &unicode, &unused); 8584 if (!begin) return; 8585 s->buffer.memory.ptr = begin; 8586 end = nk_str_at_rune(s, len, &unicode, &unused); 8587 s->buffer.memory.ptr = temp; 8588 if (!end) return; 8589 nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin)); 8590 } 8591 NK_API char* 8592 nk_str_at_char(struct nk_str *s, int pos) 8593 { 8594 NK_ASSERT(s); 8595 if (!s || pos > (int)s->buffer.allocated) return 0; 8596 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8597 } 8598 NK_API char* 8599 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len) 8600 { 8601 int i = 0; 8602 int src_len = 0; 8603 int glyph_len = 0; 8604 char *text; 8605 int text_len; 8606 8607 NK_ASSERT(str); 8608 NK_ASSERT(unicode); 8609 NK_ASSERT(len); 8610 8611 if (!str || !unicode || !len) return 0; 8612 if (pos < 0) { 8613 *unicode = 0; 8614 *len = 0; 8615 return 0; 8616 } 8617 8618 text = (char*)str->buffer.memory.ptr; 8619 text_len = (int)str->buffer.allocated; 8620 glyph_len = nk_utf_decode(text, unicode, text_len); 8621 while (glyph_len) { 8622 if (i == pos) { 8623 *len = glyph_len; 8624 break; 8625 } 8626 8627 i++; 8628 src_len = src_len + glyph_len; 8629 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8630 } 8631 if (i != pos) return 0; 8632 return text + src_len; 8633 } 8634 NK_API const char* 8635 nk_str_at_char_const(const struct nk_str *s, int pos) 8636 { 8637 NK_ASSERT(s); 8638 if (!s || pos > (int)s->buffer.allocated) return 0; 8639 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8640 } 8641 NK_API const char* 8642 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len) 8643 { 8644 int i = 0; 8645 int src_len = 0; 8646 int glyph_len = 0; 8647 char *text; 8648 int text_len; 8649 8650 NK_ASSERT(str); 8651 NK_ASSERT(unicode); 8652 NK_ASSERT(len); 8653 8654 if (!str || !unicode || !len) return 0; 8655 if (pos < 0) { 8656 *unicode = 0; 8657 *len = 0; 8658 return 0; 8659 } 8660 8661 text = (char*)str->buffer.memory.ptr; 8662 text_len = (int)str->buffer.allocated; 8663 glyph_len = nk_utf_decode(text, unicode, text_len); 8664 while (glyph_len) { 8665 if (i == pos) { 8666 *len = glyph_len; 8667 break; 8668 } 8669 8670 i++; 8671 src_len = src_len + glyph_len; 8672 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8673 } 8674 if (i != pos) return 0; 8675 return text + src_len; 8676 } 8677 NK_API nk_rune 8678 nk_str_rune_at(const struct nk_str *str, int pos) 8679 { 8680 int len; 8681 nk_rune unicode = 0; 8682 nk_str_at_const(str, pos, &unicode, &len); 8683 return unicode; 8684 } 8685 NK_API char* 8686 nk_str_get(struct nk_str *s) 8687 { 8688 NK_ASSERT(s); 8689 if (!s || !s->len || !s->buffer.allocated) return 0; 8690 return (char*)s->buffer.memory.ptr; 8691 } 8692 NK_API const char* 8693 nk_str_get_const(const struct nk_str *s) 8694 { 8695 NK_ASSERT(s); 8696 if (!s || !s->len || !s->buffer.allocated) return 0; 8697 return (const char*)s->buffer.memory.ptr; 8698 } 8699 NK_API int 8700 nk_str_len(struct nk_str *s) 8701 { 8702 NK_ASSERT(s); 8703 if (!s || !s->len || !s->buffer.allocated) return 0; 8704 return s->len; 8705 } 8706 NK_API int 8707 nk_str_len_char(struct nk_str *s) 8708 { 8709 NK_ASSERT(s); 8710 if (!s || !s->len || !s->buffer.allocated) return 0; 8711 return (int)s->buffer.allocated; 8712 } 8713 NK_API void 8714 nk_str_clear(struct nk_str *str) 8715 { 8716 NK_ASSERT(str); 8717 nk_buffer_clear(&str->buffer); 8718 str->len = 0; 8719 } 8720 NK_API void 8721 nk_str_free(struct nk_str *str) 8722 { 8723 NK_ASSERT(str); 8724 nk_buffer_free(&str->buffer); 8725 str->len = 0; 8726 } 8727 8728 8729 8730 8731 8732 /* ============================================================== 8733 * 8734 * DRAW 8735 * 8736 * ===============================================================*/ 8737 NK_LIB void 8738 nk_command_buffer_init(struct nk_command_buffer *cb, 8739 struct nk_buffer *b, enum nk_command_clipping clip) 8740 { 8741 NK_ASSERT(cb); 8742 NK_ASSERT(b); 8743 if (!cb || !b) return; 8744 cb->base = b; 8745 cb->use_clipping = (int)clip; 8746 cb->begin = b->allocated; 8747 cb->end = b->allocated; 8748 cb->last = b->allocated; 8749 } 8750 NK_LIB void 8751 nk_command_buffer_reset(struct nk_command_buffer *b) 8752 { 8753 NK_ASSERT(b); 8754 if (!b) return; 8755 b->begin = 0; 8756 b->end = 0; 8757 b->last = 0; 8758 b->clip = nk_null_rect; 8759 #ifdef NK_INCLUDE_COMMAND_USERDATA 8760 b->userdata.ptr = 0; 8761 #endif 8762 } 8763 NK_LIB void* 8764 nk_command_buffer_push(struct nk_command_buffer* b, 8765 enum nk_command_type t, nk_size size) 8766 { 8767 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command); 8768 struct nk_command *cmd; 8769 nk_size alignment; 8770 void *unaligned; 8771 void *memory; 8772 8773 NK_ASSERT(b); 8774 NK_ASSERT(b->base); 8775 if (!b) return 0; 8776 cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align); 8777 if (!cmd) return 0; 8778 8779 /* make sure the offset to the next command is aligned */ 8780 b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr); 8781 unaligned = (nk_byte*)cmd + size; 8782 memory = NK_ALIGN_PTR(unaligned, align); 8783 alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8784 #ifdef NK_ZERO_COMMAND_MEMORY 8785 NK_MEMSET(cmd, 0, size + alignment); 8786 #endif 8787 8788 cmd->type = t; 8789 cmd->next = b->base->allocated + alignment; 8790 #ifdef NK_INCLUDE_COMMAND_USERDATA 8791 cmd->userdata = b->userdata; 8792 #endif 8793 b->end = cmd->next; 8794 return cmd; 8795 } 8796 NK_API void 8797 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r) 8798 { 8799 struct nk_command_scissor *cmd; 8800 NK_ASSERT(b); 8801 if (!b) return; 8802 8803 b->clip.x = r.x; 8804 b->clip.y = r.y; 8805 b->clip.w = r.w; 8806 b->clip.h = r.h; 8807 cmd = (struct nk_command_scissor*) 8808 nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd)); 8809 8810 if (!cmd) return; 8811 cmd->x = (short)r.x; 8812 cmd->y = (short)r.y; 8813 cmd->w = (unsigned short)NK_MAX(0, r.w); 8814 cmd->h = (unsigned short)NK_MAX(0, r.h); 8815 } 8816 NK_API void 8817 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, 8818 float x1, float y1, float line_thickness, struct nk_color c) 8819 { 8820 struct nk_command_line *cmd; 8821 NK_ASSERT(b); 8822 if (!b || line_thickness <= 0) return; 8823 cmd = (struct nk_command_line*) 8824 nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd)); 8825 if (!cmd) return; 8826 cmd->line_thickness = (unsigned short)line_thickness; 8827 cmd->begin.x = (short)x0; 8828 cmd->begin.y = (short)y0; 8829 cmd->end.x = (short)x1; 8830 cmd->end.y = (short)y1; 8831 cmd->color = c; 8832 } 8833 NK_API void 8834 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay, 8835 float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, 8836 float bx, float by, float line_thickness, struct nk_color col) 8837 { 8838 struct nk_command_curve *cmd; 8839 NK_ASSERT(b); 8840 if (!b || col.a == 0 || line_thickness <= 0) return; 8841 8842 cmd = (struct nk_command_curve*) 8843 nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd)); 8844 if (!cmd) return; 8845 cmd->line_thickness = (unsigned short)line_thickness; 8846 cmd->begin.x = (short)ax; 8847 cmd->begin.y = (short)ay; 8848 cmd->ctrl[0].x = (short)ctrl0x; 8849 cmd->ctrl[0].y = (short)ctrl0y; 8850 cmd->ctrl[1].x = (short)ctrl1x; 8851 cmd->ctrl[1].y = (short)ctrl1y; 8852 cmd->end.x = (short)bx; 8853 cmd->end.y = (short)by; 8854 cmd->color = col; 8855 } 8856 NK_API void 8857 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect, 8858 float rounding, float line_thickness, struct nk_color c) 8859 { 8860 struct nk_command_rect *cmd; 8861 NK_ASSERT(b); 8862 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return; 8863 if (b->use_clipping) { 8864 const struct nk_rect *clip = &b->clip; 8865 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8866 clip->x, clip->y, clip->w, clip->h)) return; 8867 } 8868 cmd = (struct nk_command_rect*) 8869 nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd)); 8870 if (!cmd) return; 8871 cmd->rounding = (unsigned short)rounding; 8872 cmd->line_thickness = (unsigned short)line_thickness; 8873 cmd->x = (short)rect.x; 8874 cmd->y = (short)rect.y; 8875 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8876 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8877 cmd->color = c; 8878 } 8879 NK_API void 8880 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect, 8881 float rounding, struct nk_color c) 8882 { 8883 struct nk_command_rect_filled *cmd; 8884 NK_ASSERT(b); 8885 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; 8886 if (b->use_clipping) { 8887 const struct nk_rect *clip = &b->clip; 8888 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8889 clip->x, clip->y, clip->w, clip->h)) return; 8890 } 8891 8892 cmd = (struct nk_command_rect_filled*) 8893 nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd)); 8894 if (!cmd) return; 8895 cmd->rounding = (unsigned short)rounding; 8896 cmd->x = (short)rect.x; 8897 cmd->y = (short)rect.y; 8898 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8899 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8900 cmd->color = c; 8901 } 8902 NK_API void 8903 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect, 8904 struct nk_color left, struct nk_color top, struct nk_color right, 8905 struct nk_color bottom) 8906 { 8907 struct nk_command_rect_multi_color *cmd; 8908 NK_ASSERT(b); 8909 if (!b || rect.w == 0 || rect.h == 0) return; 8910 if (b->use_clipping) { 8911 const struct nk_rect *clip = &b->clip; 8912 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8913 clip->x, clip->y, clip->w, clip->h)) return; 8914 } 8915 8916 cmd = (struct nk_command_rect_multi_color*) 8917 nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd)); 8918 if (!cmd) return; 8919 cmd->x = (short)rect.x; 8920 cmd->y = (short)rect.y; 8921 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8922 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8923 cmd->left = left; 8924 cmd->top = top; 8925 cmd->right = right; 8926 cmd->bottom = bottom; 8927 } 8928 NK_API void 8929 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r, 8930 float line_thickness, struct nk_color c) 8931 { 8932 struct nk_command_circle *cmd; 8933 if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return; 8934 if (b->use_clipping) { 8935 const struct nk_rect *clip = &b->clip; 8936 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 8937 return; 8938 } 8939 8940 cmd = (struct nk_command_circle*) 8941 nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd)); 8942 if (!cmd) return; 8943 cmd->line_thickness = (unsigned short)line_thickness; 8944 cmd->x = (short)r.x; 8945 cmd->y = (short)r.y; 8946 cmd->w = (unsigned short)NK_MAX(r.w, 0); 8947 cmd->h = (unsigned short)NK_MAX(r.h, 0); 8948 cmd->color = c; 8949 } 8950 NK_API void 8951 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c) 8952 { 8953 struct nk_command_circle_filled *cmd; 8954 NK_ASSERT(b); 8955 if (!b || c.a == 0 || r.w == 0 || r.h == 0) return; 8956 if (b->use_clipping) { 8957 const struct nk_rect *clip = &b->clip; 8958 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 8959 return; 8960 } 8961 8962 cmd = (struct nk_command_circle_filled*) 8963 nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); 8964 if (!cmd) return; 8965 cmd->x = (short)r.x; 8966 cmd->y = (short)r.y; 8967 cmd->w = (unsigned short)NK_MAX(r.w, 0); 8968 cmd->h = (unsigned short)NK_MAX(r.h, 0); 8969 cmd->color = c; 8970 } 8971 NK_API void 8972 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 8973 float a_min, float a_max, float line_thickness, struct nk_color c) 8974 { 8975 struct nk_command_arc *cmd; 8976 if (!b || c.a == 0 || line_thickness <= 0) return; 8977 cmd = (struct nk_command_arc*) 8978 nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd)); 8979 if (!cmd) return; 8980 cmd->line_thickness = (unsigned short)line_thickness; 8981 cmd->cx = (short)cx; 8982 cmd->cy = (short)cy; 8983 cmd->r = (unsigned short)radius; 8984 cmd->a[0] = a_min; 8985 cmd->a[1] = a_max; 8986 cmd->color = c; 8987 } 8988 NK_API void 8989 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 8990 float a_min, float a_max, struct nk_color c) 8991 { 8992 struct nk_command_arc_filled *cmd; 8993 NK_ASSERT(b); 8994 if (!b || c.a == 0) return; 8995 cmd = (struct nk_command_arc_filled*) 8996 nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd)); 8997 if (!cmd) return; 8998 cmd->cx = (short)cx; 8999 cmd->cy = (short)cy; 9000 cmd->r = (unsigned short)radius; 9001 cmd->a[0] = a_min; 9002 cmd->a[1] = a_max; 9003 cmd->color = c; 9004 } 9005 NK_API void 9006 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 9007 float y1, float x2, float y2, float line_thickness, struct nk_color c) 9008 { 9009 struct nk_command_triangle *cmd; 9010 NK_ASSERT(b); 9011 if (!b || c.a == 0 || line_thickness <= 0) return; 9012 if (b->use_clipping) { 9013 const struct nk_rect *clip = &b->clip; 9014 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 9015 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 9016 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 9017 return; 9018 } 9019 9020 cmd = (struct nk_command_triangle*) 9021 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd)); 9022 if (!cmd) return; 9023 cmd->line_thickness = (unsigned short)line_thickness; 9024 cmd->a.x = (short)x0; 9025 cmd->a.y = (short)y0; 9026 cmd->b.x = (short)x1; 9027 cmd->b.y = (short)y1; 9028 cmd->c.x = (short)x2; 9029 cmd->c.y = (short)y2; 9030 cmd->color = c; 9031 } 9032 NK_API void 9033 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 9034 float y1, float x2, float y2, struct nk_color c) 9035 { 9036 struct nk_command_triangle_filled *cmd; 9037 NK_ASSERT(b); 9038 if (!b || c.a == 0) return; 9039 if (!b) return; 9040 if (b->use_clipping) { 9041 const struct nk_rect *clip = &b->clip; 9042 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 9043 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 9044 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 9045 return; 9046 } 9047 9048 cmd = (struct nk_command_triangle_filled*) 9049 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); 9050 if (!cmd) return; 9051 cmd->a.x = (short)x0; 9052 cmd->a.y = (short)y0; 9053 cmd->b.x = (short)x1; 9054 cmd->b.y = (short)y1; 9055 cmd->c.x = (short)x2; 9056 cmd->c.y = (short)y2; 9057 cmd->color = c; 9058 } 9059 NK_API void 9060 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count, 9061 float line_thickness, struct nk_color col) 9062 { 9063 int i; 9064 nk_size size = 0; 9065 struct nk_command_polygon *cmd; 9066 9067 NK_ASSERT(b); 9068 if (!b || col.a == 0 || line_thickness <= 0) return; 9069 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9070 cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size); 9071 if (!cmd) return; 9072 cmd->color = col; 9073 cmd->line_thickness = (unsigned short)line_thickness; 9074 cmd->point_count = (unsigned short)point_count; 9075 for (i = 0; i < point_count; ++i) { 9076 cmd->points[i].x = (short)points[i*2]; 9077 cmd->points[i].y = (short)points[i*2+1]; 9078 } 9079 } 9080 NK_API void 9081 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count, 9082 struct nk_color col) 9083 { 9084 int i; 9085 nk_size size = 0; 9086 struct nk_command_polygon_filled *cmd; 9087 9088 NK_ASSERT(b); 9089 if (!b || col.a == 0) return; 9090 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9091 cmd = (struct nk_command_polygon_filled*) 9092 nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size); 9093 if (!cmd) return; 9094 cmd->color = col; 9095 cmd->point_count = (unsigned short)point_count; 9096 for (i = 0; i < point_count; ++i) { 9097 cmd->points[i].x = (short)points[i*2+0]; 9098 cmd->points[i].y = (short)points[i*2+1]; 9099 } 9100 } 9101 NK_API void 9102 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count, 9103 float line_thickness, struct nk_color col) 9104 { 9105 int i; 9106 nk_size size = 0; 9107 struct nk_command_polyline *cmd; 9108 9109 NK_ASSERT(b); 9110 if (!b || col.a == 0 || line_thickness <= 0) return; 9111 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9112 cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size); 9113 if (!cmd) return; 9114 cmd->color = col; 9115 cmd->point_count = (unsigned short)point_count; 9116 cmd->line_thickness = (unsigned short)line_thickness; 9117 for (i = 0; i < point_count; ++i) { 9118 cmd->points[i].x = (short)points[i*2]; 9119 cmd->points[i].y = (short)points[i*2+1]; 9120 } 9121 } 9122 NK_API void 9123 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r, 9124 const struct nk_image *img, struct nk_color col) 9125 { 9126 struct nk_command_image *cmd; 9127 NK_ASSERT(b); 9128 if (!b) return; 9129 if (b->use_clipping) { 9130 const struct nk_rect *c = &b->clip; 9131 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)) 9132 return; 9133 } 9134 9135 cmd = (struct nk_command_image*) 9136 nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd)); 9137 if (!cmd) return; 9138 cmd->x = (short)r.x; 9139 cmd->y = (short)r.y; 9140 cmd->w = (unsigned short)NK_MAX(0, r.w); 9141 cmd->h = (unsigned short)NK_MAX(0, r.h); 9142 cmd->img = *img; 9143 cmd->col = col; 9144 } 9145 NK_API void 9146 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r, 9147 nk_command_custom_callback cb, nk_handle usr) 9148 { 9149 struct nk_command_custom *cmd; 9150 NK_ASSERT(b); 9151 if (!b) return; 9152 if (b->use_clipping) { 9153 const struct nk_rect *c = &b->clip; 9154 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)) 9155 return; 9156 } 9157 9158 cmd = (struct nk_command_custom*) 9159 nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd)); 9160 if (!cmd) return; 9161 cmd->x = (short)r.x; 9162 cmd->y = (short)r.y; 9163 cmd->w = (unsigned short)NK_MAX(0, r.w); 9164 cmd->h = (unsigned short)NK_MAX(0, r.h); 9165 cmd->callback_data = usr; 9166 cmd->callback = cb; 9167 } 9168 NK_API void 9169 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r, 9170 const char *string, int length, const struct nk_user_font *font, 9171 struct nk_color bg, struct nk_color fg) 9172 { 9173 float text_width = 0; 9174 struct nk_command_text *cmd; 9175 9176 NK_ASSERT(b); 9177 NK_ASSERT(font); 9178 if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; 9179 if (b->use_clipping) { 9180 const struct nk_rect *c = &b->clip; 9181 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)) 9182 return; 9183 } 9184 9185 /* make sure text fits inside bounds */ 9186 text_width = font->width(font->userdata, font->height, string, length); 9187 if (text_width > r.w){ 9188 int glyphs = 0; 9189 float txt_width = (float)text_width; 9190 length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0); 9191 } 9192 9193 if (!length) return; 9194 cmd = (struct nk_command_text*) 9195 nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1)); 9196 if (!cmd) return; 9197 cmd->x = (short)r.x; 9198 cmd->y = (short)r.y; 9199 cmd->w = (unsigned short)r.w; 9200 cmd->h = (unsigned short)r.h; 9201 cmd->background = bg; 9202 cmd->foreground = fg; 9203 cmd->font = font; 9204 cmd->length = length; 9205 cmd->height = font->height; 9206 NK_MEMCPY(cmd->string, string, (nk_size)length); 9207 cmd->string[length] = '\0'; 9208 } 9209 9210 9211 9212 9213 9214 /* =============================================================== 9215 * 9216 * VERTEX 9217 * 9218 * ===============================================================*/ 9219 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 9220 NK_API void 9221 nk_draw_list_init(struct nk_draw_list *list) 9222 { 9223 nk_size i = 0; 9224 NK_ASSERT(list); 9225 if (!list) return; 9226 nk_zero(list, sizeof(*list)); 9227 for (i = 0; i < NK_LEN(list->circle_vtx); ++i) { 9228 const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI; 9229 list->circle_vtx[i].x = (float)NK_COS(a); 9230 list->circle_vtx[i].y = (float)NK_SIN(a); 9231 } 9232 } 9233 NK_API void 9234 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config, 9235 struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, 9236 enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa) 9237 { 9238 NK_ASSERT(canvas); 9239 NK_ASSERT(config); 9240 NK_ASSERT(cmds); 9241 NK_ASSERT(vertices); 9242 NK_ASSERT(elements); 9243 if (!canvas || !config || !cmds || !vertices || !elements) 9244 return; 9245 9246 canvas->buffer = cmds; 9247 canvas->config = *config; 9248 canvas->elements = elements; 9249 canvas->vertices = vertices; 9250 canvas->line_AA = line_aa; 9251 canvas->shape_AA = shape_aa; 9252 canvas->clip_rect = nk_null_rect; 9253 9254 canvas->cmd_offset = 0; 9255 canvas->element_count = 0; 9256 canvas->vertex_count = 0; 9257 canvas->cmd_offset = 0; 9258 canvas->cmd_count = 0; 9259 canvas->path_count = 0; 9260 } 9261 NK_API const struct nk_draw_command* 9262 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9263 { 9264 nk_byte *memory; 9265 nk_size offset; 9266 const struct nk_draw_command *cmd; 9267 9268 NK_ASSERT(buffer); 9269 if (!buffer || !buffer->size || !canvas->cmd_count) 9270 return 0; 9271 9272 memory = (nk_byte*)buffer->memory.ptr; 9273 offset = buffer->memory.size - canvas->cmd_offset; 9274 cmd = nk_ptr_add(const struct nk_draw_command, memory, offset); 9275 return cmd; 9276 } 9277 NK_API const struct nk_draw_command* 9278 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9279 { 9280 nk_size size; 9281 nk_size offset; 9282 nk_byte *memory; 9283 const struct nk_draw_command *end; 9284 9285 NK_ASSERT(buffer); 9286 NK_ASSERT(canvas); 9287 if (!buffer || !canvas) 9288 return 0; 9289 9290 memory = (nk_byte*)buffer->memory.ptr; 9291 size = buffer->memory.size; 9292 offset = size - canvas->cmd_offset; 9293 end = nk_ptr_add(const struct nk_draw_command, memory, offset); 9294 end -= (canvas->cmd_count-1); 9295 return end; 9296 } 9297 NK_API const struct nk_draw_command* 9298 nk__draw_list_next(const struct nk_draw_command *cmd, 9299 const struct nk_buffer *buffer, const struct nk_draw_list *canvas) 9300 { 9301 const struct nk_draw_command *end; 9302 NK_ASSERT(buffer); 9303 NK_ASSERT(canvas); 9304 if (!cmd || !buffer || !canvas) 9305 return 0; 9306 9307 end = nk__draw_list_end(canvas, buffer); 9308 if (cmd <= end) return 0; 9309 return (cmd-1); 9310 } 9311 NK_INTERN struct nk_vec2* 9312 nk_draw_list_alloc_path(struct nk_draw_list *list, int count) 9313 { 9314 struct nk_vec2 *points; 9315 NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2); 9316 NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2); 9317 points = (struct nk_vec2*) 9318 nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT, 9319 point_size * (nk_size)count, point_align); 9320 9321 if (!points) return 0; 9322 if (!list->path_offset) { 9323 void *memory = nk_buffer_memory(list->buffer); 9324 list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory); 9325 } 9326 list->path_count += (unsigned int)count; 9327 return points; 9328 } 9329 NK_INTERN struct nk_vec2 9330 nk_draw_list_path_last(struct nk_draw_list *list) 9331 { 9332 void *memory; 9333 struct nk_vec2 *point; 9334 NK_ASSERT(list->path_count); 9335 memory = nk_buffer_memory(list->buffer); 9336 point = nk_ptr_add(struct nk_vec2, memory, list->path_offset); 9337 point += (list->path_count-1); 9338 return *point; 9339 } 9340 NK_INTERN struct nk_draw_command* 9341 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip, 9342 nk_handle texture) 9343 { 9344 NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command); 9345 NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command); 9346 struct nk_draw_command *cmd; 9347 9348 NK_ASSERT(list); 9349 cmd = (struct nk_draw_command*) 9350 nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align); 9351 9352 if (!cmd) return 0; 9353 if (!list->cmd_count) { 9354 nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer); 9355 nk_size total = nk_buffer_total(list->buffer); 9356 memory = nk_ptr_add(nk_byte, memory, total); 9357 list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd); 9358 } 9359 9360 cmd->elem_count = 0; 9361 cmd->clip_rect = clip; 9362 cmd->texture = texture; 9363 #ifdef NK_INCLUDE_COMMAND_USERDATA 9364 cmd->userdata = list->userdata; 9365 #endif 9366 9367 list->cmd_count++; 9368 list->clip_rect = clip; 9369 return cmd; 9370 } 9371 NK_INTERN struct nk_draw_command* 9372 nk_draw_list_command_last(struct nk_draw_list *list) 9373 { 9374 void *memory; 9375 nk_size size; 9376 struct nk_draw_command *cmd; 9377 NK_ASSERT(list->cmd_count); 9378 9379 memory = nk_buffer_memory(list->buffer); 9380 size = nk_buffer_total(list->buffer); 9381 cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset); 9382 return (cmd - (list->cmd_count-1)); 9383 } 9384 NK_INTERN void 9385 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect) 9386 { 9387 NK_ASSERT(list); 9388 if (!list) return; 9389 if (!list->cmd_count) { 9390 nk_draw_list_push_command(list, rect, list->config.null.texture); 9391 } else { 9392 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9393 if (prev->elem_count == 0) 9394 prev->clip_rect = rect; 9395 nk_draw_list_push_command(list, rect, prev->texture); 9396 } 9397 } 9398 NK_INTERN void 9399 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture) 9400 { 9401 NK_ASSERT(list); 9402 if (!list) return; 9403 if (!list->cmd_count) { 9404 nk_draw_list_push_command(list, nk_null_rect, texture); 9405 } else { 9406 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9407 if (prev->elem_count == 0) { 9408 prev->texture = texture; 9409 #ifdef NK_INCLUDE_COMMAND_USERDATA 9410 prev->userdata = list->userdata; 9411 #endif 9412 } else if (prev->texture.id != texture.id 9413 #ifdef NK_INCLUDE_COMMAND_USERDATA 9414 || prev->userdata.id != list->userdata.id 9415 #endif 9416 ) nk_draw_list_push_command(list, prev->clip_rect, texture); 9417 } 9418 } 9419 #ifdef NK_INCLUDE_COMMAND_USERDATA 9420 NK_API void 9421 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata) 9422 { 9423 list->userdata = userdata; 9424 } 9425 #endif 9426 NK_INTERN void* 9427 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) 9428 { 9429 void *vtx; 9430 NK_ASSERT(list); 9431 if (!list) return 0; 9432 vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, 9433 list->config.vertex_size*count, list->config.vertex_alignment); 9434 if (!vtx) return 0; 9435 list->vertex_count += (unsigned int)count; 9436 9437 /* This assert triggers because your are drawing a lot of stuff and nuklear 9438 * defined `nk_draw_index` as `nk_ushort` to safe space be default. 9439 * 9440 * So you reached the maximum number of indicies or rather vertexes. 9441 * To solve this issue please change typdef `nk_draw_index` to `nk_uint` 9442 * and don't forget to specify the new element size in your drawing 9443 * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements` 9444 * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`. 9445 * Sorry for the inconvenience. */ 9446 if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX && 9447 "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem")); 9448 return vtx; 9449 } 9450 NK_INTERN nk_draw_index* 9451 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count) 9452 { 9453 nk_draw_index *ids; 9454 struct nk_draw_command *cmd; 9455 NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index); 9456 NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index); 9457 NK_ASSERT(list); 9458 if (!list) return 0; 9459 9460 ids = (nk_draw_index*) 9461 nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align); 9462 if (!ids) return 0; 9463 cmd = nk_draw_list_command_last(list); 9464 list->element_count += (unsigned int)count; 9465 cmd->elem_count += (unsigned int)count; 9466 return ids; 9467 } 9468 NK_INTERN int 9469 nk_draw_vertex_layout_element_is_end_of_layout( 9470 const struct nk_draw_vertex_layout_element *element) 9471 { 9472 return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT || 9473 element->format == NK_FORMAT_COUNT); 9474 } 9475 NK_INTERN void 9476 nk_draw_vertex_color(void *attr, const float *vals, 9477 enum nk_draw_vertex_layout_format format) 9478 { 9479 /* if this triggers you tried to provide a value format for a color */ 9480 float val[4]; 9481 NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN); 9482 NK_ASSERT(format <= NK_FORMAT_COLOR_END); 9483 if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return; 9484 9485 val[0] = NK_SATURATE(vals[0]); 9486 val[1] = NK_SATURATE(vals[1]); 9487 val[2] = NK_SATURATE(vals[2]); 9488 val[3] = NK_SATURATE(vals[3]); 9489 9490 switch (format) { 9491 default: NK_ASSERT(0 && "Invalid vertex layout color format"); break; 9492 case NK_FORMAT_R8G8B8A8: 9493 case NK_FORMAT_R8G8B8: { 9494 struct nk_color col = nk_rgba_fv(val); 9495 NK_MEMCPY(attr, &col.r, sizeof(col)); 9496 } break; 9497 case NK_FORMAT_B8G8R8A8: { 9498 struct nk_color col = nk_rgba_fv(val); 9499 struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a); 9500 NK_MEMCPY(attr, &bgra, sizeof(bgra)); 9501 } break; 9502 case NK_FORMAT_R16G15B16: { 9503 nk_ushort col[3]; 9504 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9505 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9506 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9507 NK_MEMCPY(attr, col, sizeof(col)); 9508 } break; 9509 case NK_FORMAT_R16G15B16A16: { 9510 nk_ushort col[4]; 9511 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9512 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9513 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9514 col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX); 9515 NK_MEMCPY(attr, col, sizeof(col)); 9516 } break; 9517 case NK_FORMAT_R32G32B32: { 9518 nk_uint col[3]; 9519 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9520 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9521 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9522 NK_MEMCPY(attr, col, sizeof(col)); 9523 } break; 9524 case NK_FORMAT_R32G32B32A32: { 9525 nk_uint col[4]; 9526 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9527 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9528 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9529 col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX); 9530 NK_MEMCPY(attr, col, sizeof(col)); 9531 } break; 9532 case NK_FORMAT_R32G32B32A32_FLOAT: 9533 NK_MEMCPY(attr, val, sizeof(float)*4); 9534 break; 9535 case NK_FORMAT_R32G32B32A32_DOUBLE: { 9536 double col[4]; 9537 col[0] = (double)val[0]; 9538 col[1] = (double)val[1]; 9539 col[2] = (double)val[2]; 9540 col[3] = (double)val[3]; 9541 NK_MEMCPY(attr, col, sizeof(col)); 9542 } break; 9543 case NK_FORMAT_RGB32: 9544 case NK_FORMAT_RGBA32: { 9545 struct nk_color col = nk_rgba_fv(val); 9546 nk_uint color = nk_color_u32(col); 9547 NK_MEMCPY(attr, &color, sizeof(color)); 9548 } break; } 9549 } 9550 NK_INTERN void 9551 nk_draw_vertex_element(void *dst, const float *values, int value_count, 9552 enum nk_draw_vertex_layout_format format) 9553 { 9554 int value_index; 9555 void *attribute = dst; 9556 /* if this triggers you tried to provide a color format for a value */ 9557 NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN); 9558 if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return; 9559 for (value_index = 0; value_index < value_count; ++value_index) { 9560 switch (format) { 9561 default: NK_ASSERT(0 && "invalid vertex layout format"); break; 9562 case NK_FORMAT_SCHAR: { 9563 char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX); 9564 NK_MEMCPY(attribute, &value, sizeof(value)); 9565 attribute = (void*)((char*)attribute + sizeof(char)); 9566 } break; 9567 case NK_FORMAT_SSHORT: { 9568 nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX); 9569 NK_MEMCPY(attribute, &value, sizeof(value)); 9570 attribute = (void*)((char*)attribute + sizeof(value)); 9571 } break; 9572 case NK_FORMAT_SINT: { 9573 nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX); 9574 NK_MEMCPY(attribute, &value, sizeof(value)); 9575 attribute = (void*)((char*)attribute + sizeof(nk_int)); 9576 } break; 9577 case NK_FORMAT_UCHAR: { 9578 unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX); 9579 NK_MEMCPY(attribute, &value, sizeof(value)); 9580 attribute = (void*)((char*)attribute + sizeof(unsigned char)); 9581 } break; 9582 case NK_FORMAT_USHORT: { 9583 nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX); 9584 NK_MEMCPY(attribute, &value, sizeof(value)); 9585 attribute = (void*)((char*)attribute + sizeof(value)); 9586 } break; 9587 case NK_FORMAT_UINT: { 9588 nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX); 9589 NK_MEMCPY(attribute, &value, sizeof(value)); 9590 attribute = (void*)((char*)attribute + sizeof(nk_uint)); 9591 } break; 9592 case NK_FORMAT_FLOAT: 9593 NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index])); 9594 attribute = (void*)((char*)attribute + sizeof(float)); 9595 break; 9596 case NK_FORMAT_DOUBLE: { 9597 double value = (double)values[value_index]; 9598 NK_MEMCPY(attribute, &value, sizeof(value)); 9599 attribute = (void*)((char*)attribute + sizeof(double)); 9600 } break; 9601 } 9602 } 9603 } 9604 NK_INTERN void* 9605 nk_draw_vertex(void *dst, const struct nk_convert_config *config, 9606 struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color) 9607 { 9608 void *result = (void*)((char*)dst + config->vertex_size); 9609 const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout; 9610 while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) { 9611 void *address = (void*)((char*)dst + elem_iter->offset); 9612 switch (elem_iter->attribute) { 9613 case NK_VERTEX_ATTRIBUTE_COUNT: 9614 default: NK_ASSERT(0 && "wrong element attribute"); break; 9615 case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break; 9616 case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break; 9617 case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break; 9618 } 9619 elem_iter++; 9620 } 9621 return result; 9622 } 9623 NK_API void 9624 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points, 9625 const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed, 9626 float thickness, enum nk_anti_aliasing aliasing) 9627 { 9628 nk_size count; 9629 int thick_line; 9630 struct nk_colorf col; 9631 struct nk_colorf col_trans; 9632 NK_ASSERT(list); 9633 if (!list || points_count < 2) return; 9634 9635 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9636 count = points_count; 9637 if (!closed) count = points_count-1; 9638 thick_line = thickness > 1.0f; 9639 9640 #ifdef NK_INCLUDE_COMMAND_USERDATA 9641 nk_draw_list_push_userdata(list, list->userdata); 9642 #endif 9643 9644 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9645 nk_color_fv(&col.r, color); 9646 col_trans = col; 9647 col_trans.a = 0; 9648 9649 if (aliasing == NK_ANTI_ALIASING_ON) { 9650 /* ANTI-ALIASED STROKE */ 9651 const float AA_SIZE = 1.0f; 9652 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9653 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9654 9655 /* allocate vertices and elements */ 9656 nk_size i1 = 0; 9657 nk_size vertex_offset; 9658 nk_size index = list->vertex_count; 9659 9660 const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12); 9661 const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3); 9662 9663 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9664 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9665 9666 nk_size size; 9667 struct nk_vec2 *normals, *temp; 9668 if (!vtx || !ids) return; 9669 9670 /* temporary allocate normals + points */ 9671 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9672 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9673 size = pnt_size * ((thick_line) ? 5 : 3) * points_count; 9674 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9675 if (!normals) return; 9676 temp = normals + points_count; 9677 9678 /* make sure vertex pointer is still correct */ 9679 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9680 9681 /* calculate normals */ 9682 for (i1 = 0; i1 < count; ++i1) { 9683 const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9684 struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]); 9685 float len; 9686 9687 /* vec2 inverted length */ 9688 len = nk_vec2_len_sqr(diff); 9689 if (len != 0.0f) 9690 len = nk_inv_sqrt(len); 9691 else len = 1.0f; 9692 9693 diff = nk_vec2_muls(diff, len); 9694 normals[i1].x = diff.y; 9695 normals[i1].y = -diff.x; 9696 } 9697 9698 if (!closed) 9699 normals[points_count-1] = normals[points_count-2]; 9700 9701 if (!thick_line) { 9702 nk_size idx1, i; 9703 if (!closed) { 9704 struct nk_vec2 d; 9705 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9706 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9707 d = nk_vec2_muls(normals[points_count-1], AA_SIZE); 9708 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d); 9709 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d); 9710 } 9711 9712 /* fill elements */ 9713 idx1 = index; 9714 for (i1 = 0; i1 < count; i1++) { 9715 struct nk_vec2 dm; 9716 float dmr2; 9717 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9718 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3); 9719 9720 /* average normals */ 9721 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9722 dmr2 = dm.x * dm.x + dm.y* dm.y; 9723 if (dmr2 > 0.000001f) { 9724 float scale = 1.0f/dmr2; 9725 scale = NK_MIN(100.0f, scale); 9726 dm = nk_vec2_muls(dm, scale); 9727 } 9728 9729 dm = nk_vec2_muls(dm, AA_SIZE); 9730 temp[i2*2+0] = nk_vec2_add(points[i2], dm); 9731 temp[i2*2+1] = nk_vec2_sub(points[i2], dm); 9732 9733 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0); 9734 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9735 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0); 9736 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9737 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9738 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1); 9739 ids += 12; 9740 idx1 = idx2; 9741 } 9742 9743 /* fill vertices */ 9744 for (i = 0; i < points_count; ++i) { 9745 const struct nk_vec2 uv = list->config.null.uv; 9746 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); 9747 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); 9748 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); 9749 } 9750 } else { 9751 nk_size idx1, i; 9752 const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; 9753 if (!closed) { 9754 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE); 9755 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness); 9756 9757 temp[0] = nk_vec2_add(points[0], d1); 9758 temp[1] = nk_vec2_add(points[0], d2); 9759 temp[2] = nk_vec2_sub(points[0], d2); 9760 temp[3] = nk_vec2_sub(points[0], d1); 9761 9762 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE); 9763 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness); 9764 9765 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1); 9766 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2); 9767 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2); 9768 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1); 9769 } 9770 9771 /* add all elements */ 9772 idx1 = index; 9773 for (i1 = 0; i1 < count; ++i1) { 9774 struct nk_vec2 dm_out, dm_in; 9775 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1); 9776 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4); 9777 9778 /* average normals */ 9779 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9780 float dmr2 = dm.x * dm.x + dm.y* dm.y; 9781 if (dmr2 > 0.000001f) { 9782 float scale = 1.0f/dmr2; 9783 scale = NK_MIN(100.0f, scale); 9784 dm = nk_vec2_muls(dm, scale); 9785 } 9786 9787 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE)); 9788 dm_in = nk_vec2_muls(dm, half_inner_thickness); 9789 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out); 9790 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in); 9791 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in); 9792 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out); 9793 9794 /* add indexes */ 9795 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1); 9796 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9797 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1); 9798 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9799 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9800 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1); 9801 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2); 9802 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3); 9803 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2); 9804 ids += 18; 9805 idx1 = idx2; 9806 } 9807 9808 /* add vertices */ 9809 for (i = 0; i < points_count; ++i) { 9810 const struct nk_vec2 uv = list->config.null.uv; 9811 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); 9812 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); 9813 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); 9814 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans); 9815 } 9816 } 9817 /* free temporary normals + points */ 9818 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 9819 } else { 9820 /* NON ANTI-ALIASED STROKE */ 9821 nk_size i1 = 0; 9822 nk_size idx = list->vertex_count; 9823 const nk_size idx_count = count * 6; 9824 const nk_size vtx_count = count * 4; 9825 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9826 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9827 if (!vtx || !ids) return; 9828 9829 for (i1 = 0; i1 < count; ++i1) { 9830 float dx, dy; 9831 const struct nk_vec2 uv = list->config.null.uv; 9832 const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; 9833 const struct nk_vec2 p1 = points[i1]; 9834 const struct nk_vec2 p2 = points[i2]; 9835 struct nk_vec2 diff = nk_vec2_sub(p2, p1); 9836 float len; 9837 9838 /* vec2 inverted length */ 9839 len = nk_vec2_len_sqr(diff); 9840 if (len != 0.0f) 9841 len = nk_inv_sqrt(len); 9842 else len = 1.0f; 9843 diff = nk_vec2_muls(diff, len); 9844 9845 /* add vertices */ 9846 dx = diff.x * (thickness * 0.5f); 9847 dy = diff.y * (thickness * 0.5f); 9848 9849 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col); 9850 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col); 9851 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col); 9852 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col); 9853 9854 ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1); 9855 ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0); 9856 ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3); 9857 9858 ids += 6; 9859 idx += 4; 9860 } 9861 } 9862 } 9863 NK_API void 9864 nk_draw_list_fill_poly_convex(struct nk_draw_list *list, 9865 const struct nk_vec2 *points, const unsigned int points_count, 9866 struct nk_color color, enum nk_anti_aliasing aliasing) 9867 { 9868 struct nk_colorf col; 9869 struct nk_colorf col_trans; 9870 9871 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9872 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9873 NK_ASSERT(list); 9874 if (!list || points_count < 3) return; 9875 9876 #ifdef NK_INCLUDE_COMMAND_USERDATA 9877 nk_draw_list_push_userdata(list, list->userdata); 9878 #endif 9879 9880 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9881 nk_color_fv(&col.r, color); 9882 col_trans = col; 9883 col_trans.a = 0; 9884 9885 if (aliasing == NK_ANTI_ALIASING_ON) { 9886 nk_size i = 0; 9887 nk_size i0 = 0; 9888 nk_size i1 = 0; 9889 9890 const float AA_SIZE = 1.0f; 9891 nk_size vertex_offset = 0; 9892 nk_size index = list->vertex_count; 9893 9894 const nk_size idx_count = (points_count-2)*3 + points_count*6; 9895 const nk_size vtx_count = (points_count*2); 9896 9897 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9898 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9899 9900 nk_size size = 0; 9901 struct nk_vec2 *normals = 0; 9902 unsigned int vtx_inner_idx = (unsigned int)(index + 0); 9903 unsigned int vtx_outer_idx = (unsigned int)(index + 1); 9904 if (!vtx || !ids) return; 9905 9906 /* temporary allocate normals */ 9907 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9908 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9909 size = pnt_size * points_count; 9910 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9911 if (!normals) return; 9912 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9913 9914 /* add elements */ 9915 for (i = 2; i < points_count; i++) { 9916 ids[0] = (nk_draw_index)(vtx_inner_idx); 9917 ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1)); 9918 ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1)); 9919 ids += 3; 9920 } 9921 9922 /* compute normals */ 9923 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 9924 struct nk_vec2 p0 = points[i0]; 9925 struct nk_vec2 p1 = points[i1]; 9926 struct nk_vec2 diff = nk_vec2_sub(p1, p0); 9927 9928 /* vec2 inverted length */ 9929 float len = nk_vec2_len_sqr(diff); 9930 if (len != 0.0f) 9931 len = nk_inv_sqrt(len); 9932 else len = 1.0f; 9933 diff = nk_vec2_muls(diff, len); 9934 9935 normals[i0].x = diff.y; 9936 normals[i0].y = -diff.x; 9937 } 9938 9939 /* add vertices + indexes */ 9940 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 9941 const struct nk_vec2 uv = list->config.null.uv; 9942 struct nk_vec2 n0 = normals[i0]; 9943 struct nk_vec2 n1 = normals[i1]; 9944 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); 9945 float dmr2 = dm.x*dm.x + dm.y*dm.y; 9946 if (dmr2 > 0.000001f) { 9947 float scale = 1.0f / dmr2; 9948 scale = NK_MIN(scale, 100.0f); 9949 dm = nk_vec2_muls(dm, scale); 9950 } 9951 dm = nk_vec2_muls(dm, AA_SIZE * 0.5f); 9952 9953 /* add vertices */ 9954 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col); 9955 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans); 9956 9957 /* add indexes */ 9958 ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 9959 ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1)); 9960 ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 9961 ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 9962 ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1)); 9963 ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 9964 ids += 6; 9965 } 9966 /* free temporary normals + points */ 9967 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 9968 } else { 9969 nk_size i = 0; 9970 nk_size index = list->vertex_count; 9971 const nk_size idx_count = (points_count-2)*3; 9972 const nk_size vtx_count = points_count; 9973 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9974 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9975 9976 if (!vtx || !ids) return; 9977 for (i = 0; i < vtx_count; ++i) 9978 vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col); 9979 for (i = 2; i < points_count; ++i) { 9980 ids[0] = (nk_draw_index)index; 9981 ids[1] = (nk_draw_index)(index+ i - 1); 9982 ids[2] = (nk_draw_index)(index+i); 9983 ids += 3; 9984 } 9985 } 9986 } 9987 NK_API void 9988 nk_draw_list_path_clear(struct nk_draw_list *list) 9989 { 9990 NK_ASSERT(list); 9991 if (!list) return; 9992 nk_buffer_reset(list->buffer, NK_BUFFER_FRONT); 9993 list->path_count = 0; 9994 list->path_offset = 0; 9995 } 9996 NK_API void 9997 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos) 9998 { 9999 struct nk_vec2 *points = 0; 10000 struct nk_draw_command *cmd = 0; 10001 NK_ASSERT(list); 10002 if (!list) return; 10003 if (!list->cmd_count) 10004 nk_draw_list_add_clip(list, nk_null_rect); 10005 10006 cmd = nk_draw_list_command_last(list); 10007 if (cmd && cmd->texture.ptr != list->config.null.texture.ptr) 10008 nk_draw_list_push_image(list, list->config.null.texture); 10009 10010 points = nk_draw_list_alloc_path(list, 1); 10011 if (!points) return; 10012 points[0] = pos; 10013 } 10014 NK_API void 10015 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center, 10016 float radius, int a_min, int a_max) 10017 { 10018 int a = 0; 10019 NK_ASSERT(list); 10020 if (!list) return; 10021 if (a_min <= a_max) { 10022 for (a = a_min; a <= a_max; a++) { 10023 const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)]; 10024 const float x = center.x + c.x * radius; 10025 const float y = center.y + c.y * radius; 10026 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 10027 } 10028 } 10029 } 10030 NK_API void 10031 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center, 10032 float radius, float a_min, float a_max, unsigned int segments) 10033 { 10034 unsigned int i = 0; 10035 NK_ASSERT(list); 10036 if (!list) return; 10037 if (radius == 0.0f) return; 10038 10039 /* This algorithm for arc drawing relies on these two trigonometric identities[1]: 10040 sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) 10041 cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) 10042 10043 Two coordinates (x, y) of a point on a circle centered on 10044 the origin can be written in polar form as: 10045 x = r * cos(a) 10046 y = r * sin(a) 10047 where r is the radius of the circle, 10048 a is the angle between (x, y) and the origin. 10049 10050 This allows us to rotate the coordinates around the 10051 origin by an angle b using the following transformation: 10052 x' = r * cos(a + b) = x * cos(b) - y * sin(b) 10053 y' = r * sin(a + b) = y * cos(b) + x * sin(b) 10054 10055 [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities 10056 */ 10057 {const float d_angle = (a_max - a_min) / (float)segments; 10058 const float sin_d = (float)NK_SIN(d_angle); 10059 const float cos_d = (float)NK_COS(d_angle); 10060 10061 float cx = (float)NK_COS(a_min) * radius; 10062 float cy = (float)NK_SIN(a_min) * radius; 10063 for(i = 0; i <= segments; ++i) { 10064 float new_cx, new_cy; 10065 const float x = center.x + cx; 10066 const float y = center.y + cy; 10067 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 10068 10069 new_cx = cx * cos_d - cy * sin_d; 10070 new_cy = cy * cos_d + cx * sin_d; 10071 cx = new_cx; 10072 cy = new_cy; 10073 }} 10074 } 10075 NK_API void 10076 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a, 10077 struct nk_vec2 b, float rounding) 10078 { 10079 float r; 10080 NK_ASSERT(list); 10081 if (!list) return; 10082 r = rounding; 10083 r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x)); 10084 r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y)); 10085 10086 if (r == 0.0f) { 10087 nk_draw_list_path_line_to(list, a); 10088 nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y)); 10089 nk_draw_list_path_line_to(list, b); 10090 nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y)); 10091 } else { 10092 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9); 10093 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12); 10094 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3); 10095 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6); 10096 } 10097 } 10098 NK_API void 10099 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2, 10100 struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments) 10101 { 10102 float t_step; 10103 unsigned int i_step; 10104 struct nk_vec2 p1; 10105 10106 NK_ASSERT(list); 10107 NK_ASSERT(list->path_count); 10108 if (!list || !list->path_count) return; 10109 num_segments = NK_MAX(num_segments, 1); 10110 10111 p1 = nk_draw_list_path_last(list); 10112 t_step = 1.0f/(float)num_segments; 10113 for (i_step = 1; i_step <= num_segments; ++i_step) { 10114 float t = t_step * (float)i_step; 10115 float u = 1.0f - t; 10116 float w1 = u*u*u; 10117 float w2 = 3*u*u*t; 10118 float w3 = 3*u*t*t; 10119 float w4 = t * t *t; 10120 float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; 10121 float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; 10122 nk_draw_list_path_line_to(list, nk_vec2(x,y)); 10123 } 10124 } 10125 NK_API void 10126 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color) 10127 { 10128 struct nk_vec2 *points; 10129 NK_ASSERT(list); 10130 if (!list) return; 10131 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10132 nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA); 10133 nk_draw_list_path_clear(list); 10134 } 10135 NK_API void 10136 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color, 10137 enum nk_draw_list_stroke closed, float thickness) 10138 { 10139 struct nk_vec2 *points; 10140 NK_ASSERT(list); 10141 if (!list) return; 10142 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10143 nk_draw_list_stroke_poly_line(list, points, list->path_count, color, 10144 closed, thickness, list->config.line_AA); 10145 nk_draw_list_path_clear(list); 10146 } 10147 NK_API void 10148 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a, 10149 struct nk_vec2 b, struct nk_color col, float thickness) 10150 { 10151 NK_ASSERT(list); 10152 if (!list || !col.a) return; 10153 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10154 nk_draw_list_path_line_to(list, a); 10155 nk_draw_list_path_line_to(list, b); 10156 } else { 10157 nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f))); 10158 nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f))); 10159 } 10160 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10161 } 10162 NK_API void 10163 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect, 10164 struct nk_color col, float rounding) 10165 { 10166 NK_ASSERT(list); 10167 if (!list || !col.a) return; 10168 10169 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10170 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10171 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10172 } else { 10173 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10174 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10175 } nk_draw_list_path_fill(list, col); 10176 } 10177 NK_API void 10178 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect, 10179 struct nk_color col, float rounding, float thickness) 10180 { 10181 NK_ASSERT(list); 10182 if (!list || !col.a) return; 10183 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10184 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10185 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10186 } else { 10187 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10188 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10189 } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10190 } 10191 NK_API void 10192 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect, 10193 struct nk_color left, struct nk_color top, struct nk_color right, 10194 struct nk_color bottom) 10195 { 10196 void *vtx; 10197 struct nk_colorf col_left, col_top; 10198 struct nk_colorf col_right, col_bottom; 10199 nk_draw_index *idx; 10200 nk_draw_index index; 10201 10202 nk_color_fv(&col_left.r, left); 10203 nk_color_fv(&col_right.r, right); 10204 nk_color_fv(&col_top.r, top); 10205 nk_color_fv(&col_bottom.r, bottom); 10206 10207 NK_ASSERT(list); 10208 if (!list) return; 10209 10210 nk_draw_list_push_image(list, list->config.null.texture); 10211 index = (nk_draw_index)list->vertex_count; 10212 vtx = nk_draw_list_alloc_vertices(list, 4); 10213 idx = nk_draw_list_alloc_elements(list, 6); 10214 if (!vtx || !idx) return; 10215 10216 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10217 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10218 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10219 10220 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left); 10221 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top); 10222 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right); 10223 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom); 10224 } 10225 NK_API void 10226 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10227 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col) 10228 { 10229 NK_ASSERT(list); 10230 if (!list || !col.a) return; 10231 nk_draw_list_path_line_to(list, a); 10232 nk_draw_list_path_line_to(list, b); 10233 nk_draw_list_path_line_to(list, c); 10234 nk_draw_list_path_fill(list, col); 10235 } 10236 NK_API void 10237 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10238 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness) 10239 { 10240 NK_ASSERT(list); 10241 if (!list || !col.a) return; 10242 nk_draw_list_path_line_to(list, a); 10243 nk_draw_list_path_line_to(list, b); 10244 nk_draw_list_path_line_to(list, c); 10245 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10246 } 10247 NK_API void 10248 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center, 10249 float radius, struct nk_color col, unsigned int segs) 10250 { 10251 float a_max; 10252 NK_ASSERT(list); 10253 if (!list || !col.a) return; 10254 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10255 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10256 nk_draw_list_path_fill(list, col); 10257 } 10258 NK_API void 10259 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center, 10260 float radius, struct nk_color col, unsigned int segs, float thickness) 10261 { 10262 float a_max; 10263 NK_ASSERT(list); 10264 if (!list || !col.a) return; 10265 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10266 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10267 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10268 } 10269 NK_API void 10270 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0, 10271 struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, 10272 struct nk_color col, unsigned int segments, float thickness) 10273 { 10274 NK_ASSERT(list); 10275 if (!list || !col.a) return; 10276 nk_draw_list_path_line_to(list, p0); 10277 nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments); 10278 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10279 } 10280 NK_INTERN void 10281 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a, 10282 struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc, 10283 struct nk_color color) 10284 { 10285 void *vtx; 10286 struct nk_vec2 uvb; 10287 struct nk_vec2 uvd; 10288 struct nk_vec2 b; 10289 struct nk_vec2 d; 10290 10291 struct nk_colorf col; 10292 nk_draw_index *idx; 10293 nk_draw_index index; 10294 NK_ASSERT(list); 10295 if (!list) return; 10296 10297 nk_color_fv(&col.r, color); 10298 uvb = nk_vec2(uvc.x, uva.y); 10299 uvd = nk_vec2(uva.x, uvc.y); 10300 b = nk_vec2(c.x, a.y); 10301 d = nk_vec2(a.x, c.y); 10302 10303 index = (nk_draw_index)list->vertex_count; 10304 vtx = nk_draw_list_alloc_vertices(list, 4); 10305 idx = nk_draw_list_alloc_elements(list, 6); 10306 if (!vtx || !idx) return; 10307 10308 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10309 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10310 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10311 10312 vtx = nk_draw_vertex(vtx, &list->config, a, uva, col); 10313 vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col); 10314 vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col); 10315 vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col); 10316 } 10317 NK_API void 10318 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture, 10319 struct nk_rect rect, struct nk_color color) 10320 { 10321 NK_ASSERT(list); 10322 if (!list) return; 10323 /* push new command with given texture */ 10324 nk_draw_list_push_image(list, texture.handle); 10325 if (nk_image_is_subimage(&texture)) { 10326 /* add region inside of the texture */ 10327 struct nk_vec2 uv[2]; 10328 uv[0].x = (float)texture.region[0]/(float)texture.w; 10329 uv[0].y = (float)texture.region[1]/(float)texture.h; 10330 uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w; 10331 uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h; 10332 nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10333 nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color); 10334 } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10335 nk_vec2(rect.x + rect.w, rect.y + rect.h), 10336 nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color); 10337 } 10338 NK_API void 10339 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font, 10340 struct nk_rect rect, const char *text, int len, float font_height, 10341 struct nk_color fg) 10342 { 10343 float x = 0; 10344 int text_len = 0; 10345 nk_rune unicode = 0; 10346 nk_rune next = 0; 10347 int glyph_len = 0; 10348 int next_glyph_len = 0; 10349 struct nk_user_font_glyph g; 10350 10351 NK_ASSERT(list); 10352 if (!list || !len || !text) return; 10353 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 10354 list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return; 10355 10356 nk_draw_list_push_image(list, font->texture); 10357 x = rect.x; 10358 glyph_len = nk_utf_decode(text, &unicode, len); 10359 if (!glyph_len) return; 10360 10361 /* draw every glyph image */ 10362 fg.a = (nk_byte)((float)fg.a * list->config.global_alpha); 10363 while (text_len < len && glyph_len) { 10364 float gx, gy, gh, gw; 10365 float char_width = 0; 10366 if (unicode == NK_UTF_INVALID) break; 10367 10368 /* query currently drawn glyph information */ 10369 next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); 10370 font->query(font->userdata, font_height, &g, unicode, 10371 (next == NK_UTF_INVALID) ? '\0' : next); 10372 10373 /* calculate and draw glyph drawing rectangle and image */ 10374 gx = x + g.offset.x; 10375 gy = rect.y + g.offset.y; 10376 gw = g.width; gh = g.height; 10377 char_width = g.xadvance; 10378 nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh), 10379 g.uv[0], g.uv[1], fg); 10380 10381 /* offset next glyph */ 10382 text_len += glyph_len; 10383 x += char_width; 10384 glyph_len = next_glyph_len; 10385 unicode = next; 10386 } 10387 } 10388 NK_API nk_flags 10389 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 10390 struct nk_buffer *vertices, struct nk_buffer *elements, 10391 const struct nk_convert_config *config) 10392 { 10393 nk_flags res = NK_CONVERT_SUCCESS; 10394 const struct nk_command *cmd; 10395 NK_ASSERT(ctx); 10396 NK_ASSERT(cmds); 10397 NK_ASSERT(vertices); 10398 NK_ASSERT(elements); 10399 NK_ASSERT(config); 10400 NK_ASSERT(config->vertex_layout); 10401 NK_ASSERT(config->vertex_size); 10402 if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout) 10403 return NK_CONVERT_INVALID_PARAM; 10404 10405 nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements, 10406 config->line_AA, config->shape_AA); 10407 nk_foreach(cmd, ctx) 10408 { 10409 #ifdef NK_INCLUDE_COMMAND_USERDATA 10410 ctx->draw_list.userdata = cmd->userdata; 10411 #endif 10412 switch (cmd->type) { 10413 case NK_COMMAND_NOP: break; 10414 case NK_COMMAND_SCISSOR: { 10415 const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd; 10416 nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h)); 10417 } break; 10418 case NK_COMMAND_LINE: { 10419 const struct nk_command_line *l = (const struct nk_command_line*)cmd; 10420 nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y), 10421 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness); 10422 } break; 10423 case NK_COMMAND_CURVE: { 10424 const struct nk_command_curve *q = (const struct nk_command_curve*)cmd; 10425 nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y), 10426 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x, 10427 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color, 10428 config->curve_segment_count, q->line_thickness); 10429 } break; 10430 case NK_COMMAND_RECT: { 10431 const struct nk_command_rect *r = (const struct nk_command_rect*)cmd; 10432 nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10433 r->color, (float)r->rounding, r->line_thickness); 10434 } break; 10435 case NK_COMMAND_RECT_FILLED: { 10436 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd; 10437 nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10438 r->color, (float)r->rounding); 10439 } break; 10440 case NK_COMMAND_RECT_MULTI_COLOR: { 10441 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd; 10442 nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10443 r->left, r->top, r->right, r->bottom); 10444 } break; 10445 case NK_COMMAND_CIRCLE: { 10446 const struct nk_command_circle *c = (const struct nk_command_circle*)cmd; 10447 nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10448 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10449 config->circle_segment_count, c->line_thickness); 10450 } break; 10451 case NK_COMMAND_CIRCLE_FILLED: { 10452 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; 10453 nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10454 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10455 config->circle_segment_count); 10456 } break; 10457 case NK_COMMAND_ARC: { 10458 const struct nk_command_arc *c = (const struct nk_command_arc*)cmd; 10459 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10460 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10461 c->a[0], c->a[1], config->arc_segment_count); 10462 nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness); 10463 } break; 10464 case NK_COMMAND_ARC_FILLED: { 10465 const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd; 10466 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10467 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10468 c->a[0], c->a[1], config->arc_segment_count); 10469 nk_draw_list_path_fill(&ctx->draw_list, c->color); 10470 } break; 10471 case NK_COMMAND_TRIANGLE: { 10472 const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; 10473 nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10474 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color, 10475 t->line_thickness); 10476 } break; 10477 case NK_COMMAND_TRIANGLE_FILLED: { 10478 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; 10479 nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10480 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color); 10481 } break; 10482 case NK_COMMAND_POLYGON: { 10483 int i; 10484 const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd; 10485 for (i = 0; i < p->point_count; ++i) { 10486 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10487 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10488 } 10489 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness); 10490 } break; 10491 case NK_COMMAND_POLYGON_FILLED: { 10492 int i; 10493 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; 10494 for (i = 0; i < p->point_count; ++i) { 10495 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10496 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10497 } 10498 nk_draw_list_path_fill(&ctx->draw_list, p->color); 10499 } break; 10500 case NK_COMMAND_POLYLINE: { 10501 int i; 10502 const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd; 10503 for (i = 0; i < p->point_count; ++i) { 10504 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10505 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10506 } 10507 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness); 10508 } break; 10509 case NK_COMMAND_TEXT: { 10510 const struct nk_command_text *t = (const struct nk_command_text*)cmd; 10511 nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h), 10512 t->string, t->length, t->height, t->foreground); 10513 } break; 10514 case NK_COMMAND_IMAGE: { 10515 const struct nk_command_image *i = (const struct nk_command_image*)cmd; 10516 nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col); 10517 } break; 10518 case NK_COMMAND_CUSTOM: { 10519 const struct nk_command_custom *c = (const struct nk_command_custom*)cmd; 10520 c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data); 10521 } break; 10522 default: break; 10523 } 10524 } 10525 res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0; 10526 res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0; 10527 res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0; 10528 return res; 10529 } 10530 NK_API const struct nk_draw_command* 10531 nk__draw_begin(const struct nk_context *ctx, 10532 const struct nk_buffer *buffer) 10533 { 10534 return nk__draw_list_begin(&ctx->draw_list, buffer); 10535 } 10536 NK_API const struct nk_draw_command* 10537 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer) 10538 { 10539 return nk__draw_list_end(&ctx->draw_list, buffer); 10540 } 10541 NK_API const struct nk_draw_command* 10542 nk__draw_next(const struct nk_draw_command *cmd, 10543 const struct nk_buffer *buffer, const struct nk_context *ctx) 10544 { 10545 return nk__draw_list_next(cmd, buffer, &ctx->draw_list); 10546 } 10547 #endif 10548 10549 10550 10551 10552 10553 #ifdef NK_INCLUDE_FONT_BAKING 10554 /* ------------------------------------------------------------- 10555 * 10556 * RECT PACK 10557 * 10558 * --------------------------------------------------------------*/ 10559 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */ 10560 /* Sean Barrett 2014 */ 10561 #define NK_RP__MAXVAL 0xffff 10562 typedef unsigned short nk_rp_coord; 10563 10564 struct nk_rp_rect { 10565 /* reserved for your use: */ 10566 int id; 10567 /* input: */ 10568 nk_rp_coord w, h; 10569 /* output: */ 10570 nk_rp_coord x, y; 10571 int was_packed; 10572 /* non-zero if valid packing */ 10573 }; /* 16 bytes, nominally */ 10574 10575 struct nk_rp_node { 10576 nk_rp_coord x,y; 10577 struct nk_rp_node *next; 10578 }; 10579 10580 struct nk_rp_context { 10581 int width; 10582 int height; 10583 int align; 10584 int init_mode; 10585 int heuristic; 10586 int num_nodes; 10587 struct nk_rp_node *active_head; 10588 struct nk_rp_node *free_head; 10589 struct nk_rp_node extra[2]; 10590 /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */ 10591 }; 10592 10593 struct nk_rp__findresult { 10594 int x,y; 10595 struct nk_rp_node **prev_link; 10596 }; 10597 10598 enum NK_RP_HEURISTIC { 10599 NK_RP_HEURISTIC_Skyline_default=0, 10600 NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default, 10601 NK_RP_HEURISTIC_Skyline_BF_sortHeight 10602 }; 10603 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1}; 10604 10605 NK_INTERN void 10606 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem) 10607 { 10608 if (allow_out_of_mem) 10609 /* if it's ok to run out of memory, then don't bother aligning them; */ 10610 /* this gives better packing, but may fail due to OOM (even though */ 10611 /* the rectangles easily fit). @TODO a smarter approach would be to only */ 10612 /* quantize once we've hit OOM, then we could get rid of this parameter. */ 10613 context->align = 1; 10614 else { 10615 /* if it's not ok to run out of memory, then quantize the widths */ 10616 /* so that num_nodes is always enough nodes. */ 10617 /* */ 10618 /* I.e. num_nodes * align >= width */ 10619 /* align >= width / num_nodes */ 10620 /* align = ceil(width/num_nodes) */ 10621 context->align = (context->width + context->num_nodes-1) / context->num_nodes; 10622 } 10623 } 10624 NK_INTERN void 10625 nk_rp_init_target(struct nk_rp_context *context, int width, int height, 10626 struct nk_rp_node *nodes, int num_nodes) 10627 { 10628 int i; 10629 #ifndef STBRP_LARGE_RECTS 10630 NK_ASSERT(width <= 0xffff && height <= 0xffff); 10631 #endif 10632 10633 for (i=0; i < num_nodes-1; ++i) 10634 nodes[i].next = &nodes[i+1]; 10635 nodes[i].next = 0; 10636 context->init_mode = NK_RP__INIT_skyline; 10637 context->heuristic = NK_RP_HEURISTIC_Skyline_default; 10638 context->free_head = &nodes[0]; 10639 context->active_head = &context->extra[0]; 10640 context->width = width; 10641 context->height = height; 10642 context->num_nodes = num_nodes; 10643 nk_rp_setup_allow_out_of_mem(context, 0); 10644 10645 /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */ 10646 context->extra[0].x = 0; 10647 context->extra[0].y = 0; 10648 context->extra[0].next = &context->extra[1]; 10649 context->extra[1].x = (nk_rp_coord) width; 10650 context->extra[1].y = 65535; 10651 context->extra[1].next = 0; 10652 } 10653 /* find minimum y position if it starts at x1 */ 10654 NK_INTERN int 10655 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first, 10656 int x0, int width, int *pwaste) 10657 { 10658 struct nk_rp_node *node = first; 10659 int x1 = x0 + width; 10660 int min_y, visited_width, waste_area; 10661 NK_ASSERT(first->x <= x0); 10662 NK_UNUSED(c); 10663 10664 NK_ASSERT(node->next->x > x0); 10665 /* we ended up handling this in the caller for efficiency */ 10666 NK_ASSERT(node->x <= x0); 10667 10668 min_y = 0; 10669 waste_area = 0; 10670 visited_width = 0; 10671 while (node->x < x1) 10672 { 10673 if (node->y > min_y) { 10674 /* raise min_y higher. */ 10675 /* we've accounted for all waste up to min_y, */ 10676 /* but we'll now add more waste for everything we've visited */ 10677 waste_area += visited_width * (node->y - min_y); 10678 min_y = node->y; 10679 /* the first time through, visited_width might be reduced */ 10680 if (node->x < x0) 10681 visited_width += node->next->x - x0; 10682 else 10683 visited_width += node->next->x - node->x; 10684 } else { 10685 /* add waste area */ 10686 int under_width = node->next->x - node->x; 10687 if (under_width + visited_width > width) 10688 under_width = width - visited_width; 10689 waste_area += under_width * (min_y - node->y); 10690 visited_width += under_width; 10691 } 10692 node = node->next; 10693 } 10694 *pwaste = waste_area; 10695 return min_y; 10696 } 10697 NK_INTERN struct nk_rp__findresult 10698 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height) 10699 { 10700 int best_waste = (1<<30), best_x, best_y = (1 << 30); 10701 struct nk_rp__findresult fr; 10702 struct nk_rp_node **prev, *node, *tail, **best = 0; 10703 10704 /* align to multiple of c->align */ 10705 width = (width + c->align - 1); 10706 width -= width % c->align; 10707 NK_ASSERT(width % c->align == 0); 10708 10709 node = c->active_head; 10710 prev = &c->active_head; 10711 while (node->x + width <= c->width) { 10712 int y,waste; 10713 y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste); 10714 /* actually just want to test BL */ 10715 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) { 10716 /* bottom left */ 10717 if (y < best_y) { 10718 best_y = y; 10719 best = prev; 10720 } 10721 } else { 10722 /* best-fit */ 10723 if (y + height <= c->height) { 10724 /* can only use it if it first vertically */ 10725 if (y < best_y || (y == best_y && waste < best_waste)) { 10726 best_y = y; 10727 best_waste = waste; 10728 best = prev; 10729 } 10730 } 10731 } 10732 prev = &node->next; 10733 node = node->next; 10734 } 10735 best_x = (best == 0) ? 0 : (*best)->x; 10736 10737 /* if doing best-fit (BF), we also have to try aligning right edge to each node position */ 10738 /* */ 10739 /* e.g, if fitting */ 10740 /* */ 10741 /* ____________________ */ 10742 /* |____________________| */ 10743 /* */ 10744 /* into */ 10745 /* */ 10746 /* | | */ 10747 /* | ____________| */ 10748 /* |____________| */ 10749 /* */ 10750 /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */ 10751 /* */ 10752 /* This makes BF take about 2x the time */ 10753 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight) 10754 { 10755 tail = c->active_head; 10756 node = c->active_head; 10757 prev = &c->active_head; 10758 /* find first node that's admissible */ 10759 while (tail->x < width) 10760 tail = tail->next; 10761 while (tail) 10762 { 10763 int xpos = tail->x - width; 10764 int y,waste; 10765 NK_ASSERT(xpos >= 0); 10766 /* find the left position that matches this */ 10767 while (node->next->x <= xpos) { 10768 prev = &node->next; 10769 node = node->next; 10770 } 10771 NK_ASSERT(node->next->x > xpos && node->x <= xpos); 10772 y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste); 10773 if (y + height < c->height) { 10774 if (y <= best_y) { 10775 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 10776 best_x = xpos; 10777 NK_ASSERT(y <= best_y); 10778 best_y = y; 10779 best_waste = waste; 10780 best = prev; 10781 } 10782 } 10783 } 10784 tail = tail->next; 10785 } 10786 } 10787 fr.prev_link = best; 10788 fr.x = best_x; 10789 fr.y = best_y; 10790 return fr; 10791 } 10792 NK_INTERN struct nk_rp__findresult 10793 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height) 10794 { 10795 /* find best position according to heuristic */ 10796 struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height); 10797 struct nk_rp_node *node, *cur; 10798 10799 /* bail if: */ 10800 /* 1. it failed */ 10801 /* 2. the best node doesn't fit (we don't always check this) */ 10802 /* 3. we're out of memory */ 10803 if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) { 10804 res.prev_link = 0; 10805 return res; 10806 } 10807 10808 /* on success, create new node */ 10809 node = context->free_head; 10810 node->x = (nk_rp_coord) res.x; 10811 node->y = (nk_rp_coord) (res.y + height); 10812 10813 context->free_head = node->next; 10814 10815 /* insert the new node into the right starting point, and */ 10816 /* let 'cur' point to the remaining nodes needing to be */ 10817 /* stitched back in */ 10818 cur = *res.prev_link; 10819 if (cur->x < res.x) { 10820 /* preserve the existing one, so start testing with the next one */ 10821 struct nk_rp_node *next = cur->next; 10822 cur->next = node; 10823 cur = next; 10824 } else { 10825 *res.prev_link = node; 10826 } 10827 10828 /* from here, traverse cur and free the nodes, until we get to one */ 10829 /* that shouldn't be freed */ 10830 while (cur->next && cur->next->x <= res.x + width) { 10831 struct nk_rp_node *next = cur->next; 10832 /* move the current node to the free list */ 10833 cur->next = context->free_head; 10834 context->free_head = cur; 10835 cur = next; 10836 } 10837 /* stitch the list back in */ 10838 node->next = cur; 10839 10840 if (cur->x < res.x + width) 10841 cur->x = (nk_rp_coord) (res.x + width); 10842 return res; 10843 } 10844 NK_INTERN int 10845 nk_rect_height_compare(const void *a, const void *b) 10846 { 10847 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; 10848 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; 10849 if (p->h > q->h) 10850 return -1; 10851 if (p->h < q->h) 10852 return 1; 10853 return (p->w > q->w) ? -1 : (p->w < q->w); 10854 } 10855 NK_INTERN int 10856 nk_rect_original_order(const void *a, const void *b) 10857 { 10858 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; 10859 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; 10860 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 10861 } 10862 NK_INTERN void 10863 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*)) 10864 { 10865 /* iterative quick sort */ 10866 #define NK_MAX_SORT_STACK 64 10867 unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0; 10868 unsigned seed = len/2 * 69069+1; 10869 for (;;) { 10870 for (; left+1 < len; len++) { 10871 struct nk_rp_rect pivot, tmp; 10872 if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0]; 10873 pivot = array[left+seed%(len-left)]; 10874 seed = seed * 69069 + 1; 10875 stack[pos++] = len; 10876 for (right = left-1;;) { 10877 while (cmp(&array[++right], &pivot) < 0); 10878 while (cmp(&pivot, &array[--len]) < 0); 10879 if (right >= len) break; 10880 tmp = array[right]; 10881 array[right] = array[len]; 10882 array[len] = tmp; 10883 } 10884 } 10885 if (pos == 0) break; 10886 left = len; 10887 len = stack[--pos]; 10888 } 10889 #undef NK_MAX_SORT_STACK 10890 } 10891 NK_INTERN void 10892 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects) 10893 { 10894 int i; 10895 /* we use the 'was_packed' field internally to allow sorting/unsorting */ 10896 for (i=0; i < num_rects; ++i) { 10897 rects[i].was_packed = i; 10898 } 10899 10900 /* sort according to heuristic */ 10901 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare); 10902 10903 for (i=0; i < num_rects; ++i) { 10904 struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 10905 if (fr.prev_link) { 10906 rects[i].x = (nk_rp_coord) fr.x; 10907 rects[i].y = (nk_rp_coord) fr.y; 10908 } else { 10909 rects[i].x = rects[i].y = NK_RP__MAXVAL; 10910 } 10911 } 10912 10913 /* unsort */ 10914 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order); 10915 10916 /* set was_packed flags */ 10917 for (i=0; i < num_rects; ++i) 10918 rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL); 10919 } 10920 10921 /* 10922 * ============================================================== 10923 * 10924 * TRUETYPE 10925 * 10926 * =============================================================== 10927 */ 10928 /* stb_truetype.h - v1.07 - public domain */ 10929 #define NK_TT_MAX_OVERSAMPLE 8 10930 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1) 10931 10932 struct nk_tt_bakedchar { 10933 unsigned short x0,y0,x1,y1; 10934 /* coordinates of bbox in bitmap */ 10935 float xoff,yoff,xadvance; 10936 }; 10937 10938 struct nk_tt_aligned_quad{ 10939 float x0,y0,s0,t0; /* top-left */ 10940 float x1,y1,s1,t1; /* bottom-right */ 10941 }; 10942 10943 struct nk_tt_packedchar { 10944 unsigned short x0,y0,x1,y1; 10945 /* coordinates of bbox in bitmap */ 10946 float xoff,yoff,xadvance; 10947 float xoff2,yoff2; 10948 }; 10949 10950 struct nk_tt_pack_range { 10951 float font_size; 10952 int first_unicode_codepoint_in_range; 10953 /* if non-zero, then the chars are continuous, and this is the first codepoint */ 10954 int *array_of_unicode_codepoints; 10955 /* if non-zero, then this is an array of unicode codepoints */ 10956 int num_chars; 10957 struct nk_tt_packedchar *chardata_for_range; /* output */ 10958 unsigned char h_oversample, v_oversample; 10959 /* don't set these, they're used internally */ 10960 }; 10961 10962 struct nk_tt_pack_context { 10963 void *pack_info; 10964 int width; 10965 int height; 10966 int stride_in_bytes; 10967 int padding; 10968 unsigned int h_oversample, v_oversample; 10969 unsigned char *pixels; 10970 void *nodes; 10971 }; 10972 10973 struct nk_tt_fontinfo { 10974 const unsigned char* data; /* pointer to .ttf file */ 10975 int fontstart;/* offset of start of font */ 10976 int numGlyphs;/* number of glyphs, needed for range checking */ 10977 int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */ 10978 int index_map; /* a cmap mapping for our chosen character encoding */ 10979 int indexToLocFormat; /* format needed to map from glyph index to glyph */ 10980 }; 10981 10982 enum { 10983 NK_TT_vmove=1, 10984 NK_TT_vline, 10985 NK_TT_vcurve 10986 }; 10987 10988 struct nk_tt_vertex { 10989 short x,y,cx,cy; 10990 unsigned char type,padding; 10991 }; 10992 10993 struct nk_tt__bitmap{ 10994 int w,h,stride; 10995 unsigned char *pixels; 10996 }; 10997 10998 struct nk_tt__hheap_chunk { 10999 struct nk_tt__hheap_chunk *next; 11000 }; 11001 struct nk_tt__hheap { 11002 struct nk_allocator alloc; 11003 struct nk_tt__hheap_chunk *head; 11004 void *first_free; 11005 int num_remaining_in_head_chunk; 11006 }; 11007 11008 struct nk_tt__edge { 11009 float x0,y0, x1,y1; 11010 int invert; 11011 }; 11012 11013 struct nk_tt__active_edge { 11014 struct nk_tt__active_edge *next; 11015 float fx,fdx,fdy; 11016 float direction; 11017 float sy; 11018 float ey; 11019 }; 11020 struct nk_tt__point {float x,y;}; 11021 11022 #define NK_TT_MACSTYLE_DONTCARE 0 11023 #define NK_TT_MACSTYLE_BOLD 1 11024 #define NK_TT_MACSTYLE_ITALIC 2 11025 #define NK_TT_MACSTYLE_UNDERSCORE 4 11026 #define NK_TT_MACSTYLE_NONE 8 11027 /* <= not same as 0, this makes us check the bitfield is 0 */ 11028 11029 enum { /* platformID */ 11030 NK_TT_PLATFORM_ID_UNICODE =0, 11031 NK_TT_PLATFORM_ID_MAC =1, 11032 NK_TT_PLATFORM_ID_ISO =2, 11033 NK_TT_PLATFORM_ID_MICROSOFT =3 11034 }; 11035 11036 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */ 11037 NK_TT_UNICODE_EID_UNICODE_1_0 =0, 11038 NK_TT_UNICODE_EID_UNICODE_1_1 =1, 11039 NK_TT_UNICODE_EID_ISO_10646 =2, 11040 NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3, 11041 NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4 11042 }; 11043 11044 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */ 11045 NK_TT_MS_EID_SYMBOL =0, 11046 NK_TT_MS_EID_UNICODE_BMP =1, 11047 NK_TT_MS_EID_SHIFTJIS =2, 11048 NK_TT_MS_EID_UNICODE_FULL =10 11049 }; 11050 11051 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */ 11052 NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4, 11053 NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5, 11054 NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6, 11055 NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7 11056 }; 11057 11058 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */ 11059 /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */ 11060 NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410, 11061 NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411, 11062 NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412, 11063 NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419, 11064 NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409, 11065 NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D 11066 }; 11067 11068 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */ 11069 NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11, 11070 NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23, 11071 NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32, 11072 NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 , 11073 NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 , 11074 NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33, 11075 NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19 11076 }; 11077 11078 #define nk_ttBYTE(p) (* (const nk_byte *) (p)) 11079 #define nk_ttCHAR(p) (* (const char *) (p)) 11080 11081 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE) 11082 #define nk_ttUSHORT(p) (* (nk_ushort *) (p)) 11083 #define nk_ttSHORT(p) (* (nk_short *) (p)) 11084 #define nk_ttULONG(p) (* (nk_uint *) (p)) 11085 #define nk_ttLONG(p) (* (nk_int *) (p)) 11086 #else 11087 static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); } 11088 static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); } 11089 static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); } 11090 #endif 11091 11092 #define nk_tt_tag4(p,c0,c1,c2,c3)\ 11093 ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) 11094 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3]) 11095 11096 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, 11097 int glyph_index, struct nk_tt_vertex **pvertices); 11098 11099 NK_INTERN nk_uint 11100 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag) 11101 { 11102 /* @OPTIMIZE: binary search */ 11103 nk_int num_tables = nk_ttUSHORT(data+fontstart+4); 11104 nk_uint tabledir = fontstart + 12; 11105 nk_int i; 11106 for (i = 0; i < num_tables; ++i) { 11107 nk_uint loc = tabledir + (nk_uint)(16*i); 11108 if (nk_tt_tag(data+loc+0, tag)) 11109 return nk_ttULONG(data+loc+8); 11110 } 11111 return 0; 11112 } 11113 NK_INTERN int 11114 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart) 11115 { 11116 nk_uint cmap, t; 11117 nk_int i,numTables; 11118 const nk_byte *data = (const nk_byte *) data2; 11119 11120 info->data = data; 11121 info->fontstart = fontstart; 11122 11123 cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */ 11124 info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */ 11125 info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */ 11126 info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */ 11127 info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */ 11128 info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */ 11129 info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */ 11130 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) 11131 return 0; 11132 11133 t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp"); 11134 if (t) info->numGlyphs = nk_ttUSHORT(data+t+4); 11135 else info->numGlyphs = 0xffff; 11136 11137 /* find a cmap encoding table we understand *now* to avoid searching */ 11138 /* later. (todo: could make this installable) */ 11139 /* the same regardless of glyph. */ 11140 numTables = nk_ttUSHORT(data + cmap + 2); 11141 info->index_map = 0; 11142 for (i=0; i < numTables; ++i) 11143 { 11144 nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i; 11145 /* find an encoding we understand: */ 11146 switch(nk_ttUSHORT(data+encoding_record)) { 11147 case NK_TT_PLATFORM_ID_MICROSOFT: 11148 switch (nk_ttUSHORT(data+encoding_record+2)) { 11149 case NK_TT_MS_EID_UNICODE_BMP: 11150 case NK_TT_MS_EID_UNICODE_FULL: 11151 /* MS/Unicode */ 11152 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); 11153 break; 11154 default: break; 11155 } break; 11156 case NK_TT_PLATFORM_ID_UNICODE: 11157 /* Mac/iOS has these */ 11158 /* all the encodingIDs are unicode, so we don't bother to check it */ 11159 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); 11160 break; 11161 default: break; 11162 } 11163 } 11164 if (info->index_map == 0) 11165 return 0; 11166 info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50); 11167 return 1; 11168 } 11169 NK_INTERN int 11170 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint) 11171 { 11172 const nk_byte *data = info->data; 11173 nk_uint index_map = (nk_uint)info->index_map; 11174 11175 nk_ushort format = nk_ttUSHORT(data + index_map + 0); 11176 if (format == 0) { /* apple byte encoding */ 11177 nk_int bytes = nk_ttUSHORT(data + index_map + 2); 11178 if (unicode_codepoint < bytes-6) 11179 return nk_ttBYTE(data + index_map + 6 + unicode_codepoint); 11180 return 0; 11181 } else if (format == 6) { 11182 nk_uint first = nk_ttUSHORT(data + index_map + 6); 11183 nk_uint count = nk_ttUSHORT(data + index_map + 8); 11184 if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count) 11185 return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2); 11186 return 0; 11187 } else if (format == 2) { 11188 NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */ 11189 return 0; 11190 } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */ 11191 nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1; 11192 nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1; 11193 nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10); 11194 nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1; 11195 11196 /* do a binary search of the segments */ 11197 nk_uint endCount = index_map + 14; 11198 nk_uint search = endCount; 11199 11200 if (unicode_codepoint > 0xffff) 11201 return 0; 11202 11203 /* they lie from endCount .. endCount + segCount */ 11204 /* but searchRange is the nearest power of two, so... */ 11205 if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2)) 11206 search += (nk_uint)(rangeShift*2); 11207 11208 /* now decrement to bias correctly to find smallest */ 11209 search -= 2; 11210 while (entrySelector) { 11211 nk_ushort end; 11212 searchRange >>= 1; 11213 end = nk_ttUSHORT(data + search + searchRange*2); 11214 if (unicode_codepoint > end) 11215 search += (nk_uint)(searchRange*2); 11216 --entrySelector; 11217 } 11218 search += 2; 11219 11220 { 11221 nk_ushort offset, start; 11222 nk_ushort item = (nk_ushort) ((search - endCount) >> 1); 11223 11224 NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item)); 11225 start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); 11226 if (unicode_codepoint < start) 11227 return 0; 11228 11229 offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); 11230 if (offset == 0) 11231 return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); 11232 11233 return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); 11234 } 11235 } else if (format == 12 || format == 13) { 11236 nk_uint ngroups = nk_ttULONG(data+index_map+12); 11237 nk_int low,high; 11238 low = 0; high = (nk_int)ngroups; 11239 /* Binary search the right group. */ 11240 while (low < high) { 11241 nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */ 11242 nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12); 11243 nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4); 11244 if ((nk_uint) unicode_codepoint < start_char) 11245 high = mid; 11246 else if ((nk_uint) unicode_codepoint > end_char) 11247 low = mid+1; 11248 else { 11249 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8); 11250 if (format == 12) 11251 return (int)start_glyph + (int)unicode_codepoint - (int)start_char; 11252 else /* format == 13 */ 11253 return (int)start_glyph; 11254 } 11255 } 11256 return 0; /* not found */ 11257 } 11258 /* @TODO */ 11259 NK_ASSERT(0); 11260 return 0; 11261 } 11262 NK_INTERN void 11263 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy) 11264 { 11265 v->type = type; 11266 v->x = (nk_short) x; 11267 v->y = (nk_short) y; 11268 v->cx = (nk_short) cx; 11269 v->cy = (nk_short) cy; 11270 } 11271 NK_INTERN int 11272 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index) 11273 { 11274 int g1,g2; 11275 if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */ 11276 if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */ 11277 11278 if (info->indexToLocFormat == 0) { 11279 g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; 11280 g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; 11281 } else { 11282 g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4); 11283 g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4); 11284 } 11285 return g1==g2 ? -1 : g1; /* if length is 0, return -1 */ 11286 } 11287 NK_INTERN int 11288 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index, 11289 int *x0, int *y0, int *x1, int *y1) 11290 { 11291 int g = nk_tt__GetGlyfOffset(info, glyph_index); 11292 if (g < 0) return 0; 11293 11294 if (x0) *x0 = nk_ttSHORT(info->data + g + 2); 11295 if (y0) *y0 = nk_ttSHORT(info->data + g + 4); 11296 if (x1) *x1 = nk_ttSHORT(info->data + g + 6); 11297 if (y1) *y1 = nk_ttSHORT(info->data + g + 8); 11298 return 1; 11299 } 11300 NK_INTERN int 11301 nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off, 11302 int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy) 11303 { 11304 if (start_off) { 11305 if (was_off) 11306 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); 11307 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy); 11308 } else { 11309 if (was_off) 11310 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy); 11311 else 11312 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0); 11313 } 11314 return num_vertices; 11315 } 11316 NK_INTERN int 11317 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, 11318 int glyph_index, struct nk_tt_vertex **pvertices) 11319 { 11320 nk_short numberOfContours; 11321 const nk_byte *endPtsOfContours; 11322 const nk_byte *data = info->data; 11323 struct nk_tt_vertex *vertices=0; 11324 int num_vertices=0; 11325 int g = nk_tt__GetGlyfOffset(info, glyph_index); 11326 *pvertices = 0; 11327 11328 if (g < 0) return 0; 11329 numberOfContours = nk_ttSHORT(data + g); 11330 if (numberOfContours > 0) { 11331 nk_byte flags=0,flagcount; 11332 nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; 11333 nk_int x,y,cx,cy,sx,sy, scx,scy; 11334 const nk_byte *points; 11335 endPtsOfContours = (data + g + 10); 11336 ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2); 11337 points = data + g + 10 + numberOfContours * 2 + 2 + ins; 11338 11339 n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2); 11340 m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */ 11341 vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0])); 11342 if (vertices == 0) 11343 return 0; 11344 11345 next_move = 0; 11346 flagcount=0; 11347 11348 /* in first pass, we load uninterpreted data into the allocated array */ 11349 /* above, shifted to the end of the array so we won't overwrite it when */ 11350 /* we create our final data starting from the front */ 11351 off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */ 11352 11353 /* first load flags */ 11354 for (i=0; i < n; ++i) { 11355 if (flagcount == 0) { 11356 flags = *points++; 11357 if (flags & 8) 11358 flagcount = *points++; 11359 } else --flagcount; 11360 vertices[off+i].type = flags; 11361 } 11362 11363 /* now load x coordinates */ 11364 x=0; 11365 for (i=0; i < n; ++i) { 11366 flags = vertices[off+i].type; 11367 if (flags & 2) { 11368 nk_short dx = *points++; 11369 x += (flags & 16) ? dx : -dx; /* ??? */ 11370 } else { 11371 if (!(flags & 16)) { 11372 x = x + (nk_short) (points[0]*256 + points[1]); 11373 points += 2; 11374 } 11375 } 11376 vertices[off+i].x = (nk_short) x; 11377 } 11378 11379 /* now load y coordinates */ 11380 y=0; 11381 for (i=0; i < n; ++i) { 11382 flags = vertices[off+i].type; 11383 if (flags & 4) { 11384 nk_short dy = *points++; 11385 y += (flags & 32) ? dy : -dy; /* ??? */ 11386 } else { 11387 if (!(flags & 32)) { 11388 y = y + (nk_short) (points[0]*256 + points[1]); 11389 points += 2; 11390 } 11391 } 11392 vertices[off+i].y = (nk_short) y; 11393 } 11394 11395 /* now convert them to our format */ 11396 num_vertices=0; 11397 sx = sy = cx = cy = scx = scy = 0; 11398 for (i=0; i < n; ++i) 11399 { 11400 flags = vertices[off+i].type; 11401 x = (nk_short) vertices[off+i].x; 11402 y = (nk_short) vertices[off+i].y; 11403 11404 if (next_move == i) { 11405 if (i != 0) 11406 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 11407 11408 /* now start the new one */ 11409 start_off = !(flags & 1); 11410 if (start_off) { 11411 /* if we start off with an off-curve point, then when we need to find a point on the curve */ 11412 /* where we can start, and we need to save some state for when we wraparound. */ 11413 scx = x; 11414 scy = y; 11415 if (!(vertices[off+i+1].type & 1)) { 11416 /* next point is also a curve point, so interpolate an on-point curve */ 11417 sx = (x + (nk_int) vertices[off+i+1].x) >> 1; 11418 sy = (y + (nk_int) vertices[off+i+1].y) >> 1; 11419 } else { 11420 /* otherwise just use the next point as our start point */ 11421 sx = (nk_int) vertices[off+i+1].x; 11422 sy = (nk_int) vertices[off+i+1].y; 11423 ++i; /* we're using point i+1 as the starting point, so skip it */ 11424 } 11425 } else { 11426 sx = x; 11427 sy = y; 11428 } 11429 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0); 11430 was_off = 0; 11431 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2); 11432 ++j; 11433 } else { 11434 if (!(flags & 1)) 11435 { /* if it's a curve */ 11436 if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */ 11437 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); 11438 cx = x; 11439 cy = y; 11440 was_off = 1; 11441 } else { 11442 if (was_off) 11443 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy); 11444 else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0); 11445 was_off = 0; 11446 } 11447 } 11448 } 11449 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 11450 } else if (numberOfContours == -1) { 11451 /* Compound shapes. */ 11452 int more = 1; 11453 const nk_byte *comp = data + g + 10; 11454 num_vertices = 0; 11455 vertices = 0; 11456 11457 while (more) 11458 { 11459 nk_ushort flags, gidx; 11460 int comp_num_verts = 0, i; 11461 struct nk_tt_vertex *comp_verts = 0, *tmp = 0; 11462 float mtx[6] = {1,0,0,1,0,0}, m, n; 11463 11464 flags = (nk_ushort)nk_ttSHORT(comp); comp+=2; 11465 gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2; 11466 11467 if (flags & 2) { /* XY values */ 11468 if (flags & 1) { /* shorts */ 11469 mtx[4] = nk_ttSHORT(comp); comp+=2; 11470 mtx[5] = nk_ttSHORT(comp); comp+=2; 11471 } else { 11472 mtx[4] = nk_ttCHAR(comp); comp+=1; 11473 mtx[5] = nk_ttCHAR(comp); comp+=1; 11474 } 11475 } else { 11476 /* @TODO handle matching point */ 11477 NK_ASSERT(0); 11478 } 11479 if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */ 11480 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11481 mtx[1] = mtx[2] = 0; 11482 } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */ 11483 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11484 mtx[1] = mtx[2] = 0; 11485 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11486 } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */ 11487 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11488 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11489 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11490 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11491 } 11492 11493 /* Find transformation scales. */ 11494 m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]); 11495 n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]); 11496 11497 /* Get indexed glyph. */ 11498 comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts); 11499 if (comp_num_verts > 0) 11500 { 11501 /* Transform vertices. */ 11502 for (i = 0; i < comp_num_verts; ++i) { 11503 struct nk_tt_vertex* v = &comp_verts[i]; 11504 short x,y; 11505 x=v->x; y=v->y; 11506 v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 11507 v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 11508 x=v->cx; y=v->cy; 11509 v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 11510 v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 11511 } 11512 /* Append vertices. */ 11513 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0, 11514 (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex)); 11515 if (!tmp) { 11516 if (vertices) alloc->free(alloc->userdata, vertices); 11517 if (comp_verts) alloc->free(alloc->userdata, comp_verts); 11518 return 0; 11519 } 11520 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex)); 11521 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex)); 11522 if (vertices) alloc->free(alloc->userdata,vertices); 11523 vertices = tmp; 11524 alloc->free(alloc->userdata,comp_verts); 11525 num_vertices += comp_num_verts; 11526 } 11527 /* More components ? */ 11528 more = flags & (1<<5); 11529 } 11530 } else if (numberOfContours < 0) { 11531 /* @TODO other compound variations? */ 11532 NK_ASSERT(0); 11533 } else { 11534 /* numberOfCounters == 0, do nothing */ 11535 } 11536 *pvertices = vertices; 11537 return num_vertices; 11538 } 11539 NK_INTERN void 11540 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index, 11541 int *advanceWidth, int *leftSideBearing) 11542 { 11543 nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34); 11544 if (glyph_index < numOfLongHorMetrics) { 11545 if (advanceWidth) 11546 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index); 11547 if (leftSideBearing) 11548 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); 11549 } else { 11550 if (advanceWidth) 11551 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); 11552 if (leftSideBearing) 11553 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); 11554 } 11555 } 11556 NK_INTERN void 11557 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info, 11558 int *ascent, int *descent, int *lineGap) 11559 { 11560 if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4); 11561 if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6); 11562 if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8); 11563 } 11564 NK_INTERN float 11565 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height) 11566 { 11567 int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6); 11568 return (float) height / (float)fheight; 11569 } 11570 NK_INTERN float 11571 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels) 11572 { 11573 int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18); 11574 return pixels / (float)unitsPerEm; 11575 } 11576 11577 /*------------------------------------------------------------- 11578 * antialiasing software rasterizer 11579 * --------------------------------------------------------------*/ 11580 NK_INTERN void 11581 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font, 11582 int glyph, float scale_x, float scale_y,float shift_x, float shift_y, 11583 int *ix0, int *iy0, int *ix1, int *iy1) 11584 { 11585 int x0,y0,x1,y1; 11586 if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { 11587 /* e.g. space character */ 11588 if (ix0) *ix0 = 0; 11589 if (iy0) *iy0 = 0; 11590 if (ix1) *ix1 = 0; 11591 if (iy1) *iy1 = 0; 11592 } else { 11593 /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */ 11594 if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x); 11595 if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y); 11596 if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x); 11597 if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y); 11598 } 11599 } 11600 NK_INTERN void 11601 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph, 11602 float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) 11603 { 11604 nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); 11605 } 11606 11607 /*------------------------------------------------------------- 11608 * Rasterizer 11609 * --------------------------------------------------------------*/ 11610 NK_INTERN void* 11611 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size) 11612 { 11613 if (hh->first_free) { 11614 void *p = hh->first_free; 11615 hh->first_free = * (void **) p; 11616 return p; 11617 } else { 11618 if (hh->num_remaining_in_head_chunk == 0) { 11619 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); 11620 struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *) 11621 hh->alloc.alloc(hh->alloc.userdata, 0, 11622 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count); 11623 if (c == 0) return 0; 11624 c->next = hh->head; 11625 hh->head = c; 11626 hh->num_remaining_in_head_chunk = count; 11627 } 11628 --hh->num_remaining_in_head_chunk; 11629 return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk; 11630 } 11631 } 11632 NK_INTERN void 11633 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p) 11634 { 11635 *(void **) p = hh->first_free; 11636 hh->first_free = p; 11637 } 11638 NK_INTERN void 11639 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh) 11640 { 11641 struct nk_tt__hheap_chunk *c = hh->head; 11642 while (c) { 11643 struct nk_tt__hheap_chunk *n = c->next; 11644 hh->alloc.free(hh->alloc.userdata, c); 11645 c = n; 11646 } 11647 } 11648 NK_INTERN struct nk_tt__active_edge* 11649 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e, 11650 int off_x, float start_point) 11651 { 11652 struct nk_tt__active_edge *z = (struct nk_tt__active_edge *) 11653 nk_tt__hheap_alloc(hh, sizeof(*z)); 11654 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 11655 /*STBTT_assert(e->y0 <= start_point); */ 11656 if (!z) return z; 11657 z->fdx = dxdy; 11658 z->fdy = (dxdy != 0) ? (1/dxdy): 0; 11659 z->fx = e->x0 + dxdy * (start_point - e->y0); 11660 z->fx -= (float)off_x; 11661 z->direction = e->invert ? 1.0f : -1.0f; 11662 z->sy = e->y0; 11663 z->ey = e->y1; 11664 z->next = 0; 11665 return z; 11666 } 11667 NK_INTERN void 11668 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e, 11669 float x0, float y0, float x1, float y1) 11670 { 11671 if (y0 == y1) return; 11672 NK_ASSERT(y0 < y1); 11673 NK_ASSERT(e->sy <= e->ey); 11674 if (y0 > e->ey) return; 11675 if (y1 < e->sy) return; 11676 if (y0 < e->sy) { 11677 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); 11678 y0 = e->sy; 11679 } 11680 if (y1 > e->ey) { 11681 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); 11682 y1 = e->ey; 11683 } 11684 11685 if (x0 == x) NK_ASSERT(x1 <= x+1); 11686 else if (x0 == x+1) NK_ASSERT(x1 >= x); 11687 else if (x0 <= x) NK_ASSERT(x1 <= x); 11688 else if (x0 >= x+1) NK_ASSERT(x1 >= x+1); 11689 else NK_ASSERT(x1 >= x && x1 <= x+1); 11690 11691 if (x0 <= x && x1 <= x) 11692 scanline[x] += e->direction * (y1-y0); 11693 else if (x0 >= x+1 && x1 >= x+1); 11694 else { 11695 NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); 11696 /* coverage = 1 - average x position */ 11697 scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f); 11698 } 11699 } 11700 NK_INTERN void 11701 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, 11702 struct nk_tt__active_edge *e, float y_top) 11703 { 11704 float y_bottom = y_top+1; 11705 while (e) 11706 { 11707 /* brute force every pixel */ 11708 /* compute intersection points with top & bottom */ 11709 NK_ASSERT(e->ey >= y_top); 11710 if (e->fdx == 0) { 11711 float x0 = e->fx; 11712 if (x0 < len) { 11713 if (x0 >= 0) { 11714 nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); 11715 nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); 11716 } else { 11717 nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); 11718 } 11719 } 11720 } else { 11721 float x0 = e->fx; 11722 float dx = e->fdx; 11723 float xb = x0 + dx; 11724 float x_top, x_bottom; 11725 float y0,y1; 11726 float dy = e->fdy; 11727 NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top); 11728 11729 /* compute endpoints of line segment clipped to this scanline (if the */ 11730 /* line segment starts on this scanline. x0 is the intersection of the */ 11731 /* line with y_top, but that may be off the line segment. */ 11732 if (e->sy > y_top) { 11733 x_top = x0 + dx * (e->sy - y_top); 11734 y0 = e->sy; 11735 } else { 11736 x_top = x0; 11737 y0 = y_top; 11738 } 11739 11740 if (e->ey < y_bottom) { 11741 x_bottom = x0 + dx * (e->ey - y_top); 11742 y1 = e->ey; 11743 } else { 11744 x_bottom = xb; 11745 y1 = y_bottom; 11746 } 11747 11748 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) 11749 { 11750 /* from here on, we don't have to range check x values */ 11751 if ((int) x_top == (int) x_bottom) { 11752 float height; 11753 /* simple case, only spans one pixel */ 11754 int x = (int) x_top; 11755 height = y1 - y0; 11756 NK_ASSERT(x >= 0 && x < len); 11757 scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height; 11758 scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */ 11759 } else { 11760 int x,x1,x2; 11761 float y_crossing, step, sign, area; 11762 /* covers 2+ pixels */ 11763 if (x_top > x_bottom) 11764 { 11765 /* flip scanline vertically; signed area is the same */ 11766 float t; 11767 y0 = y_bottom - (y0 - y_top); 11768 y1 = y_bottom - (y1 - y_top); 11769 t = y0; y0 = y1; y1 = t; 11770 t = x_bottom; x_bottom = x_top; x_top = t; 11771 dx = -dx; 11772 dy = -dy; 11773 t = x0; x0 = xb; xb = t; 11774 } 11775 11776 x1 = (int) x_top; 11777 x2 = (int) x_bottom; 11778 /* compute intersection with y axis at x1+1 */ 11779 y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top; 11780 11781 sign = e->direction; 11782 /* area of the rectangle covered from y0..y_crossing */ 11783 area = sign * (y_crossing-y0); 11784 /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */ 11785 scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f); 11786 11787 step = sign * dy; 11788 for (x = x1+1; x < x2; ++x) { 11789 scanline[x] += area + step/2; 11790 area += step; 11791 } 11792 y_crossing += (float)dy * (float)(x2 - (x1+1)); 11793 11794 scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing); 11795 scanline_fill[x2] += sign * (y1-y0); 11796 } 11797 } 11798 else 11799 { 11800 /* if edge goes outside of box we're drawing, we require */ 11801 /* clipping logic. since this does not match the intended use */ 11802 /* of this library, we use a different, very slow brute */ 11803 /* force implementation */ 11804 int x; 11805 for (x=0; x < len; ++x) 11806 { 11807 /* cases: */ 11808 /* */ 11809 /* there can be up to two intersections with the pixel. any intersection */ 11810 /* with left or right edges can be handled by splitting into two (or three) */ 11811 /* regions. intersections with top & bottom do not necessitate case-wise logic. */ 11812 /* */ 11813 /* the old way of doing this found the intersections with the left & right edges, */ 11814 /* then used some simple logic to produce up to three segments in sorted order */ 11815 /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */ 11816 /* across the x border, then the corresponding y position might not be distinct */ 11817 /* from the other y segment, and it might ignored as an empty segment. to avoid */ 11818 /* that, we need to explicitly produce segments based on x positions. */ 11819 11820 /* rename variables to clear pairs */ 11821 float ya = y_top; 11822 float x1 = (float) (x); 11823 float x2 = (float) (x+1); 11824 float x3 = xb; 11825 float y3 = y_bottom; 11826 float yb,y2; 11827 11828 yb = ((float)x - x0) / dx + y_top; 11829 y2 = ((float)x+1 - x0) / dx + y_top; 11830 11831 if (x0 < x1 && x3 > x2) { /* three segments descending down-right */ 11832 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11833 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2); 11834 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11835 } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */ 11836 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11837 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb); 11838 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11839 } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */ 11840 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11841 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11842 } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */ 11843 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11844 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11845 } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */ 11846 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11847 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11848 } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */ 11849 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11850 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11851 } else { /* one segment */ 11852 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3); 11853 } 11854 } 11855 } 11856 } 11857 e = e->next; 11858 } 11859 } 11860 NK_INTERN void 11861 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e, 11862 int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc) 11863 { 11864 /* directly AA rasterize edges w/o supersampling */ 11865 struct nk_tt__hheap hh; 11866 struct nk_tt__active_edge *active = 0; 11867 int y,j=0, i; 11868 float scanline_data[129], *scanline, *scanline2; 11869 11870 NK_UNUSED(vsubsample); 11871 nk_zero_struct(hh); 11872 hh.alloc = *alloc; 11873 11874 if (result->w > 64) 11875 scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float)); 11876 else scanline = scanline_data; 11877 11878 scanline2 = scanline + result->w; 11879 y = off_y; 11880 e[n].y0 = (float) (off_y + result->h) + 1; 11881 11882 while (j < result->h) 11883 { 11884 /* find center of pixel for this scanline */ 11885 float scan_y_top = (float)y + 0.0f; 11886 float scan_y_bottom = (float)y + 1.0f; 11887 struct nk_tt__active_edge **step = &active; 11888 11889 NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0])); 11890 NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0])); 11891 11892 /* update all active edges; */ 11893 /* remove all active edges that terminate before the top of this scanline */ 11894 while (*step) { 11895 struct nk_tt__active_edge * z = *step; 11896 if (z->ey <= scan_y_top) { 11897 *step = z->next; /* delete from list */ 11898 NK_ASSERT(z->direction); 11899 z->direction = 0; 11900 nk_tt__hheap_free(&hh, z); 11901 } else { 11902 step = &((*step)->next); /* advance through list */ 11903 } 11904 } 11905 11906 /* insert all edges that start before the bottom of this scanline */ 11907 while (e->y0 <= scan_y_bottom) { 11908 if (e->y0 != e->y1) { 11909 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top); 11910 if (z != 0) { 11911 NK_ASSERT(z->ey >= scan_y_top); 11912 /* insert at front */ 11913 z->next = active; 11914 active = z; 11915 } 11916 } 11917 ++e; 11918 } 11919 11920 /* now process all active edges */ 11921 if (active) 11922 nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); 11923 11924 { 11925 float sum = 0; 11926 for (i=0; i < result->w; ++i) { 11927 float k; 11928 int m; 11929 sum += scanline2[i]; 11930 k = scanline[i] + sum; 11931 k = (float) NK_ABS(k) * 255.0f + 0.5f; 11932 m = (int) k; 11933 if (m > 255) m = 255; 11934 result->pixels[j*result->stride + i] = (unsigned char) m; 11935 } 11936 } 11937 /* advance all the edges */ 11938 step = &active; 11939 while (*step) { 11940 struct nk_tt__active_edge *z = *step; 11941 z->fx += z->fdx; /* advance to position for current scanline */ 11942 step = &((*step)->next); /* advance through list */ 11943 } 11944 ++y; 11945 ++j; 11946 } 11947 nk_tt__hheap_cleanup(&hh); 11948 if (scanline != scanline_data) 11949 alloc->free(alloc->userdata, scanline); 11950 } 11951 NK_INTERN void 11952 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n) 11953 { 11954 int i,j; 11955 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0) 11956 for (i=1; i < n; ++i) { 11957 struct nk_tt__edge t = p[i], *a = &t; 11958 j = i; 11959 while (j > 0) { 11960 struct nk_tt__edge *b = &p[j-1]; 11961 int c = NK_TT__COMPARE(a,b); 11962 if (!c) break; 11963 p[j] = p[j-1]; 11964 --j; 11965 } 11966 if (i != j) 11967 p[j] = t; 11968 } 11969 } 11970 NK_INTERN void 11971 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n) 11972 { 11973 /* threshold for transitioning to insertion sort */ 11974 while (n > 12) { 11975 struct nk_tt__edge t; 11976 int c01,c12,c,m,i,j; 11977 11978 /* compute median of three */ 11979 m = n >> 1; 11980 c01 = NK_TT__COMPARE(&p[0],&p[m]); 11981 c12 = NK_TT__COMPARE(&p[m],&p[n-1]); 11982 11983 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ 11984 if (c01 != c12) { 11985 /* otherwise, we'll need to swap something else to middle */ 11986 int z; 11987 c = NK_TT__COMPARE(&p[0],&p[n-1]); 11988 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ 11989 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ 11990 z = (c == c12) ? 0 : n-1; 11991 t = p[z]; 11992 p[z] = p[m]; 11993 p[m] = t; 11994 } 11995 11996 /* now p[m] is the median-of-three */ 11997 /* swap it to the beginning so it won't move around */ 11998 t = p[0]; 11999 p[0] = p[m]; 12000 p[m] = t; 12001 12002 /* partition loop */ 12003 i=1; 12004 j=n-1; 12005 for(;;) { 12006 /* handling of equality is crucial here */ 12007 /* for sentinels & efficiency with duplicates */ 12008 for (;;++i) { 12009 if (!NK_TT__COMPARE(&p[i], &p[0])) break; 12010 } 12011 for (;;--j) { 12012 if (!NK_TT__COMPARE(&p[0], &p[j])) break; 12013 } 12014 12015 /* make sure we haven't crossed */ 12016 if (i >= j) break; 12017 t = p[i]; 12018 p[i] = p[j]; 12019 p[j] = t; 12020 12021 ++i; 12022 --j; 12023 12024 } 12025 12026 /* recurse on smaller side, iterate on larger */ 12027 if (j < (n-i)) { 12028 nk_tt__sort_edges_quicksort(p,j); 12029 p = p+i; 12030 n = n-i; 12031 } else { 12032 nk_tt__sort_edges_quicksort(p+i, n-i); 12033 n = j; 12034 } 12035 } 12036 } 12037 NK_INTERN void 12038 nk_tt__sort_edges(struct nk_tt__edge *p, int n) 12039 { 12040 nk_tt__sort_edges_quicksort(p, n); 12041 nk_tt__sort_edges_ins_sort(p, n); 12042 } 12043 NK_INTERN void 12044 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts, 12045 int *wcount, int windings, float scale_x, float scale_y, 12046 float shift_x, float shift_y, int off_x, int off_y, int invert, 12047 struct nk_allocator *alloc) 12048 { 12049 float y_scale_inv = invert ? -scale_y : scale_y; 12050 struct nk_tt__edge *e; 12051 int n,i,j,k,m; 12052 int vsubsample = 1; 12053 /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */ 12054 12055 /* now we have to blow out the windings into explicit edge lists */ 12056 n = 0; 12057 for (i=0; i < windings; ++i) 12058 n += wcount[i]; 12059 12060 e = (struct nk_tt__edge*) 12061 alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1))); 12062 if (e == 0) return; 12063 n = 0; 12064 12065 m=0; 12066 for (i=0; i < windings; ++i) 12067 { 12068 struct nk_tt__point *p = pts + m; 12069 m += wcount[i]; 12070 j = wcount[i]-1; 12071 for (k=0; k < wcount[i]; j=k++) { 12072 int a=k,b=j; 12073 /* skip the edge if horizontal */ 12074 if (p[j].y == p[k].y) 12075 continue; 12076 12077 /* add edge from j to k to the list */ 12078 e[n].invert = 0; 12079 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { 12080 e[n].invert = 1; 12081 a=j,b=k; 12082 } 12083 e[n].x0 = p[a].x * scale_x + shift_x; 12084 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample; 12085 e[n].x1 = p[b].x * scale_x + shift_x; 12086 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample; 12087 ++n; 12088 } 12089 } 12090 12091 /* now sort the edges by their highest point (should snap to integer, and then by x) */ 12092 /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */ 12093 nk_tt__sort_edges(e, n); 12094 /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */ 12095 nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc); 12096 alloc->free(alloc->userdata, e); 12097 } 12098 NK_INTERN void 12099 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y) 12100 { 12101 if (!points) return; /* during first pass, it's unallocated */ 12102 points[n].x = x; 12103 points[n].y = y; 12104 } 12105 NK_INTERN int 12106 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points, 12107 float x0, float y0, float x1, float y1, float x2, float y2, 12108 float objspace_flatness_squared, int n) 12109 { 12110 /* tesselate until threshold p is happy... 12111 * @TODO warped to compensate for non-linear stretching */ 12112 /* midpoint */ 12113 float mx = (x0 + 2*x1 + x2)/4; 12114 float my = (y0 + 2*y1 + y2)/4; 12115 /* versus directly drawn line */ 12116 float dx = (x0+x2)/2 - mx; 12117 float dy = (y0+y2)/2 - my; 12118 if (n > 16) /* 65536 segments on one curve better be enough! */ 12119 return 1; 12120 12121 /* half-pixel error allowed... need to be smaller if AA */ 12122 if (dx*dx+dy*dy > objspace_flatness_squared) { 12123 nk_tt__tesselate_curve(points, num_points, x0,y0, 12124 (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); 12125 nk_tt__tesselate_curve(points, num_points, mx,my, 12126 (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); 12127 } else { 12128 nk_tt__add_point(points, *num_points,x2,y2); 12129 *num_points = *num_points+1; 12130 } 12131 return 1; 12132 } 12133 NK_INTERN struct nk_tt__point* 12134 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts, 12135 float objspace_flatness, int **contour_lengths, int *num_contours, 12136 struct nk_allocator *alloc) 12137 { 12138 /* returns number of contours */ 12139 struct nk_tt__point *points=0; 12140 int num_points=0; 12141 float objspace_flatness_squared = objspace_flatness * objspace_flatness; 12142 int i; 12143 int n=0; 12144 int start=0; 12145 int pass; 12146 12147 /* count how many "moves" there are to get the contour count */ 12148 for (i=0; i < num_verts; ++i) 12149 if (vertices[i].type == NK_TT_vmove) ++n; 12150 12151 *num_contours = n; 12152 if (n == 0) return 0; 12153 12154 *contour_lengths = (int *) 12155 alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n)); 12156 if (*contour_lengths == 0) { 12157 *num_contours = 0; 12158 return 0; 12159 } 12160 12161 /* make two passes through the points so we don't need to realloc */ 12162 for (pass=0; pass < 2; ++pass) 12163 { 12164 float x=0,y=0; 12165 if (pass == 1) { 12166 points = (struct nk_tt__point *) 12167 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0])); 12168 if (points == 0) goto error; 12169 } 12170 num_points = 0; 12171 n= -1; 12172 12173 for (i=0; i < num_verts; ++i) 12174 { 12175 switch (vertices[i].type) { 12176 case NK_TT_vmove: 12177 /* start the next contour */ 12178 if (n >= 0) 12179 (*contour_lengths)[n] = num_points - start; 12180 ++n; 12181 start = num_points; 12182 12183 x = vertices[i].x, y = vertices[i].y; 12184 nk_tt__add_point(points, num_points++, x,y); 12185 break; 12186 case NK_TT_vline: 12187 x = vertices[i].x, y = vertices[i].y; 12188 nk_tt__add_point(points, num_points++, x, y); 12189 break; 12190 case NK_TT_vcurve: 12191 nk_tt__tesselate_curve(points, &num_points, x,y, 12192 vertices[i].cx, vertices[i].cy, 12193 vertices[i].x, vertices[i].y, 12194 objspace_flatness_squared, 0); 12195 x = vertices[i].x, y = vertices[i].y; 12196 break; 12197 default: break; 12198 } 12199 } 12200 (*contour_lengths)[n] = num_points - start; 12201 } 12202 return points; 12203 12204 error: 12205 alloc->free(alloc->userdata, points); 12206 alloc->free(alloc->userdata, *contour_lengths); 12207 *contour_lengths = 0; 12208 *num_contours = 0; 12209 return 0; 12210 } 12211 NK_INTERN void 12212 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels, 12213 struct nk_tt_vertex *vertices, int num_verts, 12214 float scale_x, float scale_y, float shift_x, float shift_y, 12215 int x_off, int y_off, int invert, struct nk_allocator *alloc) 12216 { 12217 float scale = scale_x > scale_y ? scale_y : scale_x; 12218 int winding_count, *winding_lengths; 12219 struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts, 12220 flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc); 12221 12222 NK_ASSERT(alloc); 12223 if (windings) { 12224 nk_tt__rasterize(result, windings, winding_lengths, winding_count, 12225 scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc); 12226 alloc->free(alloc->userdata, winding_lengths); 12227 alloc->free(alloc->userdata, windings); 12228 } 12229 } 12230 NK_INTERN void 12231 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output, 12232 int out_w, int out_h, int out_stride, float scale_x, float scale_y, 12233 float shift_x, float shift_y, int glyph, struct nk_allocator *alloc) 12234 { 12235 int ix0,iy0; 12236 struct nk_tt_vertex *vertices; 12237 int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices); 12238 struct nk_tt__bitmap gbm; 12239 12240 nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, 12241 shift_y, &ix0,&iy0,0,0); 12242 gbm.pixels = output; 12243 gbm.w = out_w; 12244 gbm.h = out_h; 12245 gbm.stride = out_stride; 12246 12247 if (gbm.w && gbm.h) 12248 nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, 12249 shift_x, shift_y, ix0,iy0, 1, alloc); 12250 alloc->free(alloc->userdata, vertices); 12251 } 12252 12253 /*------------------------------------------------------------- 12254 * Bitmap baking 12255 * --------------------------------------------------------------*/ 12256 NK_INTERN int 12257 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels, 12258 int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc) 12259 { 12260 int num_nodes = pw - padding; 12261 struct nk_rp_context *context = (struct nk_rp_context *) 12262 alloc->alloc(alloc->userdata,0, sizeof(*context)); 12263 struct nk_rp_node *nodes = (struct nk_rp_node*) 12264 alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes)); 12265 12266 if (context == 0 || nodes == 0) { 12267 if (context != 0) alloc->free(alloc->userdata, context); 12268 if (nodes != 0) alloc->free(alloc->userdata, nodes); 12269 return 0; 12270 } 12271 12272 spc->width = pw; 12273 spc->height = ph; 12274 spc->pixels = pixels; 12275 spc->pack_info = context; 12276 spc->nodes = nodes; 12277 spc->padding = padding; 12278 spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw; 12279 spc->h_oversample = 1; 12280 spc->v_oversample = 1; 12281 12282 nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); 12283 if (pixels) 12284 NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */ 12285 return 1; 12286 } 12287 NK_INTERN void 12288 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc) 12289 { 12290 alloc->free(alloc->userdata, spc->nodes); 12291 alloc->free(alloc->userdata, spc->pack_info); 12292 } 12293 NK_INTERN void 12294 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc, 12295 unsigned int h_oversample, unsigned int v_oversample) 12296 { 12297 NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE); 12298 NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE); 12299 if (h_oversample <= NK_TT_MAX_OVERSAMPLE) 12300 spc->h_oversample = h_oversample; 12301 if (v_oversample <= NK_TT_MAX_OVERSAMPLE) 12302 spc->v_oversample = v_oversample; 12303 } 12304 NK_INTERN void 12305 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, 12306 int kernel_width) 12307 { 12308 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; 12309 int safe_w = w - kernel_width; 12310 int j; 12311 12312 for (j=0; j < h; ++j) 12313 { 12314 int i; 12315 unsigned int total; 12316 NK_MEMSET(buffer, 0, (nk_size)kernel_width); 12317 12318 total = 0; 12319 12320 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 12321 switch (kernel_width) { 12322 case 2: 12323 for (i=0; i <= safe_w; ++i) { 12324 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12325 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12326 pixels[i] = (unsigned char) (total / 2); 12327 } 12328 break; 12329 case 3: 12330 for (i=0; i <= safe_w; ++i) { 12331 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12332 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12333 pixels[i] = (unsigned char) (total / 3); 12334 } 12335 break; 12336 case 4: 12337 for (i=0; i <= safe_w; ++i) { 12338 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK]; 12339 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12340 pixels[i] = (unsigned char) (total / 4); 12341 } 12342 break; 12343 case 5: 12344 for (i=0; i <= safe_w; ++i) { 12345 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12346 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12347 pixels[i] = (unsigned char) (total / 5); 12348 } 12349 break; 12350 default: 12351 for (i=0; i <= safe_w; ++i) { 12352 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12353 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12354 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); 12355 } 12356 break; 12357 } 12358 12359 for (; i < w; ++i) { 12360 NK_ASSERT(pixels[i] == 0); 12361 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); 12362 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); 12363 } 12364 pixels += stride_in_bytes; 12365 } 12366 } 12367 NK_INTERN void 12368 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, 12369 int kernel_width) 12370 { 12371 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; 12372 int safe_h = h - kernel_width; 12373 int j; 12374 12375 for (j=0; j < w; ++j) 12376 { 12377 int i; 12378 unsigned int total; 12379 NK_MEMSET(buffer, 0, (nk_size)kernel_width); 12380 12381 total = 0; 12382 12383 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 12384 switch (kernel_width) { 12385 case 2: 12386 for (i=0; i <= safe_h; ++i) { 12387 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12388 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12389 pixels[i*stride_in_bytes] = (unsigned char) (total / 2); 12390 } 12391 break; 12392 case 3: 12393 for (i=0; i <= safe_h; ++i) { 12394 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12395 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12396 pixels[i*stride_in_bytes] = (unsigned char) (total / 3); 12397 } 12398 break; 12399 case 4: 12400 for (i=0; i <= safe_h; ++i) { 12401 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12402 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12403 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); 12404 } 12405 break; 12406 case 5: 12407 for (i=0; i <= safe_h; ++i) { 12408 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12409 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12410 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); 12411 } 12412 break; 12413 default: 12414 for (i=0; i <= safe_h; ++i) { 12415 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12416 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12417 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); 12418 } 12419 break; 12420 } 12421 12422 for (; i < h; ++i) { 12423 NK_ASSERT(pixels[i*stride_in_bytes] == 0); 12424 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); 12425 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); 12426 } 12427 pixels += 1; 12428 } 12429 } 12430 NK_INTERN float 12431 nk_tt__oversample_shift(int oversample) 12432 { 12433 if (!oversample) 12434 return 0.0f; 12435 12436 /* The prefilter is a box filter of width "oversample", */ 12437 /* which shifts phase by (oversample - 1)/2 pixels in */ 12438 /* oversampled space. We want to shift in the opposite */ 12439 /* direction to counter this. */ 12440 return (float)-(oversample - 1) / (2.0f * (float)oversample); 12441 } 12442 NK_INTERN int 12443 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc, 12444 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, 12445 int num_ranges, struct nk_rp_rect *rects) 12446 { 12447 /* rects array must be big enough to accommodate all characters in the given ranges */ 12448 int i,j,k; 12449 k = 0; 12450 12451 for (i=0; i < num_ranges; ++i) { 12452 float fh = ranges[i].font_size; 12453 float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh): 12454 nk_tt_ScaleForMappingEmToPixels(info, -fh); 12455 ranges[i].h_oversample = (unsigned char) spc->h_oversample; 12456 ranges[i].v_oversample = (unsigned char) spc->v_oversample; 12457 for (j=0; j < ranges[i].num_chars; ++j) { 12458 int x0,y0,x1,y1; 12459 int codepoint = ranges[i].first_unicode_codepoint_in_range ? 12460 ranges[i].first_unicode_codepoint_in_range + j : 12461 ranges[i].array_of_unicode_codepoints[j]; 12462 12463 int glyph = nk_tt_FindGlyphIndex(info, codepoint); 12464 nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample, 12465 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); 12466 rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1); 12467 rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1); 12468 ++k; 12469 } 12470 } 12471 return k; 12472 } 12473 NK_INTERN int 12474 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc, 12475 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, 12476 int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc) 12477 { 12478 int i,j,k, return_value = 1; 12479 /* save current values */ 12480 int old_h_over = (int)spc->h_oversample; 12481 int old_v_over = (int)spc->v_oversample; 12482 /* rects array must be big enough to accommodate all characters in the given ranges */ 12483 12484 k = 0; 12485 for (i=0; i < num_ranges; ++i) 12486 { 12487 float fh = ranges[i].font_size; 12488 float recip_h,recip_v,sub_x,sub_y; 12489 float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh): 12490 nk_tt_ScaleForMappingEmToPixels(info, -fh); 12491 12492 spc->h_oversample = ranges[i].h_oversample; 12493 spc->v_oversample = ranges[i].v_oversample; 12494 12495 recip_h = 1.0f / (float)spc->h_oversample; 12496 recip_v = 1.0f / (float)spc->v_oversample; 12497 12498 sub_x = nk_tt__oversample_shift((int)spc->h_oversample); 12499 sub_y = nk_tt__oversample_shift((int)spc->v_oversample); 12500 12501 for (j=0; j < ranges[i].num_chars; ++j) 12502 { 12503 struct nk_rp_rect *r = &rects[k]; 12504 if (r->was_packed) 12505 { 12506 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j]; 12507 int advance, lsb, x0,y0,x1,y1; 12508 int codepoint = ranges[i].first_unicode_codepoint_in_range ? 12509 ranges[i].first_unicode_codepoint_in_range + j : 12510 ranges[i].array_of_unicode_codepoints[j]; 12511 int glyph = nk_tt_FindGlyphIndex(info, codepoint); 12512 nk_rp_coord pad = (nk_rp_coord) spc->padding; 12513 12514 /* pad on left and top */ 12515 r->x = (nk_rp_coord)((int)r->x + (int)pad); 12516 r->y = (nk_rp_coord)((int)r->y + (int)pad); 12517 r->w = (nk_rp_coord)((int)r->w - (int)pad); 12518 r->h = (nk_rp_coord)((int)r->h - (int)pad); 12519 12520 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb); 12521 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample, 12522 (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1); 12523 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, 12524 (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1), 12525 spc->stride_in_bytes, scale * (float)spc->h_oversample, 12526 scale * (float)spc->v_oversample, 0,0, glyph, alloc); 12527 12528 if (spc->h_oversample > 1) 12529 nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 12530 r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample); 12531 12532 if (spc->v_oversample > 1) 12533 nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 12534 r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample); 12535 12536 bc->x0 = (nk_ushort) r->x; 12537 bc->y0 = (nk_ushort) r->y; 12538 bc->x1 = (nk_ushort) (r->x + r->w); 12539 bc->y1 = (nk_ushort) (r->y + r->h); 12540 bc->xadvance = scale * (float)advance; 12541 bc->xoff = (float) x0 * recip_h + sub_x; 12542 bc->yoff = (float) y0 * recip_v + sub_y; 12543 bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x; 12544 bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y; 12545 } else { 12546 return_value = 0; /* if any fail, report failure */ 12547 } 12548 ++k; 12549 } 12550 } 12551 /* restore original values */ 12552 spc->h_oversample = (unsigned int)old_h_over; 12553 spc->v_oversample = (unsigned int)old_v_over; 12554 return return_value; 12555 } 12556 NK_INTERN void 12557 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph, 12558 int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q, 12559 int align_to_integer) 12560 { 12561 float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph; 12562 struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index); 12563 if (align_to_integer) { 12564 int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f); 12565 int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f); 12566 12567 float x = (float)tx; 12568 float y = (float)ty; 12569 12570 q->x0 = x; 12571 q->y0 = y; 12572 q->x1 = x + b->xoff2 - b->xoff; 12573 q->y1 = y + b->yoff2 - b->yoff; 12574 } else { 12575 q->x0 = *xpos + b->xoff; 12576 q->y0 = *ypos + b->yoff; 12577 q->x1 = *xpos + b->xoff2; 12578 q->y1 = *ypos + b->yoff2; 12579 } 12580 q->s0 = b->x0 * ipw; 12581 q->t0 = b->y0 * iph; 12582 q->s1 = b->x1 * ipw; 12583 q->t1 = b->y1 * iph; 12584 *xpos += b->xadvance; 12585 } 12586 12587 /* ------------------------------------------------------------- 12588 * 12589 * FONT BAKING 12590 * 12591 * --------------------------------------------------------------*/ 12592 struct nk_font_bake_data { 12593 struct nk_tt_fontinfo info; 12594 struct nk_rp_rect *rects; 12595 struct nk_tt_pack_range *ranges; 12596 nk_rune range_count; 12597 }; 12598 12599 struct nk_font_baker { 12600 struct nk_allocator alloc; 12601 struct nk_tt_pack_context spc; 12602 struct nk_font_bake_data *build; 12603 struct nk_tt_packedchar *packed_chars; 12604 struct nk_rp_rect *rects; 12605 struct nk_tt_pack_range *ranges; 12606 }; 12607 12608 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect); 12609 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range); 12610 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar); 12611 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data); 12612 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker); 12613 12614 NK_INTERN int 12615 nk_range_count(const nk_rune *range) 12616 { 12617 const nk_rune *iter = range; 12618 NK_ASSERT(range); 12619 if (!range) return 0; 12620 while (*(iter++) != 0); 12621 return (iter == range) ? 0 : (int)((iter - range)/2); 12622 } 12623 NK_INTERN int 12624 nk_range_glyph_count(const nk_rune *range, int count) 12625 { 12626 int i = 0; 12627 int total_glyphs = 0; 12628 for (i = 0; i < count; ++i) { 12629 int diff; 12630 nk_rune f = range[(i*2)+0]; 12631 nk_rune t = range[(i*2)+1]; 12632 NK_ASSERT(t >= f); 12633 diff = (int)((t - f) + 1); 12634 total_glyphs += diff; 12635 } 12636 return total_glyphs; 12637 } 12638 NK_API const nk_rune* 12639 nk_font_default_glyph_ranges(void) 12640 { 12641 NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0}; 12642 return ranges; 12643 } 12644 NK_API const nk_rune* 12645 nk_font_chinese_glyph_ranges(void) 12646 { 12647 NK_STORAGE const nk_rune ranges[] = { 12648 0x0020, 0x00FF, 12649 0x3000, 0x30FF, 12650 0x31F0, 0x31FF, 12651 0xFF00, 0xFFEF, 12652 0x4e00, 0x9FAF, 12653 0 12654 }; 12655 return ranges; 12656 } 12657 NK_API const nk_rune* 12658 nk_font_cyrillic_glyph_ranges(void) 12659 { 12660 NK_STORAGE const nk_rune ranges[] = { 12661 0x0020, 0x00FF, 12662 0x0400, 0x052F, 12663 0x2DE0, 0x2DFF, 12664 0xA640, 0xA69F, 12665 0 12666 }; 12667 return ranges; 12668 } 12669 NK_API const nk_rune* 12670 nk_font_korean_glyph_ranges(void) 12671 { 12672 NK_STORAGE const nk_rune ranges[] = { 12673 0x0020, 0x00FF, 12674 0x3131, 0x3163, 12675 0xAC00, 0xD79D, 12676 0 12677 }; 12678 return ranges; 12679 } 12680 NK_INTERN void 12681 nk_font_baker_memory(nk_size *temp, int *glyph_count, 12682 struct nk_font_config *config_list, int count) 12683 { 12684 int range_count = 0; 12685 int total_range_count = 0; 12686 struct nk_font_config *iter, *i; 12687 12688 NK_ASSERT(config_list); 12689 NK_ASSERT(glyph_count); 12690 if (!config_list) { 12691 *temp = 0; 12692 *glyph_count = 0; 12693 return; 12694 } 12695 *glyph_count = 0; 12696 for (iter = config_list; iter; iter = iter->next) { 12697 i = iter; 12698 do {if (!i->range) iter->range = nk_font_default_glyph_ranges(); 12699 range_count = nk_range_count(i->range); 12700 total_range_count += range_count; 12701 *glyph_count += nk_range_glyph_count(i->range, range_count); 12702 } while ((i = i->n) != iter); 12703 } 12704 *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect); 12705 *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range); 12706 *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar); 12707 *temp += (nk_size)count * sizeof(struct nk_font_bake_data); 12708 *temp += sizeof(struct nk_font_baker); 12709 *temp += nk_rect_align + nk_range_align + nk_char_align; 12710 *temp += nk_build_align + nk_baker_align; 12711 } 12712 NK_INTERN struct nk_font_baker* 12713 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc) 12714 { 12715 struct nk_font_baker *baker; 12716 if (!memory) return 0; 12717 /* setup baker inside a memory block */ 12718 baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align); 12719 baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align); 12720 baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align); 12721 baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align); 12722 baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align); 12723 baker->alloc = *alloc; 12724 return baker; 12725 } 12726 NK_INTERN int 12727 nk_font_bake_pack(struct nk_font_baker *baker, 12728 nk_size *image_memory, int *width, int *height, struct nk_recti *custom, 12729 const struct nk_font_config *config_list, int count, 12730 struct nk_allocator *alloc) 12731 { 12732 NK_STORAGE const nk_size max_height = 1024 * 32; 12733 const struct nk_font_config *config_iter, *it; 12734 int total_glyph_count = 0; 12735 int total_range_count = 0; 12736 int range_count = 0; 12737 int i = 0; 12738 12739 NK_ASSERT(image_memory); 12740 NK_ASSERT(width); 12741 NK_ASSERT(height); 12742 NK_ASSERT(config_list); 12743 NK_ASSERT(count); 12744 NK_ASSERT(alloc); 12745 12746 if (!image_memory || !width || !height || !config_list || !count) return nk_false; 12747 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 12748 it = config_iter; 12749 do {range_count = nk_range_count(it->range); 12750 total_range_count += range_count; 12751 total_glyph_count += nk_range_glyph_count(it->range, range_count); 12752 } while ((it = it->n) != config_iter); 12753 } 12754 /* setup font baker from temporary memory */ 12755 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 12756 it = config_iter; 12757 do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0)) 12758 return nk_false; 12759 } while ((it = it->n) != config_iter); 12760 } 12761 *height = 0; 12762 *width = (total_glyph_count > 1000) ? 1024 : 512; 12763 nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc); 12764 { 12765 int input_i = 0; 12766 int range_n = 0; 12767 int rect_n = 0; 12768 int char_n = 0; 12769 12770 if (custom) { 12771 /* pack custom user data first so it will be in the upper left corner*/ 12772 struct nk_rp_rect custom_space; 12773 nk_zero(&custom_space, sizeof(custom_space)); 12774 custom_space.w = (nk_rp_coord)(custom->w); 12775 custom_space.h = (nk_rp_coord)(custom->h); 12776 12777 nk_tt_PackSetOversampling(&baker->spc, 1, 1); 12778 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1); 12779 *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h)); 12780 12781 custom->x = (short)custom_space.x; 12782 custom->y = (short)custom_space.y; 12783 custom->w = (short)custom_space.w; 12784 custom->h = (short)custom_space.h; 12785 } 12786 12787 /* first font pass: pack all glyphs */ 12788 for (input_i = 0, config_iter = config_list; input_i < count && config_iter; 12789 config_iter = config_iter->next) { 12790 it = config_iter; 12791 do {int n = 0; 12792 int glyph_count; 12793 const nk_rune *in_range; 12794 const struct nk_font_config *cfg = it; 12795 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12796 12797 /* count glyphs + ranges in current font */ 12798 glyph_count = 0; range_count = 0; 12799 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) { 12800 glyph_count += (int)(in_range[1] - in_range[0]) + 1; 12801 range_count++; 12802 } 12803 12804 /* setup ranges */ 12805 tmp->ranges = baker->ranges + range_n; 12806 tmp->range_count = (nk_rune)range_count; 12807 range_n += range_count; 12808 for (i = 0; i < range_count; ++i) { 12809 in_range = &cfg->range[i * 2]; 12810 tmp->ranges[i].font_size = cfg->size; 12811 tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0]; 12812 tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1; 12813 tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n; 12814 char_n += tmp->ranges[i].num_chars; 12815 } 12816 12817 /* pack */ 12818 tmp->rects = baker->rects + rect_n; 12819 rect_n += glyph_count; 12820 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 12821 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info, 12822 tmp->ranges, (int)tmp->range_count, tmp->rects); 12823 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n); 12824 12825 /* texture height */ 12826 for (i = 0; i < n; ++i) { 12827 if (tmp->rects[i].was_packed) 12828 *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h); 12829 } 12830 } while ((it = it->n) != config_iter); 12831 } 12832 NK_ASSERT(rect_n == total_glyph_count); 12833 NK_ASSERT(char_n == total_glyph_count); 12834 NK_ASSERT(range_n == total_range_count); 12835 } 12836 *height = (int)nk_round_up_pow2((nk_uint)*height); 12837 *image_memory = (nk_size)(*width) * (nk_size)(*height); 12838 return nk_true; 12839 } 12840 NK_INTERN void 12841 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height, 12842 struct nk_font_glyph *glyphs, int glyphs_count, 12843 const struct nk_font_config *config_list, int font_count) 12844 { 12845 int input_i = 0; 12846 nk_rune glyph_n = 0; 12847 const struct nk_font_config *config_iter; 12848 const struct nk_font_config *it; 12849 12850 NK_ASSERT(image_memory); 12851 NK_ASSERT(width); 12852 NK_ASSERT(height); 12853 NK_ASSERT(config_list); 12854 NK_ASSERT(baker); 12855 NK_ASSERT(font_count); 12856 NK_ASSERT(glyphs_count); 12857 if (!image_memory || !width || !height || !config_list || 12858 !font_count || !glyphs || !glyphs_count) 12859 return; 12860 12861 /* second font pass: render glyphs */ 12862 nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height)); 12863 baker->spc.pixels = (unsigned char*)image_memory; 12864 baker->spc.height = (int)height; 12865 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 12866 config_iter = config_iter->next) { 12867 it = config_iter; 12868 do {const struct nk_font_config *cfg = it; 12869 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12870 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 12871 nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, 12872 (int)tmp->range_count, tmp->rects, &baker->alloc); 12873 } while ((it = it->n) != config_iter); 12874 } nk_tt_PackEnd(&baker->spc, &baker->alloc); 12875 12876 /* third pass: setup font and glyphs */ 12877 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 12878 config_iter = config_iter->next) { 12879 it = config_iter; 12880 do {nk_size i = 0; 12881 int char_idx = 0; 12882 nk_rune glyph_count = 0; 12883 const struct nk_font_config *cfg = it; 12884 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12885 struct nk_baked_font *dst_font = cfg->font; 12886 12887 float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size); 12888 int unscaled_ascent, unscaled_descent, unscaled_line_gap; 12889 nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent, 12890 &unscaled_line_gap); 12891 12892 /* fill baked font */ 12893 if (!cfg->merge_mode) { 12894 dst_font->ranges = cfg->range; 12895 dst_font->height = cfg->size; 12896 dst_font->ascent = ((float)unscaled_ascent * font_scale); 12897 dst_font->descent = ((float)unscaled_descent * font_scale); 12898 dst_font->glyph_offset = glyph_n; 12899 // Need to zero this, or it will carry over from a previous 12900 // bake, and cause a segfault when accessing glyphs[]. 12901 dst_font->glyph_count = 0; 12902 } 12903 12904 /* fill own baked font glyph array */ 12905 for (i = 0; i < tmp->range_count; ++i) { 12906 struct nk_tt_pack_range *range = &tmp->ranges[i]; 12907 for (char_idx = 0; char_idx < range->num_chars; char_idx++) 12908 { 12909 nk_rune codepoint = 0; 12910 float dummy_x = 0, dummy_y = 0; 12911 struct nk_tt_aligned_quad q; 12912 struct nk_font_glyph *glyph; 12913 12914 /* query glyph bounds from stb_truetype */ 12915 const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx]; 12916 if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue; 12917 codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx); 12918 nk_tt_GetPackedQuad(range->chardata_for_range, (int)width, 12919 (int)height, char_idx, &dummy_x, &dummy_y, &q, 0); 12920 12921 /* fill own glyph type with data */ 12922 glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count]; 12923 glyph->codepoint = codepoint; 12924 glyph->x0 = q.x0; glyph->y0 = q.y0; 12925 glyph->x1 = q.x1; glyph->y1 = q.y1; 12926 glyph->y0 += (dst_font->ascent + 0.5f); 12927 glyph->y1 += (dst_font->ascent + 0.5f); 12928 glyph->w = glyph->x1 - glyph->x0 + 0.5f; 12929 glyph->h = glyph->y1 - glyph->y0; 12930 12931 if (cfg->coord_type == NK_COORD_PIXEL) { 12932 glyph->u0 = q.s0 * (float)width; 12933 glyph->v0 = q.t0 * (float)height; 12934 glyph->u1 = q.s1 * (float)width; 12935 glyph->v1 = q.t1 * (float)height; 12936 } else { 12937 glyph->u0 = q.s0; 12938 glyph->v0 = q.t0; 12939 glyph->u1 = q.s1; 12940 glyph->v1 = q.t1; 12941 } 12942 glyph->xadvance = (pc->xadvance + cfg->spacing.x); 12943 if (cfg->pixel_snap) 12944 glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f); 12945 glyph_count++; 12946 } 12947 } 12948 dst_font->glyph_count += glyph_count; 12949 glyph_n += glyph_count; 12950 } while ((it = it->n) != config_iter); 12951 } 12952 } 12953 NK_INTERN void 12954 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height, 12955 struct nk_recti img_dst, const char *texture_data_mask, int tex_width, 12956 int tex_height, char white, char black) 12957 { 12958 nk_byte *pixels; 12959 int y = 0; 12960 int x = 0; 12961 int n = 0; 12962 12963 NK_ASSERT(img_memory); 12964 NK_ASSERT(img_width); 12965 NK_ASSERT(img_height); 12966 NK_ASSERT(texture_data_mask); 12967 NK_UNUSED(tex_height); 12968 if (!img_memory || !img_width || !img_height || !texture_data_mask) 12969 return; 12970 12971 pixels = (nk_byte*)img_memory; 12972 for (y = 0, n = 0; y < tex_height; ++y) { 12973 for (x = 0; x < tex_width; ++x, ++n) { 12974 const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width); 12975 const int off1 = off0 + 1 + tex_width; 12976 pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00; 12977 pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00; 12978 } 12979 } 12980 } 12981 NK_INTERN void 12982 nk_font_bake_convert(void *out_memory, int img_width, int img_height, 12983 const void *in_memory) 12984 { 12985 int n = 0; 12986 nk_rune *dst; 12987 const nk_byte *src; 12988 12989 NK_ASSERT(out_memory); 12990 NK_ASSERT(in_memory); 12991 NK_ASSERT(img_width); 12992 NK_ASSERT(img_height); 12993 if (!out_memory || !in_memory || !img_height || !img_width) return; 12994 12995 dst = (nk_rune*)out_memory; 12996 src = (const nk_byte*)in_memory; 12997 for (n = (int)(img_width * img_height); n > 0; n--) 12998 *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF; 12999 } 13000 13001 /* ------------------------------------------------------------- 13002 * 13003 * FONT 13004 * 13005 * --------------------------------------------------------------*/ 13006 NK_INTERN float 13007 nk_font_text_width(nk_handle handle, float height, const char *text, int len) 13008 { 13009 nk_rune unicode; 13010 int text_len = 0; 13011 float text_width = 0; 13012 int glyph_len = 0; 13013 float scale = 0; 13014 13015 struct nk_font *font = (struct nk_font*)handle.ptr; 13016 NK_ASSERT(font); 13017 NK_ASSERT(font->glyphs); 13018 if (!font || !text || !len) 13019 return 0; 13020 13021 scale = height/font->info.height; 13022 glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len); 13023 if (!glyph_len) return 0; 13024 while (text_len <= (int)len && glyph_len) { 13025 const struct nk_font_glyph *g; 13026 if (unicode == NK_UTF_INVALID) break; 13027 13028 /* query currently drawn glyph information */ 13029 g = nk_font_find_glyph(font, unicode); 13030 text_width += g->xadvance * scale; 13031 13032 /* offset next glyph */ 13033 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len); 13034 text_len += glyph_len; 13035 } 13036 return text_width; 13037 } 13038 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13039 NK_INTERN void 13040 nk_font_query_font_glyph(nk_handle handle, float height, 13041 struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 13042 { 13043 float scale; 13044 const struct nk_font_glyph *g; 13045 struct nk_font *font; 13046 13047 NK_ASSERT(glyph); 13048 NK_UNUSED(next_codepoint); 13049 13050 font = (struct nk_font*)handle.ptr; 13051 NK_ASSERT(font); 13052 NK_ASSERT(font->glyphs); 13053 if (!font || !glyph) 13054 return; 13055 13056 scale = height/font->info.height; 13057 g = nk_font_find_glyph(font, codepoint); 13058 glyph->width = (g->x1 - g->x0) * scale; 13059 glyph->height = (g->y1 - g->y0) * scale; 13060 glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); 13061 glyph->xadvance = (g->xadvance * scale); 13062 glyph->uv[0] = nk_vec2(g->u0, g->v0); 13063 glyph->uv[1] = nk_vec2(g->u1, g->v1); 13064 } 13065 #endif 13066 NK_API const struct nk_font_glyph* 13067 nk_font_find_glyph(struct nk_font *font, nk_rune unicode) 13068 { 13069 int i = 0; 13070 int count; 13071 int total_glyphs = 0; 13072 const struct nk_font_glyph *glyph = 0; 13073 const struct nk_font_config *iter = 0; 13074 13075 NK_ASSERT(font); 13076 NK_ASSERT(font->glyphs); 13077 NK_ASSERT(font->info.ranges); 13078 if (!font || !font->glyphs) return 0; 13079 13080 glyph = font->fallback; 13081 iter = font->config; 13082 do {count = nk_range_count(iter->range); 13083 for (i = 0; i < count; ++i) { 13084 nk_rune f = iter->range[(i*2)+0]; 13085 nk_rune t = iter->range[(i*2)+1]; 13086 int diff = (int)((t - f) + 1); 13087 if (unicode >= f && unicode <= t) 13088 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))]; 13089 total_glyphs += diff; 13090 } 13091 } while ((iter = iter->n) != font->config); 13092 return glyph; 13093 } 13094 NK_INTERN void 13095 nk_font_init(struct nk_font *font, float pixel_height, 13096 nk_rune fallback_codepoint, struct nk_font_glyph *glyphs, 13097 const struct nk_baked_font *baked_font, nk_handle atlas) 13098 { 13099 struct nk_baked_font baked; 13100 NK_ASSERT(font); 13101 NK_ASSERT(glyphs); 13102 NK_ASSERT(baked_font); 13103 if (!font || !glyphs || !baked_font) 13104 return; 13105 13106 baked = *baked_font; 13107 font->fallback = 0; 13108 font->info = baked; 13109 font->scale = (float)pixel_height / (float)font->info.height; 13110 font->glyphs = &glyphs[baked_font->glyph_offset]; 13111 font->texture = atlas; 13112 font->fallback_codepoint = fallback_codepoint; 13113 font->fallback = nk_font_find_glyph(font, fallback_codepoint); 13114 13115 font->handle.height = font->info.height * font->scale; 13116 font->handle.width = nk_font_text_width; 13117 font->handle.userdata.ptr = font; 13118 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13119 font->handle.query = nk_font_query_font_glyph; 13120 font->handle.texture = font->texture; 13121 #endif 13122 } 13123 13124 /* --------------------------------------------------------------------------- 13125 * 13126 * DEFAULT FONT 13127 * 13128 * ProggyClean.ttf 13129 * Copyright (c) 2004, 2005 Tristan Grimmer 13130 * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) 13131 * Download and more information at http://upperbounds.net 13132 *-----------------------------------------------------------------------------*/ 13133 #ifdef __clang__ 13134 #pragma clang diagnostic push 13135 #pragma clang diagnostic ignored "-Woverlength-strings" 13136 #elif defined(__GNUC__) || defined(__GNUG__) 13137 #pragma GCC diagnostic push 13138 #pragma GCC diagnostic ignored "-Woverlength-strings" 13139 #endif 13140 13141 #ifdef NK_INCLUDE_DEFAULT_FONT 13142 13143 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] = 13144 "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" 13145 "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#" 13146 "`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" 13147 "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" 13148 "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" 13149 "*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)" 13150 "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" 13151 "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." 13152 "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" 13153 "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(,)" 13154 "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#" 13155 "'/###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" 13156 "_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" 13157 "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/" 13158 "/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" 13159 "%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&#" 13160 "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)(" 13161 "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" 13162 "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" 13163 "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^-" 13164 "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-" 13165 "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" 13166 "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%" 13167 "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]" 13168 "%(?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" 13169 "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:" 13170 "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(" 13171 "$/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<" 13172 "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'?" 13173 "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/;" 13174 ")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" 13175 "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(" 13176 "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" 13177 "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" 13178 "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<-" 13179 "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" 13180 "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" 13181 ".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@@" 13182 "$&)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*" 13183 "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" 13184 "@-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&#" 13185 "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#" 13186 "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" 13187 "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" 13188 "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&#" 13189 "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" 13190 ":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+" 13191 "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*" 13192 "$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" 13193 ":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" 13194 "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" 13195 "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" 13196 "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" 13197 ":^#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@&]>" 13198 "_>@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%" 13199 "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;" 13200 "^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:" 13201 "+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%" 13202 "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-" 13203 "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*" 13204 "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" 13205 "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-" 13206 "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`" 13207 "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]%/" 13208 "+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" 13209 "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" 13210 "?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" 13211 "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" 13212 ">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'>" 13213 "[%$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" 13214 "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#" 13215 "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$" 13216 "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,)" 13217 "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" 13218 "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" 13219 "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" 13220 "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(#" 13221 ";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&>" 13222 "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#" 13223 "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" 13224 "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#" 13225 "/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-#" 13226 "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#" 13227 "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" 13228 "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" 13229 "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; 13230 13231 #endif /* NK_INCLUDE_DEFAULT_FONT */ 13232 13233 #define NK_CURSOR_DATA_W 90 13234 #define NK_CURSOR_DATA_H 27 13235 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] = 13236 { 13237 "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" 13238 "..- -X.....X- X.X - X.X -X.....X - X.....X" 13239 "--- -XXX.XXX- X...X - X...X -X....X - X....X" 13240 "X - X.X - X.....X - X.....X -X...X - X...X" 13241 "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" 13242 "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" 13243 "X..X - X.X - X.X - X.X -XX X.X - X.X XX" 13244 "X...X - X.X - X.X - XX X.X XX - X.X - X.X " 13245 "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " 13246 "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " 13247 "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " 13248 "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " 13249 "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " 13250 "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " 13251 "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " 13252 "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " 13253 "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " 13254 "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" 13255 "X.X X..X - -X.......X- X.......X - XX XX - " 13256 "XX X..X - - X.....X - X.....X - X.X X.X - " 13257 " X..X - X...X - X...X - X..X X..X - " 13258 " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " 13259 "------------ - X - X -X.....................X- " 13260 " ----------------------------------- X...XXXXXXXXXXXXX...X - " 13261 " - X..X X..X - " 13262 " - X.X X.X - " 13263 " - XX XX - " 13264 }; 13265 13266 #ifdef __clang__ 13267 #pragma clang diagnostic pop 13268 #elif defined(__GNUC__) || defined(__GNUG__) 13269 #pragma GCC diagnostic pop 13270 #endif 13271 13272 NK_GLOBAL unsigned char *nk__barrier; 13273 NK_GLOBAL unsigned char *nk__barrier2; 13274 NK_GLOBAL unsigned char *nk__barrier3; 13275 NK_GLOBAL unsigned char *nk__barrier4; 13276 NK_GLOBAL unsigned char *nk__dout; 13277 13278 NK_INTERN unsigned int 13279 nk_decompress_length(unsigned char *input) 13280 { 13281 return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]); 13282 } 13283 NK_INTERN void 13284 nk__match(unsigned char *data, unsigned int length) 13285 { 13286 /* INVERSE of memmove... write each byte before copying the next...*/ 13287 NK_ASSERT (nk__dout + length <= nk__barrier); 13288 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 13289 if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; } 13290 while (length--) *nk__dout++ = *data++; 13291 } 13292 NK_INTERN void 13293 nk__lit(unsigned char *data, unsigned int length) 13294 { 13295 NK_ASSERT (nk__dout + length <= nk__barrier); 13296 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 13297 if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; } 13298 NK_MEMCPY(nk__dout, data, length); 13299 nk__dout += length; 13300 } 13301 NK_INTERN unsigned char* 13302 nk_decompress_token(unsigned char *i) 13303 { 13304 #define nk__in2(x) ((i[x] << 8) + i[(x)+1]) 13305 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1)) 13306 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1)) 13307 13308 if (*i >= 0x20) { /* use fewer if's for cases that expand small */ 13309 if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2; 13310 else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3; 13311 else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); 13312 } else { /* more ifs for cases that expand large, since overhead is amortized */ 13313 if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4; 13314 else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5; 13315 else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1); 13316 else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1); 13317 else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5; 13318 else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6; 13319 } 13320 return i; 13321 } 13322 NK_INTERN unsigned int 13323 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) 13324 { 13325 const unsigned long ADLER_MOD = 65521; 13326 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; 13327 unsigned long blocklen, i; 13328 13329 blocklen = buflen % 5552; 13330 while (buflen) { 13331 for (i=0; i + 7 < blocklen; i += 8) { 13332 s1 += buffer[0]; s2 += s1; 13333 s1 += buffer[1]; s2 += s1; 13334 s1 += buffer[2]; s2 += s1; 13335 s1 += buffer[3]; s2 += s1; 13336 s1 += buffer[4]; s2 += s1; 13337 s1 += buffer[5]; s2 += s1; 13338 s1 += buffer[6]; s2 += s1; 13339 s1 += buffer[7]; s2 += s1; 13340 buffer += 8; 13341 } 13342 for (; i < blocklen; ++i) { 13343 s1 += *buffer++; s2 += s1; 13344 } 13345 13346 s1 %= ADLER_MOD; s2 %= ADLER_MOD; 13347 buflen -= (unsigned int)blocklen; 13348 blocklen = 5552; 13349 } 13350 return (unsigned int)(s2 << 16) + (unsigned int)s1; 13351 } 13352 NK_INTERN unsigned int 13353 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length) 13354 { 13355 unsigned int olen; 13356 if (nk__in4(0) != 0x57bC0000) return 0; 13357 if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */ 13358 olen = nk_decompress_length(i); 13359 nk__barrier2 = i; 13360 nk__barrier3 = i+length; 13361 nk__barrier = output + olen; 13362 nk__barrier4 = output; 13363 i += 16; 13364 13365 nk__dout = output; 13366 for (;;) { 13367 unsigned char *old_i = i; 13368 i = nk_decompress_token(i); 13369 if (i == old_i) { 13370 if (*i == 0x05 && i[1] == 0xfa) { 13371 NK_ASSERT(nk__dout == output + olen); 13372 if (nk__dout != output + olen) return 0; 13373 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2)) 13374 return 0; 13375 return olen; 13376 } else { 13377 NK_ASSERT(0); /* NOTREACHED */ 13378 return 0; 13379 } 13380 } 13381 NK_ASSERT(nk__dout <= output + olen); 13382 if (nk__dout > output + olen) 13383 return 0; 13384 } 13385 } 13386 NK_INTERN unsigned int 13387 nk_decode_85_byte(char c) 13388 { 13389 return (unsigned int)((c >= '\\') ? c-36 : c-35); 13390 } 13391 NK_INTERN void 13392 nk_decode_85(unsigned char* dst, const unsigned char* src) 13393 { 13394 while (*src) 13395 { 13396 unsigned int tmp = 13397 nk_decode_85_byte((char)src[0]) + 13398 85 * (nk_decode_85_byte((char)src[1]) + 13399 85 * (nk_decode_85_byte((char)src[2]) + 13400 85 * (nk_decode_85_byte((char)src[3]) + 13401 85 * nk_decode_85_byte((char)src[4])))); 13402 13403 /* we can't assume little-endianess. */ 13404 dst[0] = (unsigned char)((tmp >> 0) & 0xFF); 13405 dst[1] = (unsigned char)((tmp >> 8) & 0xFF); 13406 dst[2] = (unsigned char)((tmp >> 16) & 0xFF); 13407 dst[3] = (unsigned char)((tmp >> 24) & 0xFF); 13408 13409 src += 5; 13410 dst += 4; 13411 } 13412 } 13413 13414 /* ------------------------------------------------------------- 13415 * 13416 * FONT ATLAS 13417 * 13418 * --------------------------------------------------------------*/ 13419 NK_API struct nk_font_config 13420 nk_font_config(float pixel_height) 13421 { 13422 struct nk_font_config cfg; 13423 nk_zero_struct(cfg); 13424 cfg.ttf_blob = 0; 13425 cfg.ttf_size = 0; 13426 cfg.ttf_data_owned_by_atlas = 0; 13427 cfg.size = pixel_height; 13428 cfg.oversample_h = 3; 13429 cfg.oversample_v = 1; 13430 cfg.pixel_snap = 0; 13431 cfg.coord_type = NK_COORD_UV; 13432 cfg.spacing = nk_vec2(0,0); 13433 cfg.range = nk_font_default_glyph_ranges(); 13434 cfg.merge_mode = 0; 13435 cfg.fallback_glyph = '?'; 13436 cfg.font = 0; 13437 cfg.n = 0; 13438 return cfg; 13439 } 13440 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 13441 NK_API void 13442 nk_font_atlas_init_default(struct nk_font_atlas *atlas) 13443 { 13444 NK_ASSERT(atlas); 13445 if (!atlas) return; 13446 nk_zero_struct(*atlas); 13447 atlas->temporary.userdata.ptr = 0; 13448 atlas->temporary.alloc = nk_malloc; 13449 atlas->temporary.free = nk_mfree; 13450 atlas->permanent.userdata.ptr = 0; 13451 atlas->permanent.alloc = nk_malloc; 13452 atlas->permanent.free = nk_mfree; 13453 } 13454 #endif 13455 NK_API void 13456 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc) 13457 { 13458 NK_ASSERT(atlas); 13459 NK_ASSERT(alloc); 13460 if (!atlas || !alloc) return; 13461 nk_zero_struct(*atlas); 13462 atlas->permanent = *alloc; 13463 atlas->temporary = *alloc; 13464 } 13465 NK_API void 13466 nk_font_atlas_init_custom(struct nk_font_atlas *atlas, 13467 struct nk_allocator *permanent, struct nk_allocator *temporary) 13468 { 13469 NK_ASSERT(atlas); 13470 NK_ASSERT(permanent); 13471 NK_ASSERT(temporary); 13472 if (!atlas || !permanent || !temporary) return; 13473 nk_zero_struct(*atlas); 13474 atlas->permanent = *permanent; 13475 atlas->temporary = *temporary; 13476 } 13477 NK_API void 13478 nk_font_atlas_begin(struct nk_font_atlas *atlas) 13479 { 13480 NK_ASSERT(atlas); 13481 NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free); 13482 NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free); 13483 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free || 13484 !atlas->temporary.alloc || !atlas->temporary.free) return; 13485 if (atlas->glyphs) { 13486 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13487 atlas->glyphs = 0; 13488 } 13489 if (atlas->pixel) { 13490 atlas->permanent.free(atlas->permanent.userdata, atlas->pixel); 13491 atlas->pixel = 0; 13492 } 13493 } 13494 NK_API struct nk_font* 13495 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config) 13496 { 13497 struct nk_font *font = 0; 13498 struct nk_font_config *cfg; 13499 13500 NK_ASSERT(atlas); 13501 NK_ASSERT(atlas->permanent.alloc); 13502 NK_ASSERT(atlas->permanent.free); 13503 NK_ASSERT(atlas->temporary.alloc); 13504 NK_ASSERT(atlas->temporary.free); 13505 13506 NK_ASSERT(config); 13507 NK_ASSERT(config->ttf_blob); 13508 NK_ASSERT(config->ttf_size); 13509 NK_ASSERT(config->size > 0.0f); 13510 13511 if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f|| 13512 !atlas->permanent.alloc || !atlas->permanent.free || 13513 !atlas->temporary.alloc || !atlas->temporary.free) 13514 return 0; 13515 13516 /* allocate font config */ 13517 cfg = (struct nk_font_config*) 13518 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config)); 13519 NK_MEMCPY(cfg, config, sizeof(*config)); 13520 cfg->n = cfg; 13521 cfg->p = cfg; 13522 13523 if (!config->merge_mode) { 13524 /* insert font config into list */ 13525 if (!atlas->config) { 13526 atlas->config = cfg; 13527 cfg->next = 0; 13528 } else { 13529 struct nk_font_config *i = atlas->config; 13530 while (i->next) i = i->next; 13531 i->next = cfg; 13532 cfg->next = 0; 13533 } 13534 /* allocate new font */ 13535 font = (struct nk_font*) 13536 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font)); 13537 NK_ASSERT(font); 13538 nk_zero(font, sizeof(*font)); 13539 if (!font) return 0; 13540 font->config = cfg; 13541 13542 /* insert font into list */ 13543 if (!atlas->fonts) { 13544 atlas->fonts = font; 13545 font->next = 0; 13546 } else { 13547 struct nk_font *i = atlas->fonts; 13548 while (i->next) i = i->next; 13549 i->next = font; 13550 font->next = 0; 13551 } 13552 cfg->font = &font->info; 13553 } else { 13554 /* extend previously added font */ 13555 struct nk_font *f = 0; 13556 struct nk_font_config *c = 0; 13557 NK_ASSERT(atlas->font_num); 13558 f = atlas->fonts; 13559 c = f->config; 13560 cfg->font = &f->info; 13561 13562 cfg->n = c; 13563 cfg->p = c->p; 13564 c->p->n = cfg; 13565 c->p = cfg; 13566 } 13567 /* create own copy of .TTF font blob */ 13568 if (!config->ttf_data_owned_by_atlas) { 13569 cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size); 13570 NK_ASSERT(cfg->ttf_blob); 13571 if (!cfg->ttf_blob) { 13572 atlas->font_num++; 13573 return 0; 13574 } 13575 NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size); 13576 cfg->ttf_data_owned_by_atlas = 1; 13577 } 13578 atlas->font_num++; 13579 return font; 13580 } 13581 NK_API struct nk_font* 13582 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, 13583 nk_size size, float height, const struct nk_font_config *config) 13584 { 13585 struct nk_font_config cfg; 13586 NK_ASSERT(memory); 13587 NK_ASSERT(size); 13588 13589 NK_ASSERT(atlas); 13590 NK_ASSERT(atlas->temporary.alloc); 13591 NK_ASSERT(atlas->temporary.free); 13592 NK_ASSERT(atlas->permanent.alloc); 13593 NK_ASSERT(atlas->permanent.free); 13594 if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size || 13595 !atlas->permanent.alloc || !atlas->permanent.free) 13596 return 0; 13597 13598 cfg = (config) ? *config: nk_font_config(height); 13599 cfg.ttf_blob = memory; 13600 cfg.ttf_size = size; 13601 cfg.size = height; 13602 cfg.ttf_data_owned_by_atlas = 0; 13603 return nk_font_atlas_add(atlas, &cfg); 13604 } 13605 #ifdef NK_INCLUDE_STANDARD_IO 13606 NK_API struct nk_font* 13607 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, 13608 float height, const struct nk_font_config *config) 13609 { 13610 nk_size size; 13611 char *memory; 13612 struct nk_font_config cfg; 13613 13614 NK_ASSERT(atlas); 13615 NK_ASSERT(atlas->temporary.alloc); 13616 NK_ASSERT(atlas->temporary.free); 13617 NK_ASSERT(atlas->permanent.alloc); 13618 NK_ASSERT(atlas->permanent.free); 13619 13620 if (!atlas || !file_path) return 0; 13621 memory = nk_file_load(file_path, &size, &atlas->permanent); 13622 if (!memory) return 0; 13623 13624 cfg = (config) ? *config: nk_font_config(height); 13625 cfg.ttf_blob = memory; 13626 cfg.ttf_size = size; 13627 cfg.size = height; 13628 cfg.ttf_data_owned_by_atlas = 1; 13629 return nk_font_atlas_add(atlas, &cfg); 13630 } 13631 #endif 13632 NK_API struct nk_font* 13633 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas, 13634 void *compressed_data, nk_size compressed_size, float height, 13635 const struct nk_font_config *config) 13636 { 13637 unsigned int decompressed_size; 13638 void *decompressed_data; 13639 struct nk_font_config cfg; 13640 13641 NK_ASSERT(atlas); 13642 NK_ASSERT(atlas->temporary.alloc); 13643 NK_ASSERT(atlas->temporary.free); 13644 NK_ASSERT(atlas->permanent.alloc); 13645 NK_ASSERT(atlas->permanent.free); 13646 13647 NK_ASSERT(compressed_data); 13648 NK_ASSERT(compressed_size); 13649 if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free || 13650 !atlas->permanent.alloc || !atlas->permanent.free) 13651 return 0; 13652 13653 decompressed_size = nk_decompress_length((unsigned char*)compressed_data); 13654 decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size); 13655 NK_ASSERT(decompressed_data); 13656 if (!decompressed_data) return 0; 13657 nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data, 13658 (unsigned int)compressed_size); 13659 13660 cfg = (config) ? *config: nk_font_config(height); 13661 cfg.ttf_blob = decompressed_data; 13662 cfg.ttf_size = decompressed_size; 13663 cfg.size = height; 13664 cfg.ttf_data_owned_by_atlas = 1; 13665 return nk_font_atlas_add(atlas, &cfg); 13666 } 13667 NK_API struct nk_font* 13668 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas, 13669 const char *data_base85, float height, const struct nk_font_config *config) 13670 { 13671 int compressed_size; 13672 void *compressed_data; 13673 struct nk_font *font; 13674 13675 NK_ASSERT(atlas); 13676 NK_ASSERT(atlas->temporary.alloc); 13677 NK_ASSERT(atlas->temporary.free); 13678 NK_ASSERT(atlas->permanent.alloc); 13679 NK_ASSERT(atlas->permanent.free); 13680 13681 NK_ASSERT(data_base85); 13682 if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free || 13683 !atlas->permanent.alloc || !atlas->permanent.free) 13684 return 0; 13685 13686 compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4; 13687 compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size); 13688 NK_ASSERT(compressed_data); 13689 if (!compressed_data) return 0; 13690 nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85); 13691 font = nk_font_atlas_add_compressed(atlas, compressed_data, 13692 (nk_size)compressed_size, height, config); 13693 atlas->temporary.free(atlas->temporary.userdata, compressed_data); 13694 return font; 13695 } 13696 13697 #ifdef NK_INCLUDE_DEFAULT_FONT 13698 NK_API struct nk_font* 13699 nk_font_atlas_add_default(struct nk_font_atlas *atlas, 13700 float pixel_height, const struct nk_font_config *config) 13701 { 13702 NK_ASSERT(atlas); 13703 NK_ASSERT(atlas->temporary.alloc); 13704 NK_ASSERT(atlas->temporary.free); 13705 NK_ASSERT(atlas->permanent.alloc); 13706 NK_ASSERT(atlas->permanent.free); 13707 return nk_font_atlas_add_compressed_base85(atlas, 13708 nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config); 13709 } 13710 #endif 13711 NK_API const void* 13712 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height, 13713 enum nk_font_atlas_format fmt) 13714 { 13715 int i = 0; 13716 void *tmp = 0; 13717 nk_size tmp_size, img_size; 13718 struct nk_font *font_iter; 13719 struct nk_font_baker *baker; 13720 13721 NK_ASSERT(atlas); 13722 NK_ASSERT(atlas->temporary.alloc); 13723 NK_ASSERT(atlas->temporary.free); 13724 NK_ASSERT(atlas->permanent.alloc); 13725 NK_ASSERT(atlas->permanent.free); 13726 13727 NK_ASSERT(width); 13728 NK_ASSERT(height); 13729 if (!atlas || !width || !height || 13730 !atlas->temporary.alloc || !atlas->temporary.free || 13731 !atlas->permanent.alloc || !atlas->permanent.free) 13732 return 0; 13733 13734 #ifdef NK_INCLUDE_DEFAULT_FONT 13735 /* no font added so just use default font */ 13736 if (!atlas->font_num) 13737 atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0); 13738 #endif 13739 NK_ASSERT(atlas->font_num); 13740 if (!atlas->font_num) return 0; 13741 13742 /* allocate temporary baker memory required for the baking process */ 13743 nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num); 13744 tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size); 13745 NK_ASSERT(tmp); 13746 if (!tmp) goto failed; 13747 13748 /* allocate glyph memory for all fonts */ 13749 baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary); 13750 atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc( 13751 atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count); 13752 NK_ASSERT(atlas->glyphs); 13753 if (!atlas->glyphs) 13754 goto failed; 13755 13756 /* pack all glyphs into a tight fit space */ 13757 atlas->custom.w = (NK_CURSOR_DATA_W*2)+1; 13758 atlas->custom.h = NK_CURSOR_DATA_H + 1; 13759 if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom, 13760 atlas->config, atlas->font_num, &atlas->temporary)) 13761 goto failed; 13762 13763 /* allocate memory for the baked image font atlas */ 13764 atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size); 13765 NK_ASSERT(atlas->pixel); 13766 if (!atlas->pixel) 13767 goto failed; 13768 13769 /* bake glyphs and custom white pixel into image */ 13770 nk_font_bake(baker, atlas->pixel, *width, *height, 13771 atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num); 13772 nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom, 13773 nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X'); 13774 13775 if (fmt == NK_FONT_ATLAS_RGBA32) { 13776 /* convert alpha8 image into rgba32 image */ 13777 void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0, 13778 (nk_size)(*width * *height * 4)); 13779 NK_ASSERT(img_rgba); 13780 if (!img_rgba) goto failed; 13781 nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel); 13782 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13783 atlas->pixel = img_rgba; 13784 } 13785 atlas->tex_width = *width; 13786 atlas->tex_height = *height; 13787 13788 /* initialize each font */ 13789 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 13790 struct nk_font *font = font_iter; 13791 struct nk_font_config *config = font->config; 13792 nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs, 13793 config->font, nk_handle_ptr(0)); 13794 } 13795 13796 /* initialize each cursor */ 13797 {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = { 13798 /* Pos Size Offset */ 13799 {{ 0, 3}, {12,19}, { 0, 0}}, 13800 {{13, 0}, { 7,16}, { 4, 8}}, 13801 {{31, 0}, {23,23}, {11,11}}, 13802 {{21, 0}, { 9, 23}, { 5,11}}, 13803 {{55,18}, {23, 9}, {11, 5}}, 13804 {{73, 0}, {17,17}, { 9, 9}}, 13805 {{55, 0}, {17,17}, { 9, 9}} 13806 }; 13807 for (i = 0; i < NK_CURSOR_COUNT; ++i) { 13808 struct nk_cursor *cursor = &atlas->cursors[i]; 13809 cursor->img.w = (unsigned short)*width; 13810 cursor->img.h = (unsigned short)*height; 13811 cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x); 13812 cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y); 13813 cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x; 13814 cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y; 13815 cursor->size = nk_cursor_data[i][1]; 13816 cursor->offset = nk_cursor_data[i][2]; 13817 }} 13818 /* free temporary memory */ 13819 atlas->temporary.free(atlas->temporary.userdata, tmp); 13820 return atlas->pixel; 13821 13822 failed: 13823 /* error so cleanup all memory */ 13824 if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp); 13825 if (atlas->glyphs) { 13826 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13827 atlas->glyphs = 0; 13828 } 13829 if (atlas->pixel) { 13830 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13831 atlas->pixel = 0; 13832 } 13833 return 0; 13834 } 13835 NK_API void 13836 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, 13837 struct nk_draw_null_texture *null) 13838 { 13839 int i = 0; 13840 struct nk_font *font_iter; 13841 NK_ASSERT(atlas); 13842 if (!atlas) { 13843 if (!null) return; 13844 null->texture = texture; 13845 null->uv = nk_vec2(0.5f,0.5f); 13846 } 13847 if (null) { 13848 null->texture = texture; 13849 null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; 13850 null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; 13851 } 13852 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 13853 font_iter->texture = texture; 13854 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13855 font_iter->handle.texture = texture; 13856 #endif 13857 } 13858 for (i = 0; i < NK_CURSOR_COUNT; ++i) 13859 atlas->cursors[i].img.handle = texture; 13860 13861 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13862 atlas->pixel = 0; 13863 atlas->tex_width = 0; 13864 atlas->tex_height = 0; 13865 atlas->custom.x = 0; 13866 atlas->custom.y = 0; 13867 atlas->custom.w = 0; 13868 atlas->custom.h = 0; 13869 } 13870 NK_API void 13871 nk_font_atlas_cleanup(struct nk_font_atlas *atlas) 13872 { 13873 NK_ASSERT(atlas); 13874 NK_ASSERT(atlas->temporary.alloc); 13875 NK_ASSERT(atlas->temporary.free); 13876 NK_ASSERT(atlas->permanent.alloc); 13877 NK_ASSERT(atlas->permanent.free); 13878 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 13879 if (atlas->config) { 13880 struct nk_font_config *iter; 13881 for (iter = atlas->config; iter; iter = iter->next) { 13882 struct nk_font_config *i; 13883 for (i = iter->n; i != iter; i = i->n) { 13884 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 13885 i->ttf_blob = 0; 13886 } 13887 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 13888 iter->ttf_blob = 0; 13889 } 13890 } 13891 } 13892 NK_API void 13893 nk_font_atlas_clear(struct nk_font_atlas *atlas) 13894 { 13895 NK_ASSERT(atlas); 13896 NK_ASSERT(atlas->temporary.alloc); 13897 NK_ASSERT(atlas->temporary.free); 13898 NK_ASSERT(atlas->permanent.alloc); 13899 NK_ASSERT(atlas->permanent.free); 13900 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 13901 13902 if (atlas->config) { 13903 struct nk_font_config *iter, *next; 13904 for (iter = atlas->config; iter; iter = next) { 13905 struct nk_font_config *i, *n; 13906 for (i = iter->n; i != iter; i = n) { 13907 n = i->n; 13908 if (i->ttf_blob) 13909 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 13910 atlas->permanent.free(atlas->permanent.userdata, i); 13911 } 13912 next = iter->next; 13913 if (i->ttf_blob) 13914 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 13915 atlas->permanent.free(atlas->permanent.userdata, iter); 13916 } 13917 atlas->config = 0; 13918 } 13919 if (atlas->fonts) { 13920 struct nk_font *iter, *next; 13921 for (iter = atlas->fonts; iter; iter = next) { 13922 next = iter->next; 13923 atlas->permanent.free(atlas->permanent.userdata, iter); 13924 } 13925 atlas->fonts = 0; 13926 } 13927 if (atlas->glyphs) 13928 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13929 nk_zero_struct(*atlas); 13930 } 13931 #endif 13932 13933 13934 13935 13936 13937 /* =============================================================== 13938 * 13939 * INPUT 13940 * 13941 * ===============================================================*/ 13942 NK_API void 13943 nk_input_begin(struct nk_context *ctx) 13944 { 13945 int i; 13946 struct nk_input *in; 13947 NK_ASSERT(ctx); 13948 if (!ctx) return; 13949 in = &ctx->input; 13950 for (i = 0; i < NK_BUTTON_MAX; ++i) 13951 in->mouse.buttons[i].clicked = 0; 13952 13953 in->keyboard.text_len = 0; 13954 in->mouse.scroll_delta = nk_vec2(0,0); 13955 in->mouse.prev.x = in->mouse.pos.x; 13956 in->mouse.prev.y = in->mouse.pos.y; 13957 in->mouse.delta.x = 0; 13958 in->mouse.delta.y = 0; 13959 for (i = 0; i < NK_KEY_MAX; i++) 13960 in->keyboard.keys[i].clicked = 0; 13961 } 13962 NK_API void 13963 nk_input_end(struct nk_context *ctx) 13964 { 13965 struct nk_input *in; 13966 NK_ASSERT(ctx); 13967 if (!ctx) return; 13968 in = &ctx->input; 13969 if (in->mouse.grab) 13970 in->mouse.grab = 0; 13971 if (in->mouse.ungrab) { 13972 in->mouse.grabbed = 0; 13973 in->mouse.ungrab = 0; 13974 in->mouse.grab = 0; 13975 } 13976 } 13977 NK_API void 13978 nk_input_motion(struct nk_context *ctx, int x, int y) 13979 { 13980 struct nk_input *in; 13981 NK_ASSERT(ctx); 13982 if (!ctx) return; 13983 in = &ctx->input; 13984 in->mouse.pos.x = (float)x; 13985 in->mouse.pos.y = (float)y; 13986 in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x; 13987 in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y; 13988 } 13989 NK_API void 13990 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down) 13991 { 13992 struct nk_input *in; 13993 NK_ASSERT(ctx); 13994 if (!ctx) return; 13995 in = &ctx->input; 13996 #ifdef NK_KEYSTATE_BASED_INPUT 13997 if (in->keyboard.keys[key].down != down) 13998 in->keyboard.keys[key].clicked++; 13999 #else 14000 in->keyboard.keys[key].clicked++; 14001 #endif 14002 in->keyboard.keys[key].down = down; 14003 } 14004 NK_API void 14005 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down) 14006 { 14007 struct nk_mouse_button *btn; 14008 struct nk_input *in; 14009 NK_ASSERT(ctx); 14010 if (!ctx) return; 14011 in = &ctx->input; 14012 if (in->mouse.buttons[id].down == down) return; 14013 14014 btn = &in->mouse.buttons[id]; 14015 btn->clicked_pos.x = (float)x; 14016 btn->clicked_pos.y = (float)y; 14017 btn->down = down; 14018 btn->clicked++; 14019 } 14020 NK_API void 14021 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val) 14022 { 14023 NK_ASSERT(ctx); 14024 if (!ctx) return; 14025 ctx->input.mouse.scroll_delta.x += val.x; 14026 ctx->input.mouse.scroll_delta.y += val.y; 14027 } 14028 NK_API void 14029 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph) 14030 { 14031 int len = 0; 14032 nk_rune unicode; 14033 struct nk_input *in; 14034 14035 NK_ASSERT(ctx); 14036 if (!ctx) return; 14037 in = &ctx->input; 14038 14039 len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE); 14040 if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) { 14041 nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len], 14042 NK_INPUT_MAX - in->keyboard.text_len); 14043 in->keyboard.text_len += len; 14044 } 14045 } 14046 NK_API void 14047 nk_input_char(struct nk_context *ctx, char c) 14048 { 14049 nk_glyph glyph; 14050 NK_ASSERT(ctx); 14051 if (!ctx) return; 14052 glyph[0] = c; 14053 nk_input_glyph(ctx, glyph); 14054 } 14055 NK_API void 14056 nk_input_unicode(struct nk_context *ctx, nk_rune unicode) 14057 { 14058 nk_glyph rune; 14059 NK_ASSERT(ctx); 14060 if (!ctx) return; 14061 nk_utf_encode(unicode, rune, NK_UTF_SIZE); 14062 nk_input_glyph(ctx, rune); 14063 } 14064 NK_API int 14065 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id) 14066 { 14067 const struct nk_mouse_button *btn; 14068 if (!i) return nk_false; 14069 btn = &i->mouse.buttons[id]; 14070 return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false; 14071 } 14072 NK_API int 14073 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 14074 struct nk_rect b) 14075 { 14076 const struct nk_mouse_button *btn; 14077 if (!i) return nk_false; 14078 btn = &i->mouse.buttons[id]; 14079 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) 14080 return nk_false; 14081 return nk_true; 14082 } 14083 NK_API int 14084 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 14085 struct nk_rect b, int down) 14086 { 14087 const struct nk_mouse_button *btn; 14088 if (!i) return nk_false; 14089 btn = &i->mouse.buttons[id]; 14090 return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down); 14091 } 14092 NK_API int 14093 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 14094 struct nk_rect b) 14095 { 14096 const struct nk_mouse_button *btn; 14097 if (!i) return nk_false; 14098 btn = &i->mouse.buttons[id]; 14099 return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) && 14100 btn->clicked) ? nk_true : nk_false; 14101 } 14102 NK_API int 14103 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 14104 struct nk_rect b, int down) 14105 { 14106 const struct nk_mouse_button *btn; 14107 if (!i) return nk_false; 14108 btn = &i->mouse.buttons[id]; 14109 return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) && 14110 btn->clicked) ? nk_true : nk_false; 14111 } 14112 NK_API int 14113 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b) 14114 { 14115 int i, down = 0; 14116 for (i = 0; i < NK_BUTTON_MAX; ++i) 14117 down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b); 14118 return down; 14119 } 14120 NK_API int 14121 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect) 14122 { 14123 if (!i) return nk_false; 14124 return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h); 14125 } 14126 NK_API int 14127 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect) 14128 { 14129 if (!i) return nk_false; 14130 return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h); 14131 } 14132 NK_API int 14133 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect) 14134 { 14135 if (!i) return nk_false; 14136 if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false; 14137 return nk_input_is_mouse_click_in_rect(i, id, rect); 14138 } 14139 NK_API int 14140 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id) 14141 { 14142 if (!i) return nk_false; 14143 return i->mouse.buttons[id].down; 14144 } 14145 NK_API int 14146 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id) 14147 { 14148 const struct nk_mouse_button *b; 14149 if (!i) return nk_false; 14150 b = &i->mouse.buttons[id]; 14151 if (b->down && b->clicked) 14152 return nk_true; 14153 return nk_false; 14154 } 14155 NK_API int 14156 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id) 14157 { 14158 if (!i) return nk_false; 14159 return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked); 14160 } 14161 NK_API int 14162 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key) 14163 { 14164 const struct nk_key *k; 14165 if (!i) return nk_false; 14166 k = &i->keyboard.keys[key]; 14167 if ((k->down && k->clicked) || (!k->down && k->clicked >= 2)) 14168 return nk_true; 14169 return nk_false; 14170 } 14171 NK_API int 14172 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key) 14173 { 14174 const struct nk_key *k; 14175 if (!i) return nk_false; 14176 k = &i->keyboard.keys[key]; 14177 if ((!k->down && k->clicked) || (k->down && k->clicked >= 2)) 14178 return nk_true; 14179 return nk_false; 14180 } 14181 NK_API int 14182 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key) 14183 { 14184 const struct nk_key *k; 14185 if (!i) return nk_false; 14186 k = &i->keyboard.keys[key]; 14187 if (k->down) return nk_true; 14188 return nk_false; 14189 } 14190 14191 14192 14193 14194 14195 /* =============================================================== 14196 * 14197 * STYLE 14198 * 14199 * ===============================================================*/ 14200 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);} 14201 #define NK_COLOR_MAP(NK_COLOR)\ 14202 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \ 14203 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \ 14204 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \ 14205 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \ 14206 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \ 14207 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \ 14208 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \ 14209 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \ 14210 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ 14211 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ 14212 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ 14213 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ 14214 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ 14215 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ 14216 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ 14217 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ 14218 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ 14219 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ 14220 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ 14221 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ 14222 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ 14223 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \ 14224 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \ 14225 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \ 14226 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ 14227 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \ 14228 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \ 14229 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) 14230 14231 NK_GLOBAL const struct nk_color 14232 nk_default_color_style[NK_COLOR_COUNT] = { 14233 #define NK_COLOR(a,b,c,d,e) {b,c,d,e}, 14234 NK_COLOR_MAP(NK_COLOR) 14235 #undef NK_COLOR 14236 }; 14237 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = { 14238 #define NK_COLOR(a,b,c,d,e) #a, 14239 NK_COLOR_MAP(NK_COLOR) 14240 #undef NK_COLOR 14241 }; 14242 14243 NK_API const char* 14244 nk_style_get_color_by_name(enum nk_style_colors c) 14245 { 14246 return nk_color_names[c]; 14247 } 14248 NK_API struct nk_style_item 14249 nk_style_item_image(struct nk_image img) 14250 { 14251 struct nk_style_item i; 14252 i.type = NK_STYLE_ITEM_IMAGE; 14253 i.data.image = img; 14254 return i; 14255 } 14256 NK_API struct nk_style_item 14257 nk_style_item_color(struct nk_color col) 14258 { 14259 struct nk_style_item i; 14260 i.type = NK_STYLE_ITEM_COLOR; 14261 i.data.color = col; 14262 return i; 14263 } 14264 NK_API struct nk_style_item 14265 nk_style_item_hide(void) 14266 { 14267 struct nk_style_item i; 14268 i.type = NK_STYLE_ITEM_COLOR; 14269 i.data.color = nk_rgba(0,0,0,0); 14270 return i; 14271 } 14272 NK_API void 14273 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) 14274 { 14275 struct nk_style *style; 14276 struct nk_style_text *text; 14277 struct nk_style_button *button; 14278 struct nk_style_toggle *toggle; 14279 struct nk_style_selectable *select; 14280 struct nk_style_slider *slider; 14281 struct nk_style_progress *prog; 14282 struct nk_style_scrollbar *scroll; 14283 struct nk_style_edit *edit; 14284 struct nk_style_property *property; 14285 struct nk_style_combo *combo; 14286 struct nk_style_chart *chart; 14287 struct nk_style_tab *tab; 14288 struct nk_style_window *win; 14289 14290 NK_ASSERT(ctx); 14291 if (!ctx) return; 14292 style = &ctx->style; 14293 table = (!table) ? nk_default_color_style: table; 14294 14295 /* default text */ 14296 text = &style->text; 14297 text->color = table[NK_COLOR_TEXT]; 14298 text->padding = nk_vec2(0,0); 14299 14300 /* default button */ 14301 button = &style->button; 14302 nk_zero_struct(*button); 14303 button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]); 14304 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 14305 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 14306 button->border_color = table[NK_COLOR_BORDER]; 14307 button->text_background = table[NK_COLOR_BUTTON]; 14308 button->text_normal = table[NK_COLOR_TEXT]; 14309 button->text_hover = table[NK_COLOR_TEXT]; 14310 button->text_active = table[NK_COLOR_TEXT]; 14311 button->padding = nk_vec2(2.0f,2.0f); 14312 button->image_padding = nk_vec2(0.0f,0.0f); 14313 button->touch_padding = nk_vec2(0.0f, 0.0f); 14314 button->userdata = nk_handle_ptr(0); 14315 button->text_alignment = NK_TEXT_CENTERED; 14316 button->border = 1.0f; 14317 button->rounding = 4.0f; 14318 button->draw_begin = 0; 14319 button->draw_end = 0; 14320 14321 /* contextual button */ 14322 button = &style->contextual_button; 14323 nk_zero_struct(*button); 14324 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14325 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 14326 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 14327 button->border_color = table[NK_COLOR_WINDOW]; 14328 button->text_background = table[NK_COLOR_WINDOW]; 14329 button->text_normal = table[NK_COLOR_TEXT]; 14330 button->text_hover = table[NK_COLOR_TEXT]; 14331 button->text_active = table[NK_COLOR_TEXT]; 14332 button->padding = nk_vec2(2.0f,2.0f); 14333 button->touch_padding = nk_vec2(0.0f,0.0f); 14334 button->userdata = nk_handle_ptr(0); 14335 button->text_alignment = NK_TEXT_CENTERED; 14336 button->border = 0.0f; 14337 button->rounding = 0.0f; 14338 button->draw_begin = 0; 14339 button->draw_end = 0; 14340 14341 /* menu button */ 14342 button = &style->menu_button; 14343 nk_zero_struct(*button); 14344 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14345 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 14346 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 14347 button->border_color = table[NK_COLOR_WINDOW]; 14348 button->text_background = table[NK_COLOR_WINDOW]; 14349 button->text_normal = table[NK_COLOR_TEXT]; 14350 button->text_hover = table[NK_COLOR_TEXT]; 14351 button->text_active = table[NK_COLOR_TEXT]; 14352 button->padding = nk_vec2(2.0f,2.0f); 14353 button->touch_padding = nk_vec2(0.0f,0.0f); 14354 button->userdata = nk_handle_ptr(0); 14355 button->text_alignment = NK_TEXT_CENTERED; 14356 button->border = 0.0f; 14357 button->rounding = 1.0f; 14358 button->draw_begin = 0; 14359 button->draw_end = 0; 14360 14361 /* checkbox toggle */ 14362 toggle = &style->checkbox; 14363 nk_zero_struct(*toggle); 14364 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 14365 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14366 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14367 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14368 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14369 toggle->userdata = nk_handle_ptr(0); 14370 toggle->text_background = table[NK_COLOR_WINDOW]; 14371 toggle->text_normal = table[NK_COLOR_TEXT]; 14372 toggle->text_hover = table[NK_COLOR_TEXT]; 14373 toggle->text_active = table[NK_COLOR_TEXT]; 14374 toggle->padding = nk_vec2(2.0f, 2.0f); 14375 toggle->touch_padding = nk_vec2(0,0); 14376 toggle->border_color = nk_rgba(0,0,0,0); 14377 toggle->border = 0.0f; 14378 toggle->spacing = 4; 14379 14380 /* option toggle */ 14381 toggle = &style->option; 14382 nk_zero_struct(*toggle); 14383 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 14384 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14385 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14386 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14387 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14388 toggle->userdata = nk_handle_ptr(0); 14389 toggle->text_background = table[NK_COLOR_WINDOW]; 14390 toggle->text_normal = table[NK_COLOR_TEXT]; 14391 toggle->text_hover = table[NK_COLOR_TEXT]; 14392 toggle->text_active = table[NK_COLOR_TEXT]; 14393 toggle->padding = nk_vec2(3.0f, 3.0f); 14394 toggle->touch_padding = nk_vec2(0,0); 14395 toggle->border_color = nk_rgba(0,0,0,0); 14396 toggle->border = 0.0f; 14397 toggle->spacing = 4; 14398 14399 /* selectable */ 14400 select = &style->selectable; 14401 nk_zero_struct(*select); 14402 select->normal = nk_style_item_color(table[NK_COLOR_SELECT]); 14403 select->hover = nk_style_item_color(table[NK_COLOR_SELECT]); 14404 select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]); 14405 select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14406 select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14407 select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14408 select->text_normal = table[NK_COLOR_TEXT]; 14409 select->text_hover = table[NK_COLOR_TEXT]; 14410 select->text_pressed = table[NK_COLOR_TEXT]; 14411 select->text_normal_active = table[NK_COLOR_TEXT]; 14412 select->text_hover_active = table[NK_COLOR_TEXT]; 14413 select->text_pressed_active = table[NK_COLOR_TEXT]; 14414 select->padding = nk_vec2(2.0f,2.0f); 14415 select->image_padding = nk_vec2(2.0f,2.0f); 14416 select->touch_padding = nk_vec2(0,0); 14417 select->userdata = nk_handle_ptr(0); 14418 select->rounding = 0.0f; 14419 select->draw_begin = 0; 14420 select->draw_end = 0; 14421 14422 /* slider */ 14423 slider = &style->slider; 14424 nk_zero_struct(*slider); 14425 slider->normal = nk_style_item_hide(); 14426 slider->hover = nk_style_item_hide(); 14427 slider->active = nk_style_item_hide(); 14428 slider->bar_normal = table[NK_COLOR_SLIDER]; 14429 slider->bar_hover = table[NK_COLOR_SLIDER]; 14430 slider->bar_active = table[NK_COLOR_SLIDER]; 14431 slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR]; 14432 slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 14433 slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 14434 slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 14435 slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT; 14436 slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT; 14437 slider->cursor_size = nk_vec2(16,16); 14438 slider->padding = nk_vec2(2,2); 14439 slider->spacing = nk_vec2(2,2); 14440 slider->userdata = nk_handle_ptr(0); 14441 slider->show_buttons = nk_false; 14442 slider->bar_height = 8; 14443 slider->rounding = 0; 14444 slider->draw_begin = 0; 14445 slider->draw_end = 0; 14446 14447 /* slider buttons */ 14448 button = &style->slider.inc_button; 14449 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 14450 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 14451 button->active = nk_style_item_color(nk_rgb(44,44,44)); 14452 button->border_color = nk_rgb(65,65,65); 14453 button->text_background = nk_rgb(40,40,40); 14454 button->text_normal = nk_rgb(175,175,175); 14455 button->text_hover = nk_rgb(175,175,175); 14456 button->text_active = nk_rgb(175,175,175); 14457 button->padding = nk_vec2(8.0f,8.0f); 14458 button->touch_padding = nk_vec2(0.0f,0.0f); 14459 button->userdata = nk_handle_ptr(0); 14460 button->text_alignment = NK_TEXT_CENTERED; 14461 button->border = 1.0f; 14462 button->rounding = 0.0f; 14463 button->draw_begin = 0; 14464 button->draw_end = 0; 14465 style->slider.dec_button = style->slider.inc_button; 14466 14467 /* progressbar */ 14468 prog = &style->progress; 14469 nk_zero_struct(*prog); 14470 prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]); 14471 prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]); 14472 prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]); 14473 prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 14474 prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 14475 prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 14476 prog->border_color = nk_rgba(0,0,0,0); 14477 prog->cursor_border_color = nk_rgba(0,0,0,0); 14478 prog->userdata = nk_handle_ptr(0); 14479 prog->padding = nk_vec2(4,4); 14480 prog->rounding = 0; 14481 prog->border = 0; 14482 prog->cursor_rounding = 0; 14483 prog->cursor_border = 0; 14484 prog->draw_begin = 0; 14485 prog->draw_end = 0; 14486 14487 /* scrollbars */ 14488 scroll = &style->scrollh; 14489 nk_zero_struct(*scroll); 14490 scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14491 scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14492 scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14493 scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]); 14494 scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]); 14495 scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]); 14496 scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID; 14497 scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID; 14498 scroll->userdata = nk_handle_ptr(0); 14499 scroll->border_color = table[NK_COLOR_SCROLLBAR]; 14500 scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR]; 14501 scroll->padding = nk_vec2(0,0); 14502 scroll->show_buttons = nk_false; 14503 scroll->border = 0; 14504 scroll->rounding = 0; 14505 scroll->border_cursor = 0; 14506 scroll->rounding_cursor = 0; 14507 scroll->draw_begin = 0; 14508 scroll->draw_end = 0; 14509 style->scrollv = style->scrollh; 14510 14511 /* scrollbars buttons */ 14512 button = &style->scrollh.inc_button; 14513 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 14514 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 14515 button->active = nk_style_item_color(nk_rgb(44,44,44)); 14516 button->border_color = nk_rgb(65,65,65); 14517 button->text_background = nk_rgb(40,40,40); 14518 button->text_normal = nk_rgb(175,175,175); 14519 button->text_hover = nk_rgb(175,175,175); 14520 button->text_active = nk_rgb(175,175,175); 14521 button->padding = nk_vec2(4.0f,4.0f); 14522 button->touch_padding = nk_vec2(0.0f,0.0f); 14523 button->userdata = nk_handle_ptr(0); 14524 button->text_alignment = NK_TEXT_CENTERED; 14525 button->border = 1.0f; 14526 button->rounding = 0.0f; 14527 button->draw_begin = 0; 14528 button->draw_end = 0; 14529 style->scrollh.dec_button = style->scrollh.inc_button; 14530 style->scrollv.inc_button = style->scrollh.inc_button; 14531 style->scrollv.dec_button = style->scrollh.inc_button; 14532 14533 /* edit */ 14534 edit = &style->edit; 14535 nk_zero_struct(*edit); 14536 edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]); 14537 edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]); 14538 edit->active = nk_style_item_color(table[NK_COLOR_EDIT]); 14539 edit->cursor_normal = table[NK_COLOR_TEXT]; 14540 edit->cursor_hover = table[NK_COLOR_TEXT]; 14541 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 14542 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 14543 edit->border_color = table[NK_COLOR_BORDER]; 14544 edit->text_normal = table[NK_COLOR_TEXT]; 14545 edit->text_hover = table[NK_COLOR_TEXT]; 14546 edit->text_active = table[NK_COLOR_TEXT]; 14547 edit->selected_normal = table[NK_COLOR_TEXT]; 14548 edit->selected_hover = table[NK_COLOR_TEXT]; 14549 edit->selected_text_normal = table[NK_COLOR_EDIT]; 14550 edit->selected_text_hover = table[NK_COLOR_EDIT]; 14551 edit->scrollbar_size = nk_vec2(10,10); 14552 edit->scrollbar = style->scrollv; 14553 edit->padding = nk_vec2(4,4); 14554 edit->row_padding = 2; 14555 edit->cursor_size = 4; 14556 edit->border = 1; 14557 edit->rounding = 0; 14558 14559 /* property */ 14560 property = &style->property; 14561 nk_zero_struct(*property); 14562 property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14563 property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14564 property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14565 property->border_color = table[NK_COLOR_BORDER]; 14566 property->label_normal = table[NK_COLOR_TEXT]; 14567 property->label_hover = table[NK_COLOR_TEXT]; 14568 property->label_active = table[NK_COLOR_TEXT]; 14569 property->sym_left = NK_SYMBOL_TRIANGLE_LEFT; 14570 property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT; 14571 property->userdata = nk_handle_ptr(0); 14572 property->padding = nk_vec2(4,4); 14573 property->border = 1; 14574 property->rounding = 10; 14575 property->draw_begin = 0; 14576 property->draw_end = 0; 14577 14578 /* property buttons */ 14579 button = &style->property.dec_button; 14580 nk_zero_struct(*button); 14581 button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14582 button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14583 button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14584 button->border_color = nk_rgba(0,0,0,0); 14585 button->text_background = table[NK_COLOR_PROPERTY]; 14586 button->text_normal = table[NK_COLOR_TEXT]; 14587 button->text_hover = table[NK_COLOR_TEXT]; 14588 button->text_active = table[NK_COLOR_TEXT]; 14589 button->padding = nk_vec2(0.0f,0.0f); 14590 button->touch_padding = nk_vec2(0.0f,0.0f); 14591 button->userdata = nk_handle_ptr(0); 14592 button->text_alignment = NK_TEXT_CENTERED; 14593 button->border = 0.0f; 14594 button->rounding = 0.0f; 14595 button->draw_begin = 0; 14596 button->draw_end = 0; 14597 style->property.inc_button = style->property.dec_button; 14598 14599 /* property edit */ 14600 edit = &style->property.edit; 14601 nk_zero_struct(*edit); 14602 edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14603 edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14604 edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14605 edit->border_color = nk_rgba(0,0,0,0); 14606 edit->cursor_normal = table[NK_COLOR_TEXT]; 14607 edit->cursor_hover = table[NK_COLOR_TEXT]; 14608 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 14609 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 14610 edit->text_normal = table[NK_COLOR_TEXT]; 14611 edit->text_hover = table[NK_COLOR_TEXT]; 14612 edit->text_active = table[NK_COLOR_TEXT]; 14613 edit->selected_normal = table[NK_COLOR_TEXT]; 14614 edit->selected_hover = table[NK_COLOR_TEXT]; 14615 edit->selected_text_normal = table[NK_COLOR_EDIT]; 14616 edit->selected_text_hover = table[NK_COLOR_EDIT]; 14617 edit->padding = nk_vec2(0,0); 14618 edit->cursor_size = 8; 14619 edit->border = 0; 14620 edit->rounding = 0; 14621 14622 /* chart */ 14623 chart = &style->chart; 14624 nk_zero_struct(*chart); 14625 chart->background = nk_style_item_color(table[NK_COLOR_CHART]); 14626 chart->border_color = table[NK_COLOR_BORDER]; 14627 chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT]; 14628 chart->color = table[NK_COLOR_CHART_COLOR]; 14629 chart->padding = nk_vec2(4,4); 14630 chart->border = 0; 14631 chart->rounding = 0; 14632 14633 /* combo */ 14634 combo = &style->combo; 14635 combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 14636 combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 14637 combo->active = nk_style_item_color(table[NK_COLOR_COMBO]); 14638 combo->border_color = table[NK_COLOR_BORDER]; 14639 combo->label_normal = table[NK_COLOR_TEXT]; 14640 combo->label_hover = table[NK_COLOR_TEXT]; 14641 combo->label_active = table[NK_COLOR_TEXT]; 14642 combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN; 14643 combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN; 14644 combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN; 14645 combo->content_padding = nk_vec2(4,4); 14646 combo->button_padding = nk_vec2(0,4); 14647 combo->spacing = nk_vec2(4,0); 14648 combo->border = 1; 14649 combo->rounding = 0; 14650 14651 /* combo button */ 14652 button = &style->combo.button; 14653 nk_zero_struct(*button); 14654 button->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 14655 button->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 14656 button->active = nk_style_item_color(table[NK_COLOR_COMBO]); 14657 button->border_color = nk_rgba(0,0,0,0); 14658 button->text_background = table[NK_COLOR_COMBO]; 14659 button->text_normal = table[NK_COLOR_TEXT]; 14660 button->text_hover = table[NK_COLOR_TEXT]; 14661 button->text_active = table[NK_COLOR_TEXT]; 14662 button->padding = nk_vec2(2.0f,2.0f); 14663 button->touch_padding = nk_vec2(0.0f,0.0f); 14664 button->userdata = nk_handle_ptr(0); 14665 button->text_alignment = NK_TEXT_CENTERED; 14666 button->border = 0.0f; 14667 button->rounding = 0.0f; 14668 button->draw_begin = 0; 14669 button->draw_end = 0; 14670 14671 /* tab */ 14672 tab = &style->tab; 14673 tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14674 tab->border_color = table[NK_COLOR_BORDER]; 14675 tab->text = table[NK_COLOR_TEXT]; 14676 tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT; 14677 tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN; 14678 tab->padding = nk_vec2(4,4); 14679 tab->spacing = nk_vec2(4,4); 14680 tab->indent = 10.0f; 14681 tab->border = 1; 14682 tab->rounding = 0; 14683 14684 /* tab button */ 14685 button = &style->tab.tab_minimize_button; 14686 nk_zero_struct(*button); 14687 button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14688 button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14689 button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14690 button->border_color = nk_rgba(0,0,0,0); 14691 button->text_background = table[NK_COLOR_TAB_HEADER]; 14692 button->text_normal = table[NK_COLOR_TEXT]; 14693 button->text_hover = table[NK_COLOR_TEXT]; 14694 button->text_active = table[NK_COLOR_TEXT]; 14695 button->padding = nk_vec2(2.0f,2.0f); 14696 button->touch_padding = nk_vec2(0.0f,0.0f); 14697 button->userdata = nk_handle_ptr(0); 14698 button->text_alignment = NK_TEXT_CENTERED; 14699 button->border = 0.0f; 14700 button->rounding = 0.0f; 14701 button->draw_begin = 0; 14702 button->draw_end = 0; 14703 style->tab.tab_maximize_button =*button; 14704 14705 /* node button */ 14706 button = &style->tab.node_minimize_button; 14707 nk_zero_struct(*button); 14708 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14709 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 14710 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 14711 button->border_color = nk_rgba(0,0,0,0); 14712 button->text_background = table[NK_COLOR_TAB_HEADER]; 14713 button->text_normal = table[NK_COLOR_TEXT]; 14714 button->text_hover = table[NK_COLOR_TEXT]; 14715 button->text_active = table[NK_COLOR_TEXT]; 14716 button->padding = nk_vec2(2.0f,2.0f); 14717 button->touch_padding = nk_vec2(0.0f,0.0f); 14718 button->userdata = nk_handle_ptr(0); 14719 button->text_alignment = NK_TEXT_CENTERED; 14720 button->border = 0.0f; 14721 button->rounding = 0.0f; 14722 button->draw_begin = 0; 14723 button->draw_end = 0; 14724 style->tab.node_maximize_button =*button; 14725 14726 /* window header */ 14727 win = &style->window; 14728 win->header.align = NK_HEADER_RIGHT; 14729 win->header.close_symbol = NK_SYMBOL_X; 14730 win->header.minimize_symbol = NK_SYMBOL_MINUS; 14731 win->header.maximize_symbol = NK_SYMBOL_PLUS; 14732 win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14733 win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14734 win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]); 14735 win->header.label_normal = table[NK_COLOR_TEXT]; 14736 win->header.label_hover = table[NK_COLOR_TEXT]; 14737 win->header.label_active = table[NK_COLOR_TEXT]; 14738 win->header.label_padding = nk_vec2(4,4); 14739 win->header.padding = nk_vec2(4,4); 14740 win->header.spacing = nk_vec2(0,0); 14741 14742 /* window header close button */ 14743 button = &style->window.header.close_button; 14744 nk_zero_struct(*button); 14745 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14746 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14747 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 14748 button->border_color = nk_rgba(0,0,0,0); 14749 button->text_background = table[NK_COLOR_HEADER]; 14750 button->text_normal = table[NK_COLOR_TEXT]; 14751 button->text_hover = table[NK_COLOR_TEXT]; 14752 button->text_active = table[NK_COLOR_TEXT]; 14753 button->padding = nk_vec2(0.0f,0.0f); 14754 button->touch_padding = nk_vec2(0.0f,0.0f); 14755 button->userdata = nk_handle_ptr(0); 14756 button->text_alignment = NK_TEXT_CENTERED; 14757 button->border = 0.0f; 14758 button->rounding = 0.0f; 14759 button->draw_begin = 0; 14760 button->draw_end = 0; 14761 14762 /* window header minimize button */ 14763 button = &style->window.header.minimize_button; 14764 nk_zero_struct(*button); 14765 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14766 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14767 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 14768 button->border_color = nk_rgba(0,0,0,0); 14769 button->text_background = table[NK_COLOR_HEADER]; 14770 button->text_normal = table[NK_COLOR_TEXT]; 14771 button->text_hover = table[NK_COLOR_TEXT]; 14772 button->text_active = table[NK_COLOR_TEXT]; 14773 button->padding = nk_vec2(0.0f,0.0f); 14774 button->touch_padding = nk_vec2(0.0f,0.0f); 14775 button->userdata = nk_handle_ptr(0); 14776 button->text_alignment = NK_TEXT_CENTERED; 14777 button->border = 0.0f; 14778 button->rounding = 0.0f; 14779 button->draw_begin = 0; 14780 button->draw_end = 0; 14781 14782 /* window */ 14783 win->background = table[NK_COLOR_WINDOW]; 14784 win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]); 14785 win->border_color = table[NK_COLOR_BORDER]; 14786 win->popup_border_color = table[NK_COLOR_BORDER]; 14787 win->combo_border_color = table[NK_COLOR_BORDER]; 14788 win->contextual_border_color = table[NK_COLOR_BORDER]; 14789 win->menu_border_color = table[NK_COLOR_BORDER]; 14790 win->group_border_color = table[NK_COLOR_BORDER]; 14791 win->tooltip_border_color = table[NK_COLOR_BORDER]; 14792 win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]); 14793 14794 win->rounding = 0.0f; 14795 win->spacing = nk_vec2(4,4); 14796 win->scrollbar_size = nk_vec2(10,10); 14797 win->min_size = nk_vec2(64,64); 14798 14799 win->combo_border = 1.0f; 14800 win->contextual_border = 1.0f; 14801 win->menu_border = 1.0f; 14802 win->group_border = 1.0f; 14803 win->tooltip_border = 1.0f; 14804 win->popup_border = 1.0f; 14805 win->border = 2.0f; 14806 win->min_row_height_padding = 8; 14807 14808 win->padding = nk_vec2(4,4); 14809 win->group_padding = nk_vec2(4,4); 14810 win->popup_padding = nk_vec2(4,4); 14811 win->combo_padding = nk_vec2(4,4); 14812 win->contextual_padding = nk_vec2(4,4); 14813 win->menu_padding = nk_vec2(4,4); 14814 win->tooltip_padding = nk_vec2(4,4); 14815 } 14816 NK_API void 14817 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font) 14818 { 14819 struct nk_style *style; 14820 NK_ASSERT(ctx); 14821 14822 if (!ctx) return; 14823 style = &ctx->style; 14824 style->font = font; 14825 ctx->stacks.fonts.head = 0; 14826 if (ctx->current) 14827 nk_layout_reset_min_row_height(ctx); 14828 } 14829 NK_API int 14830 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font) 14831 { 14832 struct nk_config_stack_user_font *font_stack; 14833 struct nk_config_stack_user_font_element *element; 14834 14835 NK_ASSERT(ctx); 14836 if (!ctx) return 0; 14837 14838 font_stack = &ctx->stacks.fonts; 14839 NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements)); 14840 if (font_stack->head >= (int)NK_LEN(font_stack->elements)) 14841 return 0; 14842 14843 element = &font_stack->elements[font_stack->head++]; 14844 element->address = &ctx->style.font; 14845 element->old_value = ctx->style.font; 14846 ctx->style.font = font; 14847 return 1; 14848 } 14849 NK_API int 14850 nk_style_pop_font(struct nk_context *ctx) 14851 { 14852 struct nk_config_stack_user_font *font_stack; 14853 struct nk_config_stack_user_font_element *element; 14854 14855 NK_ASSERT(ctx); 14856 if (!ctx) return 0; 14857 14858 font_stack = &ctx->stacks.fonts; 14859 NK_ASSERT(font_stack->head > 0); 14860 if (font_stack->head < 1) 14861 return 0; 14862 14863 element = &font_stack->elements[--font_stack->head]; 14864 *element->address = element->old_value; 14865 return 1; 14866 } 14867 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \ 14868 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\ 14869 {\ 14870 struct nk_config_stack_##type * type_stack;\ 14871 struct nk_config_stack_##type##_element *element;\ 14872 NK_ASSERT(ctx);\ 14873 if (!ctx) return 0;\ 14874 type_stack = &ctx->stacks.stack;\ 14875 NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\ 14876 if (type_stack->head >= (int)NK_LEN(type_stack->elements))\ 14877 return 0;\ 14878 element = &type_stack->elements[type_stack->head++];\ 14879 element->address = address;\ 14880 element->old_value = *address;\ 14881 *address = value;\ 14882 return 1;\ 14883 } 14884 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \ 14885 nk_style_pop_##type(struct nk_context *ctx)\ 14886 {\ 14887 struct nk_config_stack_##type *type_stack;\ 14888 struct nk_config_stack_##type##_element *element;\ 14889 NK_ASSERT(ctx);\ 14890 if (!ctx) return 0;\ 14891 type_stack = &ctx->stacks.stack;\ 14892 NK_ASSERT(type_stack->head > 0);\ 14893 if (type_stack->head < 1)\ 14894 return 0;\ 14895 element = &type_stack->elements[--type_stack->head];\ 14896 *element->address = element->old_value;\ 14897 return 1;\ 14898 } 14899 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items) 14900 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats) 14901 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors) 14902 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags) 14903 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors) 14904 14905 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items) 14906 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats) 14907 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors) 14908 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags) 14909 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors) 14910 14911 NK_API int 14912 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c) 14913 { 14914 struct nk_style *style; 14915 NK_ASSERT(ctx); 14916 if (!ctx) return 0; 14917 style = &ctx->style; 14918 if (style->cursors[c]) { 14919 style->cursor_active = style->cursors[c]; 14920 return 1; 14921 } 14922 return 0; 14923 } 14924 NK_API void 14925 nk_style_show_cursor(struct nk_context *ctx) 14926 { 14927 ctx->style.cursor_visible = nk_true; 14928 } 14929 NK_API void 14930 nk_style_hide_cursor(struct nk_context *ctx) 14931 { 14932 ctx->style.cursor_visible = nk_false; 14933 } 14934 NK_API void 14935 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor, 14936 const struct nk_cursor *c) 14937 { 14938 struct nk_style *style; 14939 NK_ASSERT(ctx); 14940 if (!ctx) return; 14941 style = &ctx->style; 14942 style->cursors[cursor] = c; 14943 } 14944 NK_API void 14945 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors) 14946 { 14947 int i = 0; 14948 struct nk_style *style; 14949 NK_ASSERT(ctx); 14950 if (!ctx) return; 14951 style = &ctx->style; 14952 for (i = 0; i < NK_CURSOR_COUNT; ++i) 14953 style->cursors[i] = &cursors[i]; 14954 style->cursor_visible = nk_true; 14955 } 14956 14957 14958 14959 14960 14961 /* ============================================================== 14962 * 14963 * CONTEXT 14964 * 14965 * ===============================================================*/ 14966 NK_INTERN void 14967 nk_setup(struct nk_context *ctx, const struct nk_user_font *font) 14968 { 14969 NK_ASSERT(ctx); 14970 if (!ctx) return; 14971 nk_zero_struct(*ctx); 14972 nk_style_default(ctx); 14973 ctx->seq = 1; 14974 if (font) ctx->style.font = font; 14975 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 14976 nk_draw_list_init(&ctx->draw_list); 14977 #endif 14978 } 14979 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 14980 NK_API int 14981 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font) 14982 { 14983 struct nk_allocator alloc; 14984 alloc.userdata.ptr = 0; 14985 alloc.alloc = nk_malloc; 14986 alloc.free = nk_mfree; 14987 return nk_init(ctx, &alloc, font); 14988 } 14989 #endif 14990 NK_API int 14991 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, 14992 const struct nk_user_font *font) 14993 { 14994 NK_ASSERT(memory); 14995 if (!memory) return 0; 14996 nk_setup(ctx, font); 14997 nk_buffer_init_fixed(&ctx->memory, memory, size); 14998 ctx->use_pool = nk_false; 14999 return 1; 15000 } 15001 NK_API int 15002 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, 15003 struct nk_buffer *pool, const struct nk_user_font *font) 15004 { 15005 NK_ASSERT(cmds); 15006 NK_ASSERT(pool); 15007 if (!cmds || !pool) return 0; 15008 15009 nk_setup(ctx, font); 15010 ctx->memory = *cmds; 15011 if (pool->type == NK_BUFFER_FIXED) { 15012 /* take memory from buffer and alloc fixed pool */ 15013 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size); 15014 } else { 15015 /* create dynamic pool from buffer allocator */ 15016 struct nk_allocator *alloc = &pool->pool; 15017 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 15018 } 15019 ctx->use_pool = nk_true; 15020 return 1; 15021 } 15022 NK_API int 15023 nk_init(struct nk_context *ctx, struct nk_allocator *alloc, 15024 const struct nk_user_font *font) 15025 { 15026 NK_ASSERT(alloc); 15027 if (!alloc) return 0; 15028 nk_setup(ctx, font); 15029 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE); 15030 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 15031 ctx->use_pool = nk_true; 15032 return 1; 15033 } 15034 #ifdef NK_INCLUDE_COMMAND_USERDATA 15035 NK_API void 15036 nk_set_user_data(struct nk_context *ctx, nk_handle handle) 15037 { 15038 if (!ctx) return; 15039 ctx->userdata = handle; 15040 if (ctx->current) 15041 ctx->current->buffer.userdata = handle; 15042 } 15043 #endif 15044 NK_API void 15045 nk_free(struct nk_context *ctx) 15046 { 15047 NK_ASSERT(ctx); 15048 if (!ctx) return; 15049 nk_buffer_free(&ctx->memory); 15050 if (ctx->use_pool) 15051 nk_pool_free(&ctx->pool); 15052 15053 nk_zero(&ctx->input, sizeof(ctx->input)); 15054 nk_zero(&ctx->style, sizeof(ctx->style)); 15055 nk_zero(&ctx->memory, sizeof(ctx->memory)); 15056 15057 ctx->seq = 0; 15058 ctx->build = 0; 15059 ctx->begin = 0; 15060 ctx->end = 0; 15061 ctx->active = 0; 15062 ctx->current = 0; 15063 ctx->freelist = 0; 15064 ctx->count = 0; 15065 } 15066 NK_API void 15067 nk_clear(struct nk_context *ctx) 15068 { 15069 struct nk_window *iter; 15070 struct nk_window *next; 15071 NK_ASSERT(ctx); 15072 15073 if (!ctx) return; 15074 if (ctx->use_pool) 15075 nk_buffer_clear(&ctx->memory); 15076 else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); 15077 15078 ctx->build = 0; 15079 ctx->memory.calls = 0; 15080 ctx->last_widget_state = 0; 15081 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 15082 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); 15083 15084 /* garbage collector */ 15085 iter = ctx->begin; 15086 while (iter) { 15087 /* make sure valid minimized windows do not get removed */ 15088 if ((iter->flags & NK_WINDOW_MINIMIZED) && 15089 !(iter->flags & NK_WINDOW_CLOSED) && 15090 iter->seq == ctx->seq) { 15091 iter = iter->next; 15092 continue; 15093 } 15094 /* remove hotness from hidden or closed windows*/ 15095 if (((iter->flags & NK_WINDOW_HIDDEN) || 15096 (iter->flags & NK_WINDOW_CLOSED)) && 15097 iter == ctx->active) { 15098 ctx->active = iter->prev; 15099 ctx->end = iter->prev; 15100 if (!ctx->end) 15101 ctx->begin = 0; 15102 if (ctx->active) 15103 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM; 15104 } 15105 /* free unused popup windows */ 15106 if (iter->popup.win && iter->popup.win->seq != ctx->seq) { 15107 nk_free_window(ctx, iter->popup.win); 15108 iter->popup.win = 0; 15109 } 15110 /* remove unused window state tables */ 15111 {struct nk_table *n, *it = iter->tables; 15112 while (it) { 15113 n = it->next; 15114 if (it->seq != ctx->seq) { 15115 nk_remove_table(iter, it); 15116 nk_zero(it, sizeof(union nk_page_data)); 15117 nk_free_table(ctx, it); 15118 if (it == iter->tables) 15119 iter->tables = n; 15120 } it = n; 15121 }} 15122 /* window itself is not used anymore so free */ 15123 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { 15124 next = iter->next; 15125 nk_remove_window(ctx, iter); 15126 nk_free_window(ctx, iter); 15127 iter = next; 15128 } else iter = iter->next; 15129 } 15130 ctx->seq++; 15131 } 15132 NK_LIB void 15133 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 15134 { 15135 NK_ASSERT(ctx); 15136 NK_ASSERT(buffer); 15137 if (!ctx || !buffer) return; 15138 buffer->begin = ctx->memory.allocated; 15139 buffer->end = buffer->begin; 15140 buffer->last = buffer->begin; 15141 buffer->clip = nk_null_rect; 15142 } 15143 NK_LIB void 15144 nk_start(struct nk_context *ctx, struct nk_window *win) 15145 { 15146 NK_ASSERT(ctx); 15147 NK_ASSERT(win); 15148 nk_start_buffer(ctx, &win->buffer); 15149 } 15150 NK_LIB void 15151 nk_start_popup(struct nk_context *ctx, struct nk_window *win) 15152 { 15153 struct nk_popup_buffer *buf; 15154 NK_ASSERT(ctx); 15155 NK_ASSERT(win); 15156 if (!ctx || !win) return; 15157 15158 /* save buffer fill state for popup */ 15159 buf = &win->popup.buf; 15160 buf->begin = win->buffer.end; 15161 buf->end = win->buffer.end; 15162 buf->parent = win->buffer.last; 15163 buf->last = buf->begin; 15164 buf->active = nk_true; 15165 } 15166 NK_LIB void 15167 nk_finish_popup(struct nk_context *ctx, struct nk_window *win) 15168 { 15169 struct nk_popup_buffer *buf; 15170 NK_ASSERT(ctx); 15171 NK_ASSERT(win); 15172 if (!ctx || !win) return; 15173 15174 buf = &win->popup.buf; 15175 buf->last = win->buffer.last; 15176 buf->end = win->buffer.end; 15177 } 15178 NK_LIB void 15179 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 15180 { 15181 NK_ASSERT(ctx); 15182 NK_ASSERT(buffer); 15183 if (!ctx || !buffer) return; 15184 buffer->end = ctx->memory.allocated; 15185 } 15186 NK_LIB void 15187 nk_finish(struct nk_context *ctx, struct nk_window *win) 15188 { 15189 struct nk_popup_buffer *buf; 15190 struct nk_command *parent_last; 15191 void *memory; 15192 15193 NK_ASSERT(ctx); 15194 NK_ASSERT(win); 15195 if (!ctx || !win) return; 15196 nk_finish_buffer(ctx, &win->buffer); 15197 if (!win->popup.buf.active) return; 15198 15199 buf = &win->popup.buf; 15200 memory = ctx->memory.memory.ptr; 15201 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent); 15202 parent_last->next = buf->end; 15203 } 15204 NK_LIB void 15205 nk_build(struct nk_context *ctx) 15206 { 15207 struct nk_window *it = 0; 15208 struct nk_command *cmd = 0; 15209 nk_byte *buffer = 0; 15210 15211 /* draw cursor overlay */ 15212 if (!ctx->style.cursor_active) 15213 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 15214 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) { 15215 struct nk_rect mouse_bounds; 15216 const struct nk_cursor *cursor = ctx->style.cursor_active; 15217 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF); 15218 nk_start_buffer(ctx, &ctx->overlay); 15219 15220 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x; 15221 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y; 15222 mouse_bounds.w = cursor->size.x; 15223 mouse_bounds.h = cursor->size.y; 15224 15225 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white); 15226 nk_finish_buffer(ctx, &ctx->overlay); 15227 } 15228 /* build one big draw command list out of all window buffers */ 15229 it = ctx->begin; 15230 buffer = (nk_byte*)ctx->memory.memory.ptr; 15231 while (it != 0) { 15232 struct nk_window *next = it->next; 15233 if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)|| 15234 it->seq != ctx->seq) 15235 goto cont; 15236 15237 cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last); 15238 while (next && ((next->buffer.last == next->buffer.begin) || 15239 (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq)) 15240 next = next->next; /* skip empty command buffers */ 15241 15242 if (next) cmd->next = next->buffer.begin; 15243 cont: it = next; 15244 } 15245 /* append all popup draw commands into lists */ 15246 it = ctx->begin; 15247 while (it != 0) { 15248 struct nk_window *next = it->next; 15249 struct nk_popup_buffer *buf; 15250 if (!it->popup.buf.active) 15251 goto skip; 15252 15253 buf = &it->popup.buf; 15254 cmd->next = buf->begin; 15255 cmd = nk_ptr_add(struct nk_command, buffer, buf->last); 15256 buf->active = nk_false; 15257 skip: it = next; 15258 } 15259 if (cmd) { 15260 /* append overlay commands */ 15261 if (ctx->overlay.end != ctx->overlay.begin) 15262 cmd->next = ctx->overlay.begin; 15263 else cmd->next = ctx->memory.allocated; 15264 } 15265 } 15266 NK_API const struct nk_command* 15267 nk__begin(struct nk_context *ctx) 15268 { 15269 struct nk_window *iter; 15270 nk_byte *buffer; 15271 NK_ASSERT(ctx); 15272 if (!ctx) return 0; 15273 if (!ctx->count) return 0; 15274 15275 buffer = (nk_byte*)ctx->memory.memory.ptr; 15276 if (!ctx->build) { 15277 nk_build(ctx); 15278 ctx->build = nk_true; 15279 } 15280 iter = ctx->begin; 15281 while (iter && ((iter->buffer.begin == iter->buffer.end) || 15282 (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq)) 15283 iter = iter->next; 15284 if (!iter) return 0; 15285 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin); 15286 } 15287 15288 NK_API const struct nk_command* 15289 nk__next(struct nk_context *ctx, const struct nk_command *cmd) 15290 { 15291 nk_byte *buffer; 15292 const struct nk_command *next; 15293 NK_ASSERT(ctx); 15294 if (!ctx || !cmd || !ctx->count) return 0; 15295 if (cmd->next >= ctx->memory.allocated) return 0; 15296 buffer = (nk_byte*)ctx->memory.memory.ptr; 15297 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next); 15298 return next; 15299 } 15300 15301 15302 15303 15304 15305 15306 /* =============================================================== 15307 * 15308 * POOL 15309 * 15310 * ===============================================================*/ 15311 NK_LIB void 15312 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, 15313 unsigned int capacity) 15314 { 15315 nk_zero(pool, sizeof(*pool)); 15316 pool->alloc = *alloc; 15317 pool->capacity = capacity; 15318 pool->type = NK_BUFFER_DYNAMIC; 15319 pool->pages = 0; 15320 } 15321 NK_LIB void 15322 nk_pool_free(struct nk_pool *pool) 15323 { 15324 struct nk_page *iter = pool->pages; 15325 if (!pool) return; 15326 if (pool->type == NK_BUFFER_FIXED) return; 15327 while (iter) { 15328 struct nk_page *next = iter->next; 15329 pool->alloc.free(pool->alloc.userdata, iter); 15330 iter = next; 15331 } 15332 } 15333 NK_LIB void 15334 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size) 15335 { 15336 nk_zero(pool, sizeof(*pool)); 15337 NK_ASSERT(size >= sizeof(struct nk_page)); 15338 if (size < sizeof(struct nk_page)) return; 15339 pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element); 15340 pool->pages = (struct nk_page*)memory; 15341 pool->type = NK_BUFFER_FIXED; 15342 pool->size = size; 15343 } 15344 NK_LIB struct nk_page_element* 15345 nk_pool_alloc(struct nk_pool *pool) 15346 { 15347 if (!pool->pages || pool->pages->size >= pool->capacity) { 15348 /* allocate new page */ 15349 struct nk_page *page; 15350 if (pool->type == NK_BUFFER_FIXED) { 15351 NK_ASSERT(pool->pages); 15352 if (!pool->pages) return 0; 15353 NK_ASSERT(pool->pages->size < pool->capacity); 15354 return 0; 15355 } else { 15356 nk_size size = sizeof(struct nk_page); 15357 size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data); 15358 page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size); 15359 page->next = pool->pages; 15360 pool->pages = page; 15361 page->size = 0; 15362 } 15363 } return &pool->pages->win[pool->pages->size++]; 15364 } 15365 15366 15367 15368 15369 15370 /* =============================================================== 15371 * 15372 * PAGE ELEMENT 15373 * 15374 * ===============================================================*/ 15375 NK_LIB struct nk_page_element* 15376 nk_create_page_element(struct nk_context *ctx) 15377 { 15378 struct nk_page_element *elem; 15379 if (ctx->freelist) { 15380 /* unlink page element from free list */ 15381 elem = ctx->freelist; 15382 ctx->freelist = elem->next; 15383 } else if (ctx->use_pool) { 15384 /* allocate page element from memory pool */ 15385 elem = nk_pool_alloc(&ctx->pool); 15386 NK_ASSERT(elem); 15387 if (!elem) return 0; 15388 } else { 15389 /* allocate new page element from back of fixed size memory buffer */ 15390 NK_STORAGE const nk_size size = sizeof(struct nk_page_element); 15391 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element); 15392 elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align); 15393 NK_ASSERT(elem); 15394 if (!elem) return 0; 15395 } 15396 nk_zero_struct(*elem); 15397 elem->next = 0; 15398 elem->prev = 0; 15399 return elem; 15400 } 15401 NK_LIB void 15402 nk_link_page_element_into_freelist(struct nk_context *ctx, 15403 struct nk_page_element *elem) 15404 { 15405 /* link table into freelist */ 15406 if (!ctx->freelist) { 15407 ctx->freelist = elem; 15408 } else { 15409 elem->next = ctx->freelist; 15410 ctx->freelist = elem; 15411 } 15412 } 15413 NK_LIB void 15414 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem) 15415 { 15416 /* we have a pool so just add to free list */ 15417 if (ctx->use_pool) { 15418 nk_link_page_element_into_freelist(ctx, elem); 15419 return; 15420 } 15421 /* if possible remove last element from back of fixed memory buffer */ 15422 {void *elem_end = (void*)(elem + 1); 15423 void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size; 15424 if (elem_end == buffer_end) 15425 ctx->memory.size -= sizeof(struct nk_page_element); 15426 else nk_link_page_element_into_freelist(ctx, elem);} 15427 } 15428 15429 15430 15431 15432 15433 /* =============================================================== 15434 * 15435 * TABLE 15436 * 15437 * ===============================================================*/ 15438 NK_LIB struct nk_table* 15439 nk_create_table(struct nk_context *ctx) 15440 { 15441 struct nk_page_element *elem; 15442 elem = nk_create_page_element(ctx); 15443 if (!elem) return 0; 15444 nk_zero_struct(*elem); 15445 return &elem->data.tbl; 15446 } 15447 NK_LIB void 15448 nk_free_table(struct nk_context *ctx, struct nk_table *tbl) 15449 { 15450 union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl); 15451 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 15452 nk_free_page_element(ctx, pe); 15453 } 15454 NK_LIB void 15455 nk_push_table(struct nk_window *win, struct nk_table *tbl) 15456 { 15457 if (!win->tables) { 15458 win->tables = tbl; 15459 tbl->next = 0; 15460 tbl->prev = 0; 15461 tbl->size = 0; 15462 win->table_count = 1; 15463 return; 15464 } 15465 win->tables->prev = tbl; 15466 tbl->next = win->tables; 15467 tbl->prev = 0; 15468 tbl->size = 0; 15469 win->tables = tbl; 15470 win->table_count++; 15471 } 15472 NK_LIB void 15473 nk_remove_table(struct nk_window *win, struct nk_table *tbl) 15474 { 15475 if (win->tables == tbl) 15476 win->tables = tbl->next; 15477 if (tbl->next) 15478 tbl->next->prev = tbl->prev; 15479 if (tbl->prev) 15480 tbl->prev->next = tbl->next; 15481 tbl->next = 0; 15482 tbl->prev = 0; 15483 } 15484 NK_LIB nk_uint* 15485 nk_add_value(struct nk_context *ctx, struct nk_window *win, 15486 nk_hash name, nk_uint value) 15487 { 15488 NK_ASSERT(ctx); 15489 NK_ASSERT(win); 15490 if (!win || !ctx) return 0; 15491 if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) { 15492 struct nk_table *tbl = nk_create_table(ctx); 15493 NK_ASSERT(tbl); 15494 if (!tbl) return 0; 15495 nk_push_table(win, tbl); 15496 } 15497 win->tables->seq = win->seq; 15498 win->tables->keys[win->tables->size] = name; 15499 win->tables->values[win->tables->size] = value; 15500 return &win->tables->values[win->tables->size++]; 15501 } 15502 NK_LIB nk_uint* 15503 nk_find_value(struct nk_window *win, nk_hash name) 15504 { 15505 struct nk_table *iter = win->tables; 15506 while (iter) { 15507 unsigned int i = 0; 15508 unsigned int size = iter->size; 15509 for (i = 0; i < size; ++i) { 15510 if (iter->keys[i] == name) { 15511 iter->seq = win->seq; 15512 return &iter->values[i]; 15513 } 15514 } size = NK_VALUE_PAGE_CAPACITY; 15515 iter = iter->next; 15516 } 15517 return 0; 15518 } 15519 15520 15521 15522 15523 15524 /* =============================================================== 15525 * 15526 * PANEL 15527 * 15528 * ===============================================================*/ 15529 NK_LIB void* 15530 nk_create_panel(struct nk_context *ctx) 15531 { 15532 struct nk_page_element *elem; 15533 elem = nk_create_page_element(ctx); 15534 if (!elem) return 0; 15535 nk_zero_struct(*elem); 15536 return &elem->data.pan; 15537 } 15538 NK_LIB void 15539 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan) 15540 { 15541 union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan); 15542 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 15543 nk_free_page_element(ctx, pe); 15544 } 15545 NK_LIB int 15546 nk_panel_has_header(nk_flags flags, const char *title) 15547 { 15548 int active = 0; 15549 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); 15550 active = active || (flags & NK_WINDOW_TITLE); 15551 active = active && !(flags & NK_WINDOW_HIDDEN) && title; 15552 return active; 15553 } 15554 NK_LIB struct nk_vec2 15555 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type) 15556 { 15557 switch (type) { 15558 default: 15559 case NK_PANEL_WINDOW: return style->window.padding; 15560 case NK_PANEL_GROUP: return style->window.group_padding; 15561 case NK_PANEL_POPUP: return style->window.popup_padding; 15562 case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding; 15563 case NK_PANEL_COMBO: return style->window.combo_padding; 15564 case NK_PANEL_MENU: return style->window.menu_padding; 15565 case NK_PANEL_TOOLTIP: return style->window.menu_padding;} 15566 } 15567 NK_LIB float 15568 nk_panel_get_border(const struct nk_style *style, nk_flags flags, 15569 enum nk_panel_type type) 15570 { 15571 if (flags & NK_WINDOW_BORDER) { 15572 switch (type) { 15573 default: 15574 case NK_PANEL_WINDOW: return style->window.border; 15575 case NK_PANEL_GROUP: return style->window.group_border; 15576 case NK_PANEL_POPUP: return style->window.popup_border; 15577 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border; 15578 case NK_PANEL_COMBO: return style->window.combo_border; 15579 case NK_PANEL_MENU: return style->window.menu_border; 15580 case NK_PANEL_TOOLTIP: return style->window.menu_border; 15581 }} else return 0; 15582 } 15583 NK_LIB struct nk_color 15584 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type) 15585 { 15586 switch (type) { 15587 default: 15588 case NK_PANEL_WINDOW: return style->window.border_color; 15589 case NK_PANEL_GROUP: return style->window.group_border_color; 15590 case NK_PANEL_POPUP: return style->window.popup_border_color; 15591 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color; 15592 case NK_PANEL_COMBO: return style->window.combo_border_color; 15593 case NK_PANEL_MENU: return style->window.menu_border_color; 15594 case NK_PANEL_TOOLTIP: return style->window.menu_border_color;} 15595 } 15596 NK_LIB int 15597 nk_panel_is_sub(enum nk_panel_type type) 15598 { 15599 return (type & NK_PANEL_SET_SUB)?1:0; 15600 } 15601 NK_LIB int 15602 nk_panel_is_nonblock(enum nk_panel_type type) 15603 { 15604 return (type & NK_PANEL_SET_NONBLOCK)?1:0; 15605 } 15606 NK_LIB int 15607 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type) 15608 { 15609 struct nk_input *in; 15610 struct nk_window *win; 15611 struct nk_panel *layout; 15612 struct nk_command_buffer *out; 15613 const struct nk_style *style; 15614 const struct nk_user_font *font; 15615 15616 struct nk_vec2 scrollbar_size; 15617 struct nk_vec2 panel_padding; 15618 15619 NK_ASSERT(ctx); 15620 NK_ASSERT(ctx->current); 15621 NK_ASSERT(ctx->current->layout); 15622 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 15623 nk_zero(ctx->current->layout, sizeof(*ctx->current->layout)); 15624 if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) { 15625 nk_zero(ctx->current->layout, sizeof(struct nk_panel)); 15626 ctx->current->layout->type = panel_type; 15627 return 0; 15628 } 15629 /* pull state into local stack */ 15630 style = &ctx->style; 15631 font = style->font; 15632 win = ctx->current; 15633 layout = win->layout; 15634 out = &win->buffer; 15635 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input; 15636 #ifdef NK_INCLUDE_COMMAND_USERDATA 15637 win->buffer.userdata = ctx->userdata; 15638 #endif 15639 /* pull style configuration into local stack */ 15640 scrollbar_size = style->window.scrollbar_size; 15641 panel_padding = nk_panel_get_padding(style, panel_type); 15642 15643 /* window movement */ 15644 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { 15645 int left_mouse_down; 15646 int left_mouse_clicked; 15647 int left_mouse_click_in_cursor; 15648 15649 /* calculate draggable window space */ 15650 struct nk_rect header; 15651 header.x = win->bounds.x; 15652 header.y = win->bounds.y; 15653 header.w = win->bounds.w; 15654 if (nk_panel_has_header(win->flags, title)) { 15655 header.h = font->height + 2.0f * style->window.header.padding.y; 15656 header.h += 2.0f * style->window.header.label_padding.y; 15657 } else header.h = panel_padding.y; 15658 15659 /* window movement by dragging */ 15660 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 15661 left_mouse_clicked = (int)in->mouse.buttons[NK_BUTTON_LEFT].clicked; 15662 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 15663 NK_BUTTON_LEFT, header, nk_true); 15664 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 15665 win->bounds.x = win->bounds.x + in->mouse.delta.x; 15666 win->bounds.y = win->bounds.y + in->mouse.delta.y; 15667 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; 15668 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; 15669 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE]; 15670 } 15671 } 15672 15673 /* setup panel */ 15674 layout->type = panel_type; 15675 layout->flags = win->flags; 15676 layout->bounds = win->bounds; 15677 layout->bounds.x += panel_padding.x; 15678 layout->bounds.w -= 2*panel_padding.x; 15679 if (win->flags & NK_WINDOW_BORDER) { 15680 layout->border = nk_panel_get_border(style, win->flags, panel_type); 15681 layout->bounds = nk_shrink_rect(layout->bounds, layout->border); 15682 } else layout->border = 0; 15683 layout->at_y = layout->bounds.y; 15684 layout->at_x = layout->bounds.x; 15685 layout->max_x = 0; 15686 layout->header_height = 0; 15687 layout->footer_height = 0; 15688 nk_layout_reset_min_row_height(ctx); 15689 layout->row.index = 0; 15690 layout->row.columns = 0; 15691 layout->row.ratio = 0; 15692 layout->row.item_width = 0; 15693 layout->row.tree_depth = 0; 15694 layout->row.height = panel_padding.y; 15695 layout->has_scrolling = nk_true; 15696 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) 15697 layout->bounds.w -= scrollbar_size.x; 15698 if (!nk_panel_is_nonblock(panel_type)) { 15699 layout->footer_height = 0; 15700 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE) 15701 layout->footer_height = scrollbar_size.y; 15702 layout->bounds.h -= layout->footer_height; 15703 } 15704 15705 /* panel header */ 15706 if (nk_panel_has_header(win->flags, title)) 15707 { 15708 struct nk_text text; 15709 struct nk_rect header; 15710 const struct nk_style_item *background = 0; 15711 15712 /* calculate header bounds */ 15713 header.x = win->bounds.x; 15714 header.y = win->bounds.y; 15715 header.w = win->bounds.w; 15716 header.h = font->height + 2.0f * style->window.header.padding.y; 15717 header.h += (2.0f * style->window.header.label_padding.y); 15718 15719 /* shrink panel by header */ 15720 layout->header_height = header.h; 15721 layout->bounds.y += header.h; 15722 layout->bounds.h -= header.h; 15723 layout->at_y += header.h; 15724 15725 /* select correct header background and text color */ 15726 if (ctx->active == win) { 15727 background = &style->window.header.active; 15728 text.text = style->window.header.label_active; 15729 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) { 15730 background = &style->window.header.hover; 15731 text.text = style->window.header.label_hover; 15732 } else { 15733 background = &style->window.header.normal; 15734 text.text = style->window.header.label_normal; 15735 } 15736 15737 /* draw header background */ 15738 header.h += 1.0f; 15739 if (background->type == NK_STYLE_ITEM_IMAGE) { 15740 text.background = nk_rgba(0,0,0,0); 15741 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 15742 } else { 15743 text.background = background->data.color; 15744 nk_fill_rect(out, header, 0, background->data.color); 15745 } 15746 15747 /* window close button */ 15748 {struct nk_rect button; 15749 button.y = header.y + style->window.header.padding.y; 15750 button.h = header.h - 2 * style->window.header.padding.y; 15751 button.w = button.h; 15752 if (win->flags & NK_WINDOW_CLOSABLE) { 15753 nk_flags ws = 0; 15754 if (style->window.header.align == NK_HEADER_RIGHT) { 15755 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); 15756 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; 15757 } else { 15758 button.x = header.x + style->window.header.padding.x; 15759 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 15760 } 15761 15762 if (nk_do_button_symbol(&ws, &win->buffer, button, 15763 style->window.header.close_symbol, NK_BUTTON_DEFAULT, 15764 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 15765 { 15766 layout->flags |= NK_WINDOW_HIDDEN; 15767 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED; 15768 } 15769 } 15770 15771 /* window minimize button */ 15772 if (win->flags & NK_WINDOW_MINIMIZABLE) { 15773 nk_flags ws = 0; 15774 if (style->window.header.align == NK_HEADER_RIGHT) { 15775 button.x = (header.w + header.x) - button.w; 15776 if (!(win->flags & NK_WINDOW_CLOSABLE)) { 15777 button.x -= style->window.header.padding.x; 15778 header.w -= style->window.header.padding.x; 15779 } 15780 header.w -= button.w + style->window.header.spacing.x; 15781 } else { 15782 button.x = header.x; 15783 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 15784 } 15785 if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)? 15786 style->window.header.maximize_symbol: style->window.header.minimize_symbol, 15787 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 15788 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ? 15789 layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED: 15790 layout->flags | NK_WINDOW_MINIMIZED; 15791 }} 15792 15793 {/* window header title */ 15794 int text_len = nk_strlen(title); 15795 struct nk_rect label = {0,0,0,0}; 15796 float t = font->width(font->userdata, font->height, title, text_len); 15797 text.padding = nk_vec2(0,0); 15798 15799 label.x = header.x + style->window.header.padding.x; 15800 label.x += style->window.header.label_padding.x; 15801 label.y = header.y + style->window.header.label_padding.y; 15802 label.h = font->height + 2 * style->window.header.label_padding.y; 15803 label.w = t + 2 * style->window.header.spacing.x; 15804 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x); 15805 nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);} 15806 } 15807 15808 /* draw window background */ 15809 if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) { 15810 struct nk_rect body; 15811 body.x = win->bounds.x; 15812 body.w = win->bounds.w; 15813 body.y = (win->bounds.y + layout->header_height); 15814 body.h = (win->bounds.h - layout->header_height); 15815 if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE) 15816 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white); 15817 else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color); 15818 } 15819 15820 /* set clipping rectangle */ 15821 {struct nk_rect clip; 15822 layout->clip = layout->bounds; 15823 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, 15824 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); 15825 nk_push_scissor(out, clip); 15826 layout->clip = clip;} 15827 return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED); 15828 } 15829 NK_LIB void 15830 nk_panel_end(struct nk_context *ctx) 15831 { 15832 struct nk_input *in; 15833 struct nk_window *window; 15834 struct nk_panel *layout; 15835 const struct nk_style *style; 15836 struct nk_command_buffer *out; 15837 15838 struct nk_vec2 scrollbar_size; 15839 struct nk_vec2 panel_padding; 15840 15841 NK_ASSERT(ctx); 15842 NK_ASSERT(ctx->current); 15843 NK_ASSERT(ctx->current->layout); 15844 if (!ctx || !ctx->current || !ctx->current->layout) 15845 return; 15846 15847 window = ctx->current; 15848 layout = window->layout; 15849 style = &ctx->style; 15850 out = &window->buffer; 15851 in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input; 15852 if (!nk_panel_is_sub(layout->type)) 15853 nk_push_scissor(out, nk_null_rect); 15854 15855 /* cache configuration data */ 15856 scrollbar_size = style->window.scrollbar_size; 15857 panel_padding = nk_panel_get_padding(style, layout->type); 15858 15859 /* update the current cursor Y-position to point over the last added widget */ 15860 layout->at_y += layout->row.height; 15861 15862 /* dynamic panels */ 15863 if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED)) 15864 { 15865 /* update panel height to fit dynamic growth */ 15866 struct nk_rect empty_space; 15867 if (layout->at_y < (layout->bounds.y + layout->bounds.h)) 15868 layout->bounds.h = layout->at_y - layout->bounds.y; 15869 15870 /* fill top empty space */ 15871 empty_space.x = window->bounds.x; 15872 empty_space.y = layout->bounds.y; 15873 empty_space.h = panel_padding.y; 15874 empty_space.w = window->bounds.w; 15875 nk_fill_rect(out, empty_space, 0, style->window.background); 15876 15877 /* fill left empty space */ 15878 empty_space.x = window->bounds.x; 15879 empty_space.y = layout->bounds.y; 15880 empty_space.w = panel_padding.x + layout->border; 15881 empty_space.h = layout->bounds.h; 15882 nk_fill_rect(out, empty_space, 0, style->window.background); 15883 15884 /* fill right empty space */ 15885 empty_space.x = layout->bounds.x + layout->bounds.w; 15886 empty_space.y = layout->bounds.y; 15887 empty_space.w = panel_padding.x + layout->border; 15888 empty_space.h = layout->bounds.h; 15889 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) 15890 empty_space.w += scrollbar_size.x; 15891 nk_fill_rect(out, empty_space, 0, style->window.background); 15892 15893 /* fill bottom empty space */ 15894 if (layout->footer_height > 0) { 15895 empty_space.x = window->bounds.x; 15896 empty_space.y = layout->bounds.y + layout->bounds.h; 15897 empty_space.w = window->bounds.w; 15898 empty_space.h = layout->footer_height; 15899 nk_fill_rect(out, empty_space, 0, style->window.background); 15900 } 15901 } 15902 15903 /* scrollbars */ 15904 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) && 15905 !(layout->flags & NK_WINDOW_MINIMIZED) && 15906 window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT) 15907 { 15908 struct nk_rect scroll; 15909 int scroll_has_scrolling; 15910 float scroll_target; 15911 float scroll_offset; 15912 float scroll_step; 15913 float scroll_inc; 15914 15915 /* mouse wheel scrolling */ 15916 if (nk_panel_is_sub(layout->type)) 15917 { 15918 /* sub-window mouse wheel scrolling */ 15919 struct nk_window *root_window = window; 15920 struct nk_panel *root_panel = window->layout; 15921 while (root_panel->parent) 15922 root_panel = root_panel->parent; 15923 while (root_window->parent) 15924 root_window = root_window->parent; 15925 15926 /* only allow scrolling if parent window is active */ 15927 scroll_has_scrolling = 0; 15928 if ((root_window == ctx->active) && layout->has_scrolling) { 15929 /* and panel is being hovered and inside clip rect*/ 15930 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) && 15931 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h, 15932 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h)) 15933 { 15934 /* deactivate all parent scrolling */ 15935 root_panel = window->layout; 15936 while (root_panel->parent) { 15937 root_panel->has_scrolling = nk_false; 15938 root_panel = root_panel->parent; 15939 } 15940 root_panel->has_scrolling = nk_false; 15941 scroll_has_scrolling = nk_true; 15942 } 15943 } 15944 } else if (!nk_panel_is_sub(layout->type)) { 15945 /* window mouse wheel scrolling */ 15946 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling; 15947 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling) 15948 window->scrolled = nk_true; 15949 else window->scrolled = nk_false; 15950 } else scroll_has_scrolling = nk_false; 15951 15952 { 15953 /* vertical scrollbar */ 15954 nk_flags state = 0; 15955 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 15956 scroll.y = layout->bounds.y; 15957 scroll.w = scrollbar_size.x; 15958 scroll.h = layout->bounds.h; 15959 15960 scroll_offset = (float)*layout->offset_y; 15961 scroll_step = scroll.h * 0.10f; 15962 scroll_inc = scroll.h * 0.01f; 15963 scroll_target = (float)(int)(layout->at_y - scroll.y); 15964 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling, 15965 scroll_offset, scroll_target, scroll_step, scroll_inc, 15966 &ctx->style.scrollv, in, style->font); 15967 *layout->offset_y = (nk_uint)scroll_offset; 15968 if (in && scroll_has_scrolling) 15969 in->mouse.scroll_delta.y = 0; 15970 } 15971 { 15972 /* horizontal scrollbar */ 15973 nk_flags state = 0; 15974 scroll.x = layout->bounds.x; 15975 scroll.y = layout->bounds.y + layout->bounds.h; 15976 scroll.w = layout->bounds.w; 15977 scroll.h = scrollbar_size.y; 15978 15979 scroll_offset = (float)*layout->offset_x; 15980 scroll_target = (float)(int)(layout->max_x - scroll.x); 15981 scroll_step = layout->max_x * 0.05f; 15982 scroll_inc = layout->max_x * 0.005f; 15983 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling, 15984 scroll_offset, scroll_target, scroll_step, scroll_inc, 15985 &ctx->style.scrollh, in, style->font); 15986 *layout->offset_x = (nk_uint)scroll_offset; 15987 } 15988 } 15989 15990 /* hide scroll if no user input */ 15991 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) { 15992 int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0; 15993 int is_window_hovered = nk_window_is_hovered(ctx); 15994 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 15995 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active)) 15996 window->scrollbar_hiding_timer += ctx->delta_time_seconds; 15997 else window->scrollbar_hiding_timer = 0; 15998 } else window->scrollbar_hiding_timer = 0; 15999 16000 /* window border */ 16001 if (layout->flags & NK_WINDOW_BORDER) 16002 { 16003 struct nk_color border_color = nk_panel_get_border_color(style, layout->type); 16004 const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) 16005 ? (style->window.border + window->bounds.y + layout->header_height) 16006 : ((layout->flags & NK_WINDOW_DYNAMIC) 16007 ? (layout->bounds.y + layout->bounds.h + layout->footer_height) 16008 : (window->bounds.y + window->bounds.h)); 16009 struct nk_rect b = window->bounds; 16010 b.h = padding_y - window->bounds.y; 16011 nk_stroke_rect(out, b, 0, layout->border, border_color); 16012 } 16013 16014 /* scaler */ 16015 if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED)) 16016 { 16017 /* calculate scaler bounds */ 16018 struct nk_rect scaler; 16019 scaler.w = scrollbar_size.x; 16020 scaler.h = scrollbar_size.y; 16021 scaler.y = layout->bounds.y + layout->bounds.h; 16022 if (layout->flags & NK_WINDOW_SCALE_LEFT) 16023 scaler.x = layout->bounds.x - panel_padding.x * 0.5f; 16024 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 16025 if (layout->flags & NK_WINDOW_NO_SCROLLBAR) 16026 scaler.x -= scaler.w; 16027 16028 /* draw scaler */ 16029 {const struct nk_style_item *item = &style->window.scaler; 16030 if (item->type == NK_STYLE_ITEM_IMAGE) 16031 nk_draw_image(out, scaler, &item->data.image, nk_white); 16032 else { 16033 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 16034 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x, 16035 scaler.y + scaler.h, scaler.x + scaler.w, 16036 scaler.y + scaler.h, item->data.color); 16037 } else { 16038 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w, 16039 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color); 16040 } 16041 }} 16042 16043 /* do window scaling */ 16044 if (!(window->flags & NK_WINDOW_ROM)) { 16045 struct nk_vec2 window_size = style->window.min_size; 16046 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 16047 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in, 16048 NK_BUTTON_LEFT, scaler, nk_true); 16049 16050 if (left_mouse_down && left_mouse_click_in_scaler) { 16051 float delta_x = in->mouse.delta.x; 16052 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 16053 delta_x = -delta_x; 16054 window->bounds.x += in->mouse.delta.x; 16055 } 16056 /* dragging in x-direction */ 16057 if (window->bounds.w + delta_x >= window_size.x) { 16058 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) { 16059 window->bounds.w = window->bounds.w + delta_x; 16060 scaler.x += in->mouse.delta.x; 16061 } 16062 } 16063 /* dragging in y-direction (only possible if static window) */ 16064 if (!(layout->flags & NK_WINDOW_DYNAMIC)) { 16065 if (window_size.y < window->bounds.h + in->mouse.delta.y) { 16066 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) { 16067 window->bounds.h = window->bounds.h + in->mouse.delta.y; 16068 scaler.y += in->mouse.delta.y; 16069 } 16070 } 16071 } 16072 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT]; 16073 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f; 16074 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f; 16075 } 16076 } 16077 } 16078 if (!nk_panel_is_sub(layout->type)) { 16079 /* window is hidden so clear command buffer */ 16080 if (layout->flags & NK_WINDOW_HIDDEN) 16081 nk_command_buffer_reset(&window->buffer); 16082 /* window is visible and not tab */ 16083 else nk_finish(ctx, window); 16084 } 16085 16086 /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */ 16087 if (layout->flags & NK_WINDOW_REMOVE_ROM) { 16088 layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 16089 layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 16090 } 16091 window->flags = layout->flags; 16092 16093 /* property garbage collector */ 16094 if (window->property.active && window->property.old != window->property.seq && 16095 window->property.active == window->property.prev) { 16096 nk_zero(&window->property, sizeof(window->property)); 16097 } else { 16098 window->property.old = window->property.seq; 16099 window->property.prev = window->property.active; 16100 window->property.seq = 0; 16101 } 16102 /* edit garbage collector */ 16103 if (window->edit.active && window->edit.old != window->edit.seq && 16104 window->edit.active == window->edit.prev) { 16105 nk_zero(&window->edit, sizeof(window->edit)); 16106 } else { 16107 window->edit.old = window->edit.seq; 16108 window->edit.prev = window->edit.active; 16109 window->edit.seq = 0; 16110 } 16111 /* contextual garbage collector */ 16112 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) { 16113 window->popup.con_count = 0; 16114 window->popup.con_old = 0; 16115 window->popup.active_con = 0; 16116 } else { 16117 window->popup.con_old = window->popup.con_count; 16118 window->popup.con_count = 0; 16119 } 16120 window->popup.combo_count = 0; 16121 /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */ 16122 NK_ASSERT(!layout->row.tree_depth); 16123 } 16124 16125 16126 16127 16128 16129 /* =============================================================== 16130 * 16131 * WINDOW 16132 * 16133 * ===============================================================*/ 16134 NK_LIB void* 16135 nk_create_window(struct nk_context *ctx) 16136 { 16137 struct nk_page_element *elem; 16138 elem = nk_create_page_element(ctx); 16139 if (!elem) return 0; 16140 elem->data.win.seq = ctx->seq; 16141 return &elem->data.win; 16142 } 16143 NK_LIB void 16144 nk_free_window(struct nk_context *ctx, struct nk_window *win) 16145 { 16146 /* unlink windows from list */ 16147 struct nk_table *it = win->tables; 16148 if (win->popup.win) { 16149 nk_free_window(ctx, win->popup.win); 16150 win->popup.win = 0; 16151 } 16152 win->next = 0; 16153 win->prev = 0; 16154 16155 while (it) { 16156 /*free window state tables */ 16157 struct nk_table *n = it->next; 16158 nk_remove_table(win, it); 16159 nk_free_table(ctx, it); 16160 if (it == win->tables) 16161 win->tables = n; 16162 it = n; 16163 } 16164 16165 /* link windows into freelist */ 16166 {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win); 16167 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 16168 nk_free_page_element(ctx, pe);} 16169 } 16170 NK_LIB struct nk_window* 16171 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name) 16172 { 16173 struct nk_window *iter; 16174 iter = ctx->begin; 16175 while (iter) { 16176 NK_ASSERT(iter != iter->next); 16177 if (iter->name == hash) { 16178 int max_len = nk_strlen(iter->name_string); 16179 if (!nk_stricmpn(iter->name_string, name, max_len)) 16180 return iter; 16181 } 16182 iter = iter->next; 16183 } 16184 return 0; 16185 } 16186 NK_LIB void 16187 nk_insert_window(struct nk_context *ctx, struct nk_window *win, 16188 enum nk_window_insert_location loc) 16189 { 16190 const struct nk_window *iter; 16191 NK_ASSERT(ctx); 16192 NK_ASSERT(win); 16193 if (!win || !ctx) return; 16194 16195 iter = ctx->begin; 16196 while (iter) { 16197 NK_ASSERT(iter != iter->next); 16198 NK_ASSERT(iter != win); 16199 if (iter == win) return; 16200 iter = iter->next; 16201 } 16202 16203 if (!ctx->begin) { 16204 win->next = 0; 16205 win->prev = 0; 16206 ctx->begin = win; 16207 ctx->end = win; 16208 ctx->count = 1; 16209 return; 16210 } 16211 if (loc == NK_INSERT_BACK) { 16212 struct nk_window *end; 16213 end = ctx->end; 16214 end->flags |= NK_WINDOW_ROM; 16215 end->next = win; 16216 win->prev = ctx->end; 16217 win->next = 0; 16218 ctx->end = win; 16219 ctx->active = ctx->end; 16220 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 16221 } else { 16222 /*ctx->end->flags |= NK_WINDOW_ROM;*/ 16223 ctx->begin->prev = win; 16224 win->next = ctx->begin; 16225 win->prev = 0; 16226 ctx->begin = win; 16227 ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM; 16228 } 16229 ctx->count++; 16230 } 16231 NK_LIB void 16232 nk_remove_window(struct nk_context *ctx, struct nk_window *win) 16233 { 16234 if (win == ctx->begin || win == ctx->end) { 16235 if (win == ctx->begin) { 16236 ctx->begin = win->next; 16237 if (win->next) 16238 win->next->prev = 0; 16239 } 16240 if (win == ctx->end) { 16241 ctx->end = win->prev; 16242 if (win->prev) 16243 win->prev->next = 0; 16244 } 16245 } else { 16246 if (win->next) 16247 win->next->prev = win->prev; 16248 if (win->prev) 16249 win->prev->next = win->next; 16250 } 16251 if (win == ctx->active || !ctx->active) { 16252 ctx->active = ctx->end; 16253 if (ctx->end) 16254 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 16255 } 16256 win->next = 0; 16257 win->prev = 0; 16258 ctx->count--; 16259 } 16260 NK_API int 16261 nk_begin(struct nk_context *ctx, const char *title, 16262 struct nk_rect bounds, nk_flags flags) 16263 { 16264 return nk_begin_titled(ctx, title, title, bounds, flags); 16265 } 16266 NK_API int 16267 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, 16268 struct nk_rect bounds, nk_flags flags) 16269 { 16270 struct nk_window *win; 16271 struct nk_style *style; 16272 nk_hash name_hash; 16273 int name_len; 16274 int ret = 0; 16275 16276 NK_ASSERT(ctx); 16277 NK_ASSERT(name); 16278 NK_ASSERT(title); 16279 NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font"); 16280 NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call"); 16281 if (!ctx || ctx->current || !title || !name) 16282 return 0; 16283 16284 /* find or create window */ 16285 style = &ctx->style; 16286 name_len = (int)nk_strlen(name); 16287 name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE); 16288 win = nk_find_window(ctx, name_hash, name); 16289 if (!win) { 16290 /* create new window */ 16291 nk_size name_length = (nk_size)name_len; 16292 win = (struct nk_window*)nk_create_window(ctx); 16293 NK_ASSERT(win); 16294 if (!win) return 0; 16295 16296 if (flags & NK_WINDOW_BACKGROUND) 16297 nk_insert_window(ctx, win, NK_INSERT_FRONT); 16298 else nk_insert_window(ctx, win, NK_INSERT_BACK); 16299 nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON); 16300 16301 win->flags = flags; 16302 win->bounds = bounds; 16303 win->name = name_hash; 16304 name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); 16305 NK_MEMCPY(win->name_string, name, name_length); 16306 win->name_string[name_length] = 0; 16307 win->popup.win = 0; 16308 if (!ctx->active) 16309 ctx->active = win; 16310 } else { 16311 /* update window */ 16312 win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1); 16313 win->flags |= flags; 16314 if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE))) 16315 win->bounds = bounds; 16316 /* If this assert triggers you either: 16317 * 16318 * I.) Have more than one window with the same name or 16319 * II.) You forgot to actually draw the window. 16320 * More specific you did not call `nk_clear` (nk_clear will be 16321 * automatically called for you if you are using one of the 16322 * provided demo backends). */ 16323 NK_ASSERT(win->seq != ctx->seq); 16324 win->seq = ctx->seq; 16325 if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) { 16326 ctx->active = win; 16327 ctx->end = win; 16328 } 16329 } 16330 if (win->flags & NK_WINDOW_HIDDEN) { 16331 ctx->current = win; 16332 win->layout = 0; 16333 return 0; 16334 } else nk_start(ctx, win); 16335 16336 /* window overlapping */ 16337 if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT)) 16338 { 16339 int inpanel, ishovered; 16340 struct nk_window *iter = win; 16341 float h = ctx->style.font->height + 2.0f * style->window.header.padding.y + 16342 (2.0f * style->window.header.label_padding.y); 16343 struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))? 16344 win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h); 16345 16346 /* activate window if hovered and no other window is overlapping this window */ 16347 inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true); 16348 inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked; 16349 ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds); 16350 if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) { 16351 iter = win->next; 16352 while (iter) { 16353 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 16354 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 16355 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16356 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 16357 (!(iter->flags & NK_WINDOW_HIDDEN))) 16358 break; 16359 16360 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 16361 NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16362 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 16363 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 16364 break; 16365 iter = iter->next; 16366 } 16367 } 16368 16369 /* activate window if clicked */ 16370 if (iter && inpanel && (win != ctx->end)) { 16371 iter = win->next; 16372 while (iter) { 16373 /* try to find a panel with higher priority in the same position */ 16374 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 16375 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 16376 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y, 16377 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 16378 !(iter->flags & NK_WINDOW_HIDDEN)) 16379 break; 16380 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 16381 NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16382 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 16383 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 16384 break; 16385 iter = iter->next; 16386 } 16387 } 16388 if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) { 16389 win->flags |= (nk_flags)NK_WINDOW_ROM; 16390 iter->flags &= ~(nk_flags)NK_WINDOW_ROM; 16391 ctx->active = iter; 16392 if (!(iter->flags & NK_WINDOW_BACKGROUND)) { 16393 /* current window is active in that position so transfer to top 16394 * at the highest priority in stack */ 16395 nk_remove_window(ctx, iter); 16396 nk_insert_window(ctx, iter, NK_INSERT_BACK); 16397 } 16398 } else { 16399 if (!iter && ctx->end != win) { 16400 if (!(win->flags & NK_WINDOW_BACKGROUND)) { 16401 /* current window is active in that position so transfer to top 16402 * at the highest priority in stack */ 16403 nk_remove_window(ctx, win); 16404 nk_insert_window(ctx, win, NK_INSERT_BACK); 16405 } 16406 win->flags &= ~(nk_flags)NK_WINDOW_ROM; 16407 ctx->active = win; 16408 } 16409 if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND)) 16410 win->flags |= NK_WINDOW_ROM; 16411 } 16412 } 16413 win->layout = (struct nk_panel*)nk_create_panel(ctx); 16414 ctx->current = win; 16415 ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); 16416 win->layout->offset_x = &win->scrollbar.x; 16417 win->layout->offset_y = &win->scrollbar.y; 16418 return ret; 16419 } 16420 NK_API void 16421 nk_end(struct nk_context *ctx) 16422 { 16423 struct nk_panel *layout; 16424 NK_ASSERT(ctx); 16425 NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`"); 16426 if (!ctx || !ctx->current) 16427 return; 16428 16429 layout = ctx->current->layout; 16430 if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) { 16431 ctx->current = 0; 16432 return; 16433 } 16434 nk_panel_end(ctx); 16435 nk_free_panel(ctx, ctx->current->layout); 16436 ctx->current = 0; 16437 } 16438 NK_API struct nk_rect 16439 nk_window_get_bounds(const struct nk_context *ctx) 16440 { 16441 NK_ASSERT(ctx); 16442 NK_ASSERT(ctx->current); 16443 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 16444 return ctx->current->bounds; 16445 } 16446 NK_API struct nk_vec2 16447 nk_window_get_position(const struct nk_context *ctx) 16448 { 16449 NK_ASSERT(ctx); 16450 NK_ASSERT(ctx->current); 16451 if (!ctx || !ctx->current) return nk_vec2(0,0); 16452 return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y); 16453 } 16454 NK_API struct nk_vec2 16455 nk_window_get_size(const struct nk_context *ctx) 16456 { 16457 NK_ASSERT(ctx); 16458 NK_ASSERT(ctx->current); 16459 if (!ctx || !ctx->current) return nk_vec2(0,0); 16460 return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h); 16461 } 16462 NK_API float 16463 nk_window_get_width(const struct nk_context *ctx) 16464 { 16465 NK_ASSERT(ctx); 16466 NK_ASSERT(ctx->current); 16467 if (!ctx || !ctx->current) return 0; 16468 return ctx->current->bounds.w; 16469 } 16470 NK_API float 16471 nk_window_get_height(const struct nk_context *ctx) 16472 { 16473 NK_ASSERT(ctx); 16474 NK_ASSERT(ctx->current); 16475 if (!ctx || !ctx->current) return 0; 16476 return ctx->current->bounds.h; 16477 } 16478 NK_API struct nk_rect 16479 nk_window_get_content_region(struct nk_context *ctx) 16480 { 16481 NK_ASSERT(ctx); 16482 NK_ASSERT(ctx->current); 16483 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 16484 return ctx->current->layout->clip; 16485 } 16486 NK_API struct nk_vec2 16487 nk_window_get_content_region_min(struct nk_context *ctx) 16488 { 16489 NK_ASSERT(ctx); 16490 NK_ASSERT(ctx->current); 16491 NK_ASSERT(ctx->current->layout); 16492 if (!ctx || !ctx->current) return nk_vec2(0,0); 16493 return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y); 16494 } 16495 NK_API struct nk_vec2 16496 nk_window_get_content_region_max(struct nk_context *ctx) 16497 { 16498 NK_ASSERT(ctx); 16499 NK_ASSERT(ctx->current); 16500 NK_ASSERT(ctx->current->layout); 16501 if (!ctx || !ctx->current) return nk_vec2(0,0); 16502 return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w, 16503 ctx->current->layout->clip.y + ctx->current->layout->clip.h); 16504 } 16505 NK_API struct nk_vec2 16506 nk_window_get_content_region_size(struct nk_context *ctx) 16507 { 16508 NK_ASSERT(ctx); 16509 NK_ASSERT(ctx->current); 16510 NK_ASSERT(ctx->current->layout); 16511 if (!ctx || !ctx->current) return nk_vec2(0,0); 16512 return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h); 16513 } 16514 NK_API struct nk_command_buffer* 16515 nk_window_get_canvas(struct nk_context *ctx) 16516 { 16517 NK_ASSERT(ctx); 16518 NK_ASSERT(ctx->current); 16519 NK_ASSERT(ctx->current->layout); 16520 if (!ctx || !ctx->current) return 0; 16521 return &ctx->current->buffer; 16522 } 16523 NK_API struct nk_panel* 16524 nk_window_get_panel(struct nk_context *ctx) 16525 { 16526 NK_ASSERT(ctx); 16527 NK_ASSERT(ctx->current); 16528 if (!ctx || !ctx->current) return 0; 16529 return ctx->current->layout; 16530 } 16531 NK_API void 16532 nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) 16533 { 16534 struct nk_window *win; 16535 NK_ASSERT(ctx); 16536 NK_ASSERT(ctx->current); 16537 if (!ctx || !ctx->current) 16538 return ; 16539 win = ctx->current; 16540 if (offset_x) 16541 *offset_x = win->scrollbar.x; 16542 if (offset_y) 16543 *offset_y = win->scrollbar.y; 16544 } 16545 NK_API int 16546 nk_window_has_focus(const struct nk_context *ctx) 16547 { 16548 NK_ASSERT(ctx); 16549 NK_ASSERT(ctx->current); 16550 NK_ASSERT(ctx->current->layout); 16551 if (!ctx || !ctx->current) return 0; 16552 return ctx->current == ctx->active; 16553 } 16554 NK_API int 16555 nk_window_is_hovered(struct nk_context *ctx) 16556 { 16557 NK_ASSERT(ctx); 16558 NK_ASSERT(ctx->current); 16559 if (!ctx || !ctx->current) return 0; 16560 if(ctx->current->flags & NK_WINDOW_HIDDEN) 16561 return 0; 16562 return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds); 16563 } 16564 NK_API int 16565 nk_window_is_any_hovered(struct nk_context *ctx) 16566 { 16567 struct nk_window *iter; 16568 NK_ASSERT(ctx); 16569 if (!ctx) return 0; 16570 iter = ctx->begin; 16571 while (iter) { 16572 /* check if window is being hovered */ 16573 if(!(iter->flags & NK_WINDOW_HIDDEN)) { 16574 /* check if window popup is being hovered */ 16575 if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) 16576 return 1; 16577 16578 if (iter->flags & NK_WINDOW_MINIMIZED) { 16579 struct nk_rect header = iter->bounds; 16580 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; 16581 if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) 16582 return 1; 16583 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { 16584 return 1; 16585 } 16586 } 16587 iter = iter->next; 16588 } 16589 return 0; 16590 } 16591 NK_API int 16592 nk_item_is_any_active(struct nk_context *ctx) 16593 { 16594 int any_hovered = nk_window_is_any_hovered(ctx); 16595 int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 16596 return any_hovered || any_active; 16597 } 16598 NK_API int 16599 nk_window_is_collapsed(struct nk_context *ctx, const char *name) 16600 { 16601 int title_len; 16602 nk_hash title_hash; 16603 struct nk_window *win; 16604 NK_ASSERT(ctx); 16605 if (!ctx) return 0; 16606 16607 title_len = (int)nk_strlen(name); 16608 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16609 win = nk_find_window(ctx, title_hash, name); 16610 if (!win) return 0; 16611 return win->flags & NK_WINDOW_MINIMIZED; 16612 } 16613 NK_API int 16614 nk_window_is_closed(struct nk_context *ctx, const char *name) 16615 { 16616 int title_len; 16617 nk_hash title_hash; 16618 struct nk_window *win; 16619 NK_ASSERT(ctx); 16620 if (!ctx) return 1; 16621 16622 title_len = (int)nk_strlen(name); 16623 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16624 win = nk_find_window(ctx, title_hash, name); 16625 if (!win) return 1; 16626 return (win->flags & NK_WINDOW_CLOSED); 16627 } 16628 NK_API int 16629 nk_window_is_hidden(struct nk_context *ctx, const char *name) 16630 { 16631 int title_len; 16632 nk_hash title_hash; 16633 struct nk_window *win; 16634 NK_ASSERT(ctx); 16635 if (!ctx) return 1; 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 1; 16641 return (win->flags & NK_WINDOW_HIDDEN); 16642 } 16643 NK_API int 16644 nk_window_is_active(struct nk_context *ctx, const char *name) 16645 { 16646 int title_len; 16647 nk_hash title_hash; 16648 struct nk_window *win; 16649 NK_ASSERT(ctx); 16650 if (!ctx) return 0; 16651 16652 title_len = (int)nk_strlen(name); 16653 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16654 win = nk_find_window(ctx, title_hash, name); 16655 if (!win) return 0; 16656 return win == ctx->active; 16657 } 16658 NK_API struct nk_window* 16659 nk_window_find(struct nk_context *ctx, const char *name) 16660 { 16661 int title_len; 16662 nk_hash title_hash; 16663 title_len = (int)nk_strlen(name); 16664 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16665 return nk_find_window(ctx, title_hash, name); 16666 } 16667 NK_API void 16668 nk_window_close(struct nk_context *ctx, const char *name) 16669 { 16670 struct nk_window *win; 16671 NK_ASSERT(ctx); 16672 if (!ctx) return; 16673 win = nk_window_find(ctx, name); 16674 if (!win) return; 16675 NK_ASSERT(ctx->current != win && "You cannot close a currently active window"); 16676 if (ctx->current == win) return; 16677 win->flags |= NK_WINDOW_HIDDEN; 16678 win->flags |= NK_WINDOW_CLOSED; 16679 } 16680 NK_API void 16681 nk_window_set_bounds(struct nk_context *ctx, 16682 const char *name, struct nk_rect bounds) 16683 { 16684 struct nk_window *win; 16685 NK_ASSERT(ctx); 16686 if (!ctx) return; 16687 win = nk_window_find(ctx, name); 16688 if (!win) return; 16689 NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window"); 16690 win->bounds = bounds; 16691 } 16692 NK_API void 16693 nk_window_set_position(struct nk_context *ctx, 16694 const char *name, struct nk_vec2 pos) 16695 { 16696 struct nk_window *win = nk_window_find(ctx, name); 16697 if (!win) return; 16698 win->bounds.x = pos.x; 16699 win->bounds.y = pos.y; 16700 } 16701 NK_API void 16702 nk_window_set_size(struct nk_context *ctx, 16703 const char *name, struct nk_vec2 size) 16704 { 16705 struct nk_window *win = nk_window_find(ctx, name); 16706 if (!win) return; 16707 win->bounds.w = size.x; 16708 win->bounds.h = size.y; 16709 } 16710 NK_API void 16711 nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) 16712 { 16713 struct nk_window *win; 16714 NK_ASSERT(ctx); 16715 NK_ASSERT(ctx->current); 16716 if (!ctx || !ctx->current) 16717 return; 16718 win = ctx->current; 16719 win->scrollbar.x = offset_x; 16720 win->scrollbar.y = offset_y; 16721 } 16722 NK_API void 16723 nk_window_collapse(struct nk_context *ctx, const char *name, 16724 enum nk_collapse_states c) 16725 { 16726 int title_len; 16727 nk_hash title_hash; 16728 struct nk_window *win; 16729 NK_ASSERT(ctx); 16730 if (!ctx) return; 16731 16732 title_len = (int)nk_strlen(name); 16733 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16734 win = nk_find_window(ctx, title_hash, name); 16735 if (!win) return; 16736 if (c == NK_MINIMIZED) 16737 win->flags |= NK_WINDOW_MINIMIZED; 16738 else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED; 16739 } 16740 NK_API void 16741 nk_window_collapse_if(struct nk_context *ctx, const char *name, 16742 enum nk_collapse_states c, int cond) 16743 { 16744 NK_ASSERT(ctx); 16745 if (!ctx || !cond) return; 16746 nk_window_collapse(ctx, name, c); 16747 } 16748 NK_API void 16749 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s) 16750 { 16751 int title_len; 16752 nk_hash title_hash; 16753 struct nk_window *win; 16754 NK_ASSERT(ctx); 16755 if (!ctx) return; 16756 16757 title_len = (int)nk_strlen(name); 16758 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16759 win = nk_find_window(ctx, title_hash, name); 16760 if (!win) return; 16761 if (s == NK_HIDDEN) { 16762 win->flags |= NK_WINDOW_HIDDEN; 16763 } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN; 16764 } 16765 NK_API void 16766 nk_window_show_if(struct nk_context *ctx, const char *name, 16767 enum nk_show_states s, int cond) 16768 { 16769 NK_ASSERT(ctx); 16770 if (!ctx || !cond) return; 16771 nk_window_show(ctx, name, s); 16772 } 16773 16774 NK_API void 16775 nk_window_set_focus(struct nk_context *ctx, const char *name) 16776 { 16777 int title_len; 16778 nk_hash title_hash; 16779 struct nk_window *win; 16780 NK_ASSERT(ctx); 16781 if (!ctx) return; 16782 16783 title_len = (int)nk_strlen(name); 16784 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16785 win = nk_find_window(ctx, title_hash, name); 16786 if (win && ctx->end != win) { 16787 nk_remove_window(ctx, win); 16788 nk_insert_window(ctx, win, NK_INSERT_BACK); 16789 } 16790 ctx->active = win; 16791 } 16792 16793 16794 16795 16796 /* =============================================================== 16797 * 16798 * POPUP 16799 * 16800 * ===============================================================*/ 16801 NK_API int 16802 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type, 16803 const char *title, nk_flags flags, struct nk_rect rect) 16804 { 16805 struct nk_window *popup; 16806 struct nk_window *win; 16807 struct nk_panel *panel; 16808 16809 int title_len; 16810 nk_hash title_hash; 16811 nk_size allocated; 16812 16813 NK_ASSERT(ctx); 16814 NK_ASSERT(title); 16815 NK_ASSERT(ctx->current); 16816 NK_ASSERT(ctx->current->layout); 16817 if (!ctx || !ctx->current || !ctx->current->layout) 16818 return 0; 16819 16820 win = ctx->current; 16821 panel = win->layout; 16822 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups"); 16823 (void)panel; 16824 title_len = (int)nk_strlen(title); 16825 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP); 16826 16827 popup = win->popup.win; 16828 if (!popup) { 16829 popup = (struct nk_window*)nk_create_window(ctx); 16830 popup->parent = win; 16831 win->popup.win = popup; 16832 win->popup.active = 0; 16833 win->popup.type = NK_PANEL_POPUP; 16834 } 16835 16836 /* make sure we have correct popup */ 16837 if (win->popup.name != title_hash) { 16838 if (!win->popup.active) { 16839 nk_zero(popup, sizeof(*popup)); 16840 win->popup.name = title_hash; 16841 win->popup.active = 1; 16842 win->popup.type = NK_PANEL_POPUP; 16843 } else return 0; 16844 } 16845 16846 /* popup position is local to window */ 16847 ctx->current = popup; 16848 rect.x += win->layout->clip.x; 16849 rect.y += win->layout->clip.y; 16850 16851 /* setup popup data */ 16852 popup->parent = win; 16853 popup->bounds = rect; 16854 popup->seq = ctx->seq; 16855 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 16856 popup->flags = flags; 16857 popup->flags |= NK_WINDOW_BORDER; 16858 if (type == NK_POPUP_DYNAMIC) 16859 popup->flags |= NK_WINDOW_DYNAMIC; 16860 16861 popup->buffer = win->buffer; 16862 nk_start_popup(ctx, win); 16863 allocated = ctx->memory.allocated; 16864 nk_push_scissor(&popup->buffer, nk_null_rect); 16865 16866 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) { 16867 /* popup is running therefore invalidate parent panels */ 16868 struct nk_panel *root; 16869 root = win->layout; 16870 while (root) { 16871 root->flags |= NK_WINDOW_ROM; 16872 root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 16873 root = root->parent; 16874 } 16875 win->popup.active = 1; 16876 popup->layout->offset_x = &popup->scrollbar.x; 16877 popup->layout->offset_y = &popup->scrollbar.y; 16878 popup->layout->parent = win->layout; 16879 return 1; 16880 } else { 16881 /* popup was closed/is invalid so cleanup */ 16882 struct nk_panel *root; 16883 root = win->layout; 16884 while (root) { 16885 root->flags |= NK_WINDOW_REMOVE_ROM; 16886 root = root->parent; 16887 } 16888 win->popup.buf.active = 0; 16889 win->popup.active = 0; 16890 ctx->memory.allocated = allocated; 16891 ctx->current = win; 16892 nk_free_panel(ctx, popup->layout); 16893 popup->layout = 0; 16894 return 0; 16895 } 16896 } 16897 NK_LIB int 16898 nk_nonblock_begin(struct nk_context *ctx, 16899 nk_flags flags, struct nk_rect body, struct nk_rect header, 16900 enum nk_panel_type panel_type) 16901 { 16902 struct nk_window *popup; 16903 struct nk_window *win; 16904 struct nk_panel *panel; 16905 int is_active = nk_true; 16906 16907 NK_ASSERT(ctx); 16908 NK_ASSERT(ctx->current); 16909 NK_ASSERT(ctx->current->layout); 16910 if (!ctx || !ctx->current || !ctx->current->layout) 16911 return 0; 16912 16913 /* popups cannot have popups */ 16914 win = ctx->current; 16915 panel = win->layout; 16916 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); 16917 (void)panel; 16918 popup = win->popup.win; 16919 if (!popup) { 16920 /* create window for nonblocking popup */ 16921 popup = (struct nk_window*)nk_create_window(ctx); 16922 popup->parent = win; 16923 win->popup.win = popup; 16924 win->popup.type = panel_type; 16925 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON); 16926 } else { 16927 /* close the popup if user pressed outside or in the header */ 16928 int pressed, in_body, in_header; 16929 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 16930 pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT); 16931 #else 16932 pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 16933 #endif 16934 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 16935 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); 16936 if (pressed && (!in_body || in_header)) 16937 is_active = nk_false; 16938 } 16939 win->popup.header = header; 16940 16941 if (!is_active) { 16942 /* remove read only mode from all parent panels */ 16943 struct nk_panel *root = win->layout; 16944 while (root) { 16945 root->flags |= NK_WINDOW_REMOVE_ROM; 16946 root = root->parent; 16947 } 16948 return is_active; 16949 } 16950 popup->bounds = body; 16951 popup->parent = win; 16952 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 16953 popup->flags = flags; 16954 popup->flags |= NK_WINDOW_BORDER; 16955 popup->flags |= NK_WINDOW_DYNAMIC; 16956 popup->seq = ctx->seq; 16957 win->popup.active = 1; 16958 NK_ASSERT(popup->layout); 16959 16960 nk_start_popup(ctx, win); 16961 popup->buffer = win->buffer; 16962 nk_push_scissor(&popup->buffer, nk_null_rect); 16963 ctx->current = popup; 16964 16965 nk_panel_begin(ctx, 0, panel_type); 16966 win->buffer = popup->buffer; 16967 popup->layout->parent = win->layout; 16968 popup->layout->offset_x = &popup->scrollbar.x; 16969 popup->layout->offset_y = &popup->scrollbar.y; 16970 16971 /* set read only mode to all parent panels */ 16972 {struct nk_panel *root; 16973 root = win->layout; 16974 while (root) { 16975 root->flags |= NK_WINDOW_ROM; 16976 root = root->parent; 16977 }} 16978 return is_active; 16979 } 16980 NK_API void 16981 nk_popup_close(struct nk_context *ctx) 16982 { 16983 struct nk_window *popup; 16984 NK_ASSERT(ctx); 16985 if (!ctx || !ctx->current) return; 16986 16987 popup = ctx->current; 16988 NK_ASSERT(popup->parent); 16989 NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP); 16990 popup->flags |= NK_WINDOW_HIDDEN; 16991 } 16992 NK_API void 16993 nk_popup_end(struct nk_context *ctx) 16994 { 16995 struct nk_window *win; 16996 struct nk_window *popup; 16997 16998 NK_ASSERT(ctx); 16999 NK_ASSERT(ctx->current); 17000 NK_ASSERT(ctx->current->layout); 17001 if (!ctx || !ctx->current || !ctx->current->layout) 17002 return; 17003 17004 popup = ctx->current; 17005 if (!popup->parent) return; 17006 win = popup->parent; 17007 if (popup->flags & NK_WINDOW_HIDDEN) { 17008 struct nk_panel *root; 17009 root = win->layout; 17010 while (root) { 17011 root->flags |= NK_WINDOW_REMOVE_ROM; 17012 root = root->parent; 17013 } 17014 win->popup.active = 0; 17015 } 17016 nk_push_scissor(&popup->buffer, nk_null_rect); 17017 nk_end(ctx); 17018 17019 win->buffer = popup->buffer; 17020 nk_finish_popup(ctx, win); 17021 ctx->current = win; 17022 nk_push_scissor(&win->buffer, win->layout->clip); 17023 } 17024 NK_API void 17025 nk_popup_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) 17026 { 17027 struct nk_window *popup; 17028 17029 NK_ASSERT(ctx); 17030 NK_ASSERT(ctx->current); 17031 NK_ASSERT(ctx->current->layout); 17032 if (!ctx || !ctx->current || !ctx->current->layout) 17033 return; 17034 17035 popup = ctx->current; 17036 if (offset_x) 17037 *offset_x = popup->scrollbar.x; 17038 if (offset_y) 17039 *offset_y = popup->scrollbar.y; 17040 } 17041 NK_API void 17042 nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) 17043 { 17044 struct nk_window *popup; 17045 17046 NK_ASSERT(ctx); 17047 NK_ASSERT(ctx->current); 17048 NK_ASSERT(ctx->current->layout); 17049 if (!ctx || !ctx->current || !ctx->current->layout) 17050 return; 17051 17052 popup = ctx->current; 17053 popup->scrollbar.x = offset_x; 17054 popup->scrollbar.y = offset_y; 17055 } 17056 17057 17058 17059 17060 /* ============================================================== 17061 * 17062 * CONTEXTUAL 17063 * 17064 * ===============================================================*/ 17065 NK_API int 17066 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size, 17067 struct nk_rect trigger_bounds) 17068 { 17069 struct nk_window *win; 17070 struct nk_window *popup; 17071 struct nk_rect body; 17072 17073 NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0}; 17074 int is_clicked = 0; 17075 int is_open = 0; 17076 int ret = 0; 17077 17078 NK_ASSERT(ctx); 17079 NK_ASSERT(ctx->current); 17080 NK_ASSERT(ctx->current->layout); 17081 if (!ctx || !ctx->current || !ctx->current->layout) 17082 return 0; 17083 17084 win = ctx->current; 17085 ++win->popup.con_count; 17086 if (ctx->current != ctx->active) 17087 return 0; 17088 17089 /* check if currently active contextual is active */ 17090 popup = win->popup.win; 17091 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL); 17092 is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds); 17093 if (win->popup.active_con && win->popup.con_count != win->popup.active_con) 17094 return 0; 17095 if (!is_open && win->popup.active_con) 17096 win->popup.active_con = 0; 17097 if ((!is_open && !is_clicked)) 17098 return 0; 17099 17100 /* calculate contextual position on click */ 17101 win->popup.active_con = win->popup.con_count; 17102 if (is_clicked) { 17103 body.x = ctx->input.mouse.pos.x; 17104 body.y = ctx->input.mouse.pos.y; 17105 } else { 17106 body.x = popup->bounds.x; 17107 body.y = popup->bounds.y; 17108 } 17109 body.w = size.x; 17110 body.h = size.y; 17111 17112 /* start nonblocking contextual popup */ 17113 ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body, 17114 null_rect, NK_PANEL_CONTEXTUAL); 17115 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL; 17116 else { 17117 win->popup.active_con = 0; 17118 win->popup.type = NK_PANEL_NONE; 17119 if (win->popup.win) 17120 win->popup.win->flags = 0; 17121 } 17122 return ret; 17123 } 17124 NK_API int 17125 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len, 17126 nk_flags alignment) 17127 { 17128 struct nk_window *win; 17129 const struct nk_input *in; 17130 const struct nk_style *style; 17131 17132 struct nk_rect bounds; 17133 enum nk_widget_layout_states state; 17134 17135 NK_ASSERT(ctx); 17136 NK_ASSERT(ctx->current); 17137 NK_ASSERT(ctx->current->layout); 17138 if (!ctx || !ctx->current || !ctx->current->layout) 17139 return 0; 17140 17141 win = ctx->current; 17142 style = &ctx->style; 17143 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17144 if (!state) return nk_false; 17145 17146 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17147 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 17148 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) { 17149 nk_contextual_close(ctx); 17150 return nk_true; 17151 } 17152 return nk_false; 17153 } 17154 NK_API int 17155 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align) 17156 { 17157 return nk_contextual_item_text(ctx, label, nk_strlen(label), align); 17158 } 17159 NK_API int 17160 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img, 17161 const char *text, int len, nk_flags align) 17162 { 17163 struct nk_window *win; 17164 const struct nk_input *in; 17165 const struct nk_style *style; 17166 17167 struct nk_rect bounds; 17168 enum nk_widget_layout_states state; 17169 17170 NK_ASSERT(ctx); 17171 NK_ASSERT(ctx->current); 17172 NK_ASSERT(ctx->current->layout); 17173 if (!ctx || !ctx->current || !ctx->current->layout) 17174 return 0; 17175 17176 win = ctx->current; 17177 style = &ctx->style; 17178 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17179 if (!state) return nk_false; 17180 17181 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17182 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, 17183 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){ 17184 nk_contextual_close(ctx); 17185 return nk_true; 17186 } 17187 return nk_false; 17188 } 17189 NK_API int 17190 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img, 17191 const char *label, nk_flags align) 17192 { 17193 return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align); 17194 } 17195 NK_API int 17196 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 17197 const char *text, int len, nk_flags align) 17198 { 17199 struct nk_window *win; 17200 const struct nk_input *in; 17201 const struct nk_style *style; 17202 17203 struct nk_rect bounds; 17204 enum nk_widget_layout_states state; 17205 17206 NK_ASSERT(ctx); 17207 NK_ASSERT(ctx->current); 17208 NK_ASSERT(ctx->current->layout); 17209 if (!ctx || !ctx->current || !ctx->current->layout) 17210 return 0; 17211 17212 win = ctx->current; 17213 style = &ctx->style; 17214 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17215 if (!state) return nk_false; 17216 17217 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17218 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 17219 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) { 17220 nk_contextual_close(ctx); 17221 return nk_true; 17222 } 17223 return nk_false; 17224 } 17225 NK_API int 17226 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 17227 const char *text, nk_flags align) 17228 { 17229 return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align); 17230 } 17231 NK_API void 17232 nk_contextual_close(struct nk_context *ctx) 17233 { 17234 NK_ASSERT(ctx); 17235 NK_ASSERT(ctx->current); 17236 NK_ASSERT(ctx->current->layout); 17237 if (!ctx || !ctx->current || !ctx->current->layout) return; 17238 nk_popup_close(ctx); 17239 } 17240 NK_API void 17241 nk_contextual_end(struct nk_context *ctx) 17242 { 17243 struct nk_window *popup; 17244 struct nk_panel *panel; 17245 NK_ASSERT(ctx); 17246 NK_ASSERT(ctx->current); 17247 if (!ctx || !ctx->current) return; 17248 17249 popup = ctx->current; 17250 panel = popup->layout; 17251 NK_ASSERT(popup->parent); 17252 NK_ASSERT(panel->type & NK_PANEL_SET_POPUP); 17253 if (panel->flags & NK_WINDOW_DYNAMIC) { 17254 /* Close behavior 17255 This is a bit of a hack solution since we do not know before we end our popup 17256 how big it will be. We therefore do not directly know when a 17257 click outside the non-blocking popup must close it at that direct frame. 17258 Instead it will be closed in the next frame.*/ 17259 struct nk_rect body = {0,0,0,0}; 17260 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) { 17261 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type); 17262 body = panel->bounds; 17263 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height); 17264 body.h = (panel->bounds.y + panel->bounds.h) - body.y; 17265 } 17266 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 17267 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 17268 if (pressed && in_body) 17269 popup->flags |= NK_WINDOW_HIDDEN; 17270 } 17271 } 17272 if (popup->flags & NK_WINDOW_HIDDEN) 17273 popup->seq = 0; 17274 nk_popup_end(ctx); 17275 return; 17276 } 17277 17278 17279 17280 17281 17282 /* =============================================================== 17283 * 17284 * MENU 17285 * 17286 * ===============================================================*/ 17287 NK_API void 17288 nk_menubar_begin(struct nk_context *ctx) 17289 { 17290 struct nk_panel *layout; 17291 NK_ASSERT(ctx); 17292 NK_ASSERT(ctx->current); 17293 NK_ASSERT(ctx->current->layout); 17294 if (!ctx || !ctx->current || !ctx->current->layout) 17295 return; 17296 17297 layout = ctx->current->layout; 17298 NK_ASSERT(layout->at_y == layout->bounds.y); 17299 /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin. 17300 If you want a menubar the first nuklear function after `nk_begin` has to be a 17301 `nk_menubar_begin` call. Inside the menubar you then have to allocate space for 17302 widgets (also supports multiple rows). 17303 Example: 17304 if (nk_begin(...)) { 17305 nk_menubar_begin(...); 17306 nk_layout_xxxx(...); 17307 nk_button(...); 17308 nk_layout_xxxx(...); 17309 nk_button(...); 17310 nk_menubar_end(...); 17311 } 17312 nk_end(...); 17313 */ 17314 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 17315 return; 17316 17317 layout->menu.x = layout->at_x; 17318 layout->menu.y = layout->at_y + layout->row.height; 17319 layout->menu.w = layout->bounds.w; 17320 layout->menu.offset.x = *layout->offset_x; 17321 layout->menu.offset.y = *layout->offset_y; 17322 *layout->offset_y = 0; 17323 } 17324 NK_API void 17325 nk_menubar_end(struct nk_context *ctx) 17326 { 17327 struct nk_window *win; 17328 struct nk_panel *layout; 17329 struct nk_command_buffer *out; 17330 17331 NK_ASSERT(ctx); 17332 NK_ASSERT(ctx->current); 17333 NK_ASSERT(ctx->current->layout); 17334 if (!ctx || !ctx->current || !ctx->current->layout) 17335 return; 17336 17337 win = ctx->current; 17338 out = &win->buffer; 17339 layout = win->layout; 17340 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 17341 return; 17342 17343 layout->menu.h = layout->at_y - layout->menu.y; 17344 layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height; 17345 layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height; 17346 17347 *layout->offset_x = layout->menu.offset.x; 17348 *layout->offset_y = layout->menu.offset.y; 17349 layout->at_y = layout->bounds.y - layout->row.height; 17350 17351 layout->clip.y = layout->bounds.y; 17352 layout->clip.h = layout->bounds.h; 17353 nk_push_scissor(out, layout->clip); 17354 } 17355 NK_INTERN int 17356 nk_menu_begin(struct nk_context *ctx, struct nk_window *win, 17357 const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size) 17358 { 17359 int is_open = 0; 17360 int is_active = 0; 17361 struct nk_rect body; 17362 struct nk_window *popup; 17363 nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU); 17364 17365 NK_ASSERT(ctx); 17366 NK_ASSERT(ctx->current); 17367 NK_ASSERT(ctx->current->layout); 17368 if (!ctx || !ctx->current || !ctx->current->layout) 17369 return 0; 17370 17371 body.x = header.x; 17372 body.w = size.x; 17373 body.y = header.y + header.h; 17374 body.h = size.y; 17375 17376 popup = win->popup.win; 17377 is_open = popup ? nk_true : nk_false; 17378 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU); 17379 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 17380 (!is_open && !is_active && !is_clicked)) return 0; 17381 if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU)) 17382 return 0; 17383 17384 win->popup.type = NK_PANEL_MENU; 17385 win->popup.name = hash; 17386 return 1; 17387 } 17388 NK_API int 17389 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len, 17390 nk_flags align, struct nk_vec2 size) 17391 { 17392 struct nk_window *win; 17393 const struct nk_input *in; 17394 struct nk_rect header; 17395 int is_clicked = nk_false; 17396 nk_flags state; 17397 17398 NK_ASSERT(ctx); 17399 NK_ASSERT(ctx->current); 17400 NK_ASSERT(ctx->current->layout); 17401 if (!ctx || !ctx->current || !ctx->current->layout) 17402 return 0; 17403 17404 win = ctx->current; 17405 state = nk_widget(&header, ctx); 17406 if (!state) return 0; 17407 in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17408 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header, 17409 title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 17410 is_clicked = nk_true; 17411 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17412 } 17413 NK_API int nk_menu_begin_label(struct nk_context *ctx, 17414 const char *text, nk_flags align, struct nk_vec2 size) 17415 { 17416 return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size); 17417 } 17418 NK_API int 17419 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img, 17420 struct nk_vec2 size) 17421 { 17422 struct nk_window *win; 17423 struct nk_rect header; 17424 const struct nk_input *in; 17425 int is_clicked = nk_false; 17426 nk_flags state; 17427 17428 NK_ASSERT(ctx); 17429 NK_ASSERT(ctx->current); 17430 NK_ASSERT(ctx->current->layout); 17431 if (!ctx || !ctx->current || !ctx->current->layout) 17432 return 0; 17433 17434 win = ctx->current; 17435 state = nk_widget(&header, ctx); 17436 if (!state) return 0; 17437 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17438 if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header, 17439 img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in)) 17440 is_clicked = nk_true; 17441 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 17442 } 17443 NK_API int 17444 nk_menu_begin_symbol(struct nk_context *ctx, const char *id, 17445 enum nk_symbol_type sym, struct nk_vec2 size) 17446 { 17447 struct nk_window *win; 17448 const struct nk_input *in; 17449 struct nk_rect header; 17450 int is_clicked = nk_false; 17451 nk_flags state; 17452 17453 NK_ASSERT(ctx); 17454 NK_ASSERT(ctx->current); 17455 NK_ASSERT(ctx->current->layout); 17456 if (!ctx || !ctx->current || !ctx->current->layout) 17457 return 0; 17458 17459 win = ctx->current; 17460 state = nk_widget(&header, ctx); 17461 if (!state) return 0; 17462 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17463 if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, 17464 sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 17465 is_clicked = nk_true; 17466 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 17467 } 17468 NK_API int 17469 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len, 17470 nk_flags align, struct nk_image img, struct nk_vec2 size) 17471 { 17472 struct nk_window *win; 17473 struct nk_rect header; 17474 const struct nk_input *in; 17475 int is_clicked = nk_false; 17476 nk_flags state; 17477 17478 NK_ASSERT(ctx); 17479 NK_ASSERT(ctx->current); 17480 NK_ASSERT(ctx->current->layout); 17481 if (!ctx || !ctx->current || !ctx->current->layout) 17482 return 0; 17483 17484 win = ctx->current; 17485 state = nk_widget(&header, ctx); 17486 if (!state) return 0; 17487 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17488 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 17489 header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 17490 ctx->style.font, in)) 17491 is_clicked = nk_true; 17492 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17493 } 17494 NK_API int 17495 nk_menu_begin_image_label(struct nk_context *ctx, 17496 const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size) 17497 { 17498 return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size); 17499 } 17500 NK_API int 17501 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len, 17502 nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size) 17503 { 17504 struct nk_window *win; 17505 struct nk_rect header; 17506 const struct nk_input *in; 17507 int is_clicked = nk_false; 17508 nk_flags state; 17509 17510 NK_ASSERT(ctx); 17511 NK_ASSERT(ctx->current); 17512 NK_ASSERT(ctx->current->layout); 17513 if (!ctx || !ctx->current || !ctx->current->layout) 17514 return 0; 17515 17516 win = ctx->current; 17517 state = nk_widget(&header, ctx); 17518 if (!state) return 0; 17519 17520 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17521 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, 17522 header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 17523 ctx->style.font, in)) is_clicked = nk_true; 17524 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17525 } 17526 NK_API int 17527 nk_menu_begin_symbol_label(struct nk_context *ctx, 17528 const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size ) 17529 { 17530 return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size); 17531 } 17532 NK_API int 17533 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align) 17534 { 17535 return nk_contextual_item_text(ctx, title, len, align); 17536 } 17537 NK_API int 17538 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align) 17539 { 17540 return nk_contextual_item_label(ctx, label, align); 17541 } 17542 NK_API int 17543 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img, 17544 const char *label, nk_flags align) 17545 { 17546 return nk_contextual_item_image_label(ctx, img, label, align); 17547 } 17548 NK_API int 17549 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img, 17550 const char *text, int len, nk_flags align) 17551 { 17552 return nk_contextual_item_image_text(ctx, img, text, len, align); 17553 } 17554 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 17555 const char *text, int len, nk_flags align) 17556 { 17557 return nk_contextual_item_symbol_text(ctx, sym, text, len, align); 17558 } 17559 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 17560 const char *label, nk_flags align) 17561 { 17562 return nk_contextual_item_symbol_label(ctx, sym, label, align); 17563 } 17564 NK_API void nk_menu_close(struct nk_context *ctx) 17565 { 17566 nk_contextual_close(ctx); 17567 } 17568 NK_API void 17569 nk_menu_end(struct nk_context *ctx) 17570 { 17571 nk_contextual_end(ctx); 17572 } 17573 17574 17575 17576 17577 17578 /* =============================================================== 17579 * 17580 * LAYOUT 17581 * 17582 * ===============================================================*/ 17583 NK_API void 17584 nk_layout_set_min_row_height(struct nk_context *ctx, float height) 17585 { 17586 struct nk_window *win; 17587 struct nk_panel *layout; 17588 17589 NK_ASSERT(ctx); 17590 NK_ASSERT(ctx->current); 17591 NK_ASSERT(ctx->current->layout); 17592 if (!ctx || !ctx->current || !ctx->current->layout) 17593 return; 17594 17595 win = ctx->current; 17596 layout = win->layout; 17597 layout->row.min_height = height; 17598 } 17599 NK_API void 17600 nk_layout_reset_min_row_height(struct nk_context *ctx) 17601 { 17602 struct nk_window *win; 17603 struct nk_panel *layout; 17604 17605 NK_ASSERT(ctx); 17606 NK_ASSERT(ctx->current); 17607 NK_ASSERT(ctx->current->layout); 17608 if (!ctx || !ctx->current || !ctx->current->layout) 17609 return; 17610 17611 win = ctx->current; 17612 layout = win->layout; 17613 layout->row.min_height = ctx->style.font->height; 17614 layout->row.min_height += ctx->style.text.padding.y*2; 17615 layout->row.min_height += ctx->style.window.min_row_height_padding*2; 17616 } 17617 NK_LIB float 17618 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, 17619 float total_space, int columns) 17620 { 17621 float panel_padding; 17622 float panel_spacing; 17623 float panel_space; 17624 17625 struct nk_vec2 spacing; 17626 struct nk_vec2 padding; 17627 17628 spacing = style->window.spacing; 17629 padding = nk_panel_get_padding(style, type); 17630 17631 /* calculate the usable panel space */ 17632 panel_padding = 2 * padding.x; 17633 panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x; 17634 panel_space = total_space - panel_padding - panel_spacing; 17635 return panel_space; 17636 } 17637 NK_LIB void 17638 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, 17639 float height, int cols) 17640 { 17641 struct nk_panel *layout; 17642 const struct nk_style *style; 17643 struct nk_command_buffer *out; 17644 17645 struct nk_vec2 item_spacing; 17646 struct nk_color color; 17647 17648 NK_ASSERT(ctx); 17649 NK_ASSERT(ctx->current); 17650 NK_ASSERT(ctx->current->layout); 17651 if (!ctx || !ctx->current || !ctx->current->layout) 17652 return; 17653 17654 /* prefetch some configuration data */ 17655 layout = win->layout; 17656 style = &ctx->style; 17657 out = &win->buffer; 17658 color = style->window.background; 17659 item_spacing = style->window.spacing; 17660 17661 /* if one of these triggers you forgot to add an `if` condition around either 17662 a window, group, popup, combobox or contextual menu `begin` and `end` block. 17663 Example: 17664 if (nk_begin(...) {...} nk_end(...); or 17665 if (nk_group_begin(...) { nk_group_end(...);} */ 17666 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 17667 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 17668 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 17669 17670 /* update the current row and set the current row layout */ 17671 layout->row.index = 0; 17672 layout->at_y += layout->row.height; 17673 layout->row.columns = cols; 17674 if (height == 0.0f) 17675 layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y; 17676 else layout->row.height = height + item_spacing.y; 17677 17678 layout->row.item_offset = 0; 17679 if (layout->flags & NK_WINDOW_DYNAMIC) { 17680 /* draw background for dynamic panels */ 17681 struct nk_rect background; 17682 background.x = win->bounds.x; 17683 background.w = win->bounds.w; 17684 background.y = layout->at_y - 1.0f; 17685 background.h = layout->row.height + 1.0f; 17686 nk_fill_rect(out, background, 0, color); 17687 } 17688 } 17689 NK_LIB void 17690 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, 17691 float height, int cols, int width) 17692 { 17693 /* update the current row and set the current row layout */ 17694 struct nk_window *win; 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 nk_panel_layout(ctx, win, height, cols); 17703 if (fmt == NK_DYNAMIC) 17704 win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED; 17705 else win->layout->row.type = NK_LAYOUT_STATIC_FIXED; 17706 17707 win->layout->row.ratio = 0; 17708 win->layout->row.filled = 0; 17709 win->layout->row.item_offset = 0; 17710 win->layout->row.item_width = (float)width; 17711 } 17712 NK_API float 17713 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width) 17714 { 17715 struct nk_window *win; 17716 NK_ASSERT(ctx); 17717 NK_ASSERT(pixel_width); 17718 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 17719 win = ctx->current; 17720 return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f); 17721 } 17722 NK_API void 17723 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols) 17724 { 17725 nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0); 17726 } 17727 NK_API void 17728 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols) 17729 { 17730 nk_row_layout(ctx, NK_STATIC, height, cols, item_width); 17731 } 17732 NK_API void 17733 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, 17734 float row_height, int cols) 17735 { 17736 struct nk_window *win; 17737 struct nk_panel *layout; 17738 17739 NK_ASSERT(ctx); 17740 NK_ASSERT(ctx->current); 17741 NK_ASSERT(ctx->current->layout); 17742 if (!ctx || !ctx->current || !ctx->current->layout) 17743 return; 17744 17745 win = ctx->current; 17746 layout = win->layout; 17747 nk_panel_layout(ctx, win, row_height, cols); 17748 if (fmt == NK_DYNAMIC) 17749 layout->row.type = NK_LAYOUT_DYNAMIC_ROW; 17750 else layout->row.type = NK_LAYOUT_STATIC_ROW; 17751 17752 layout->row.ratio = 0; 17753 layout->row.filled = 0; 17754 layout->row.item_width = 0; 17755 layout->row.item_offset = 0; 17756 layout->row.columns = cols; 17757 } 17758 NK_API void 17759 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width) 17760 { 17761 struct nk_window *win; 17762 struct nk_panel *layout; 17763 17764 NK_ASSERT(ctx); 17765 NK_ASSERT(ctx->current); 17766 NK_ASSERT(ctx->current->layout); 17767 if (!ctx || !ctx->current || !ctx->current->layout) 17768 return; 17769 17770 win = ctx->current; 17771 layout = win->layout; 17772 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 17773 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 17774 return; 17775 17776 if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) { 17777 float ratio = ratio_or_width; 17778 if ((ratio + layout->row.filled) > 1.0f) return; 17779 if (ratio > 0.0f) 17780 layout->row.item_width = NK_SATURATE(ratio); 17781 else layout->row.item_width = 1.0f - layout->row.filled; 17782 } else layout->row.item_width = ratio_or_width; 17783 } 17784 NK_API void 17785 nk_layout_row_end(struct nk_context *ctx) 17786 { 17787 struct nk_window *win; 17788 struct nk_panel *layout; 17789 17790 NK_ASSERT(ctx); 17791 NK_ASSERT(ctx->current); 17792 NK_ASSERT(ctx->current->layout); 17793 if (!ctx || !ctx->current || !ctx->current->layout) 17794 return; 17795 17796 win = ctx->current; 17797 layout = win->layout; 17798 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 17799 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 17800 return; 17801 layout->row.item_width = 0; 17802 layout->row.item_offset = 0; 17803 } 17804 NK_API void 17805 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt, 17806 float height, int cols, const float *ratio) 17807 { 17808 int i; 17809 int n_undef = 0; 17810 struct nk_window *win; 17811 struct nk_panel *layout; 17812 17813 NK_ASSERT(ctx); 17814 NK_ASSERT(ctx->current); 17815 NK_ASSERT(ctx->current->layout); 17816 if (!ctx || !ctx->current || !ctx->current->layout) 17817 return; 17818 17819 win = ctx->current; 17820 layout = win->layout; 17821 nk_panel_layout(ctx, win, height, cols); 17822 if (fmt == NK_DYNAMIC) { 17823 /* calculate width of undefined widget ratios */ 17824 float r = 0; 17825 layout->row.ratio = ratio; 17826 for (i = 0; i < cols; ++i) { 17827 if (ratio[i] < 0.0f) 17828 n_undef++; 17829 else r += ratio[i]; 17830 } 17831 r = NK_SATURATE(1.0f - r); 17832 layout->row.type = NK_LAYOUT_DYNAMIC; 17833 layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0; 17834 } else { 17835 layout->row.ratio = ratio; 17836 layout->row.type = NK_LAYOUT_STATIC; 17837 layout->row.item_width = 0; 17838 layout->row.item_offset = 0; 17839 } 17840 layout->row.item_offset = 0; 17841 layout->row.filled = 0; 17842 } 17843 NK_API void 17844 nk_layout_row_template_begin(struct nk_context *ctx, float height) 17845 { 17846 struct nk_window *win; 17847 struct nk_panel *layout; 17848 17849 NK_ASSERT(ctx); 17850 NK_ASSERT(ctx->current); 17851 NK_ASSERT(ctx->current->layout); 17852 if (!ctx || !ctx->current || !ctx->current->layout) 17853 return; 17854 17855 win = ctx->current; 17856 layout = win->layout; 17857 nk_panel_layout(ctx, win, height, 1); 17858 layout->row.type = NK_LAYOUT_TEMPLATE; 17859 layout->row.columns = 0; 17860 layout->row.ratio = 0; 17861 layout->row.item_width = 0; 17862 layout->row.item_height = 0; 17863 layout->row.item_offset = 0; 17864 layout->row.filled = 0; 17865 layout->row.item.x = 0; 17866 layout->row.item.y = 0; 17867 layout->row.item.w = 0; 17868 layout->row.item.h = 0; 17869 } 17870 NK_API void 17871 nk_layout_row_template_push_dynamic(struct nk_context *ctx) 17872 { 17873 struct nk_window *win; 17874 struct nk_panel *layout; 17875 17876 NK_ASSERT(ctx); 17877 NK_ASSERT(ctx->current); 17878 NK_ASSERT(ctx->current->layout); 17879 if (!ctx || !ctx->current || !ctx->current->layout) 17880 return; 17881 17882 win = ctx->current; 17883 layout = win->layout; 17884 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17885 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17886 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17887 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17888 layout->row.templates[layout->row.columns++] = -1.0f; 17889 } 17890 NK_API void 17891 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width) 17892 { 17893 struct nk_window *win; 17894 struct nk_panel *layout; 17895 17896 NK_ASSERT(ctx); 17897 NK_ASSERT(ctx->current); 17898 NK_ASSERT(ctx->current->layout); 17899 if (!ctx || !ctx->current || !ctx->current->layout) 17900 return; 17901 17902 win = ctx->current; 17903 layout = win->layout; 17904 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17905 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17906 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17907 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17908 layout->row.templates[layout->row.columns++] = -min_width; 17909 } 17910 NK_API void 17911 nk_layout_row_template_push_static(struct nk_context *ctx, float width) 17912 { 17913 struct nk_window *win; 17914 struct nk_panel *layout; 17915 17916 NK_ASSERT(ctx); 17917 NK_ASSERT(ctx->current); 17918 NK_ASSERT(ctx->current->layout); 17919 if (!ctx || !ctx->current || !ctx->current->layout) 17920 return; 17921 17922 win = ctx->current; 17923 layout = win->layout; 17924 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17925 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17926 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17927 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17928 layout->row.templates[layout->row.columns++] = width; 17929 } 17930 NK_API void 17931 nk_layout_row_template_end(struct nk_context *ctx) 17932 { 17933 struct nk_window *win; 17934 struct nk_panel *layout; 17935 17936 int i = 0; 17937 int variable_count = 0; 17938 int min_variable_count = 0; 17939 float min_fixed_width = 0.0f; 17940 float total_fixed_width = 0.0f; 17941 float max_variable_width = 0.0f; 17942 17943 NK_ASSERT(ctx); 17944 NK_ASSERT(ctx->current); 17945 NK_ASSERT(ctx->current->layout); 17946 if (!ctx || !ctx->current || !ctx->current->layout) 17947 return; 17948 17949 win = ctx->current; 17950 layout = win->layout; 17951 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17952 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17953 for (i = 0; i < layout->row.columns; ++i) { 17954 float width = layout->row.templates[i]; 17955 if (width >= 0.0f) { 17956 total_fixed_width += width; 17957 min_fixed_width += width; 17958 } else if (width < -1.0f) { 17959 width = -width; 17960 total_fixed_width += width; 17961 max_variable_width = NK_MAX(max_variable_width, width); 17962 variable_count++; 17963 } else { 17964 min_variable_count++; 17965 variable_count++; 17966 } 17967 } 17968 if (variable_count) { 17969 float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 17970 layout->bounds.w, layout->row.columns); 17971 float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count; 17972 int enough_space = var_width >= max_variable_width; 17973 if (!enough_space) 17974 var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count; 17975 for (i = 0; i < layout->row.columns; ++i) { 17976 float *width = &layout->row.templates[i]; 17977 *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width; 17978 } 17979 } 17980 } 17981 NK_API void 17982 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt, 17983 float height, int widget_count) 17984 { 17985 struct nk_window *win; 17986 struct nk_panel *layout; 17987 17988 NK_ASSERT(ctx); 17989 NK_ASSERT(ctx->current); 17990 NK_ASSERT(ctx->current->layout); 17991 if (!ctx || !ctx->current || !ctx->current->layout) 17992 return; 17993 17994 win = ctx->current; 17995 layout = win->layout; 17996 nk_panel_layout(ctx, win, height, widget_count); 17997 if (fmt == NK_STATIC) 17998 layout->row.type = NK_LAYOUT_STATIC_FREE; 17999 else layout->row.type = NK_LAYOUT_DYNAMIC_FREE; 18000 18001 layout->row.ratio = 0; 18002 layout->row.filled = 0; 18003 layout->row.item_width = 0; 18004 layout->row.item_offset = 0; 18005 } 18006 NK_API void 18007 nk_layout_space_end(struct nk_context *ctx) 18008 { 18009 struct nk_window *win; 18010 struct nk_panel *layout; 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 layout->row.item_width = 0; 18021 layout->row.item_height = 0; 18022 layout->row.item_offset = 0; 18023 nk_zero(&layout->row.item, sizeof(layout->row.item)); 18024 } 18025 NK_API void 18026 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect) 18027 { 18028 struct nk_window *win; 18029 struct nk_panel *layout; 18030 18031 NK_ASSERT(ctx); 18032 NK_ASSERT(ctx->current); 18033 NK_ASSERT(ctx->current->layout); 18034 if (!ctx || !ctx->current || !ctx->current->layout) 18035 return; 18036 18037 win = ctx->current; 18038 layout = win->layout; 18039 layout->row.item = rect; 18040 } 18041 NK_API struct nk_rect 18042 nk_layout_space_bounds(struct nk_context *ctx) 18043 { 18044 struct nk_rect ret; 18045 struct nk_window *win; 18046 struct nk_panel *layout; 18047 18048 NK_ASSERT(ctx); 18049 NK_ASSERT(ctx->current); 18050 NK_ASSERT(ctx->current->layout); 18051 win = ctx->current; 18052 layout = win->layout; 18053 18054 ret.x = layout->clip.x; 18055 ret.y = layout->clip.y; 18056 ret.w = layout->clip.w; 18057 ret.h = layout->row.height; 18058 return ret; 18059 } 18060 NK_API struct nk_rect 18061 nk_layout_widget_bounds(struct nk_context *ctx) 18062 { 18063 struct nk_rect ret; 18064 struct nk_window *win; 18065 struct nk_panel *layout; 18066 18067 NK_ASSERT(ctx); 18068 NK_ASSERT(ctx->current); 18069 NK_ASSERT(ctx->current->layout); 18070 win = ctx->current; 18071 layout = win->layout; 18072 18073 ret.x = layout->at_x; 18074 ret.y = layout->at_y; 18075 ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0); 18076 ret.h = layout->row.height; 18077 return ret; 18078 } 18079 NK_API struct nk_vec2 18080 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret) 18081 { 18082 struct nk_window *win; 18083 struct nk_panel *layout; 18084 18085 NK_ASSERT(ctx); 18086 NK_ASSERT(ctx->current); 18087 NK_ASSERT(ctx->current->layout); 18088 win = ctx->current; 18089 layout = win->layout; 18090 18091 ret.x += layout->at_x - (float)*layout->offset_x; 18092 ret.y += layout->at_y - (float)*layout->offset_y; 18093 return ret; 18094 } 18095 NK_API struct nk_vec2 18096 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret) 18097 { 18098 struct nk_window *win; 18099 struct nk_panel *layout; 18100 18101 NK_ASSERT(ctx); 18102 NK_ASSERT(ctx->current); 18103 NK_ASSERT(ctx->current->layout); 18104 win = ctx->current; 18105 layout = win->layout; 18106 18107 ret.x += -layout->at_x + (float)*layout->offset_x; 18108 ret.y += -layout->at_y + (float)*layout->offset_y; 18109 return ret; 18110 } 18111 NK_API struct nk_rect 18112 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret) 18113 { 18114 struct nk_window *win; 18115 struct nk_panel *layout; 18116 18117 NK_ASSERT(ctx); 18118 NK_ASSERT(ctx->current); 18119 NK_ASSERT(ctx->current->layout); 18120 win = ctx->current; 18121 layout = win->layout; 18122 18123 ret.x += layout->at_x - (float)*layout->offset_x; 18124 ret.y += layout->at_y - (float)*layout->offset_y; 18125 return ret; 18126 } 18127 NK_API struct nk_rect 18128 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret) 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 win = ctx->current; 18137 layout = win->layout; 18138 18139 ret.x += -layout->at_x + (float)*layout->offset_x; 18140 ret.y += -layout->at_y + (float)*layout->offset_y; 18141 return ret; 18142 } 18143 NK_LIB void 18144 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win) 18145 { 18146 struct nk_panel *layout = win->layout; 18147 struct nk_vec2 spacing = ctx->style.window.spacing; 18148 const float row_height = layout->row.height - spacing.y; 18149 nk_panel_layout(ctx, win, row_height, layout->row.columns); 18150 } 18151 NK_LIB void 18152 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, 18153 struct nk_window *win, int modify) 18154 { 18155 struct nk_panel *layout; 18156 const struct nk_style *style; 18157 18158 struct nk_vec2 spacing; 18159 struct nk_vec2 padding; 18160 18161 float item_offset = 0; 18162 float item_width = 0; 18163 float item_spacing = 0; 18164 float panel_space = 0; 18165 18166 NK_ASSERT(ctx); 18167 NK_ASSERT(ctx->current); 18168 NK_ASSERT(ctx->current->layout); 18169 if (!ctx || !ctx->current || !ctx->current->layout) 18170 return; 18171 18172 win = ctx->current; 18173 layout = win->layout; 18174 style = &ctx->style; 18175 NK_ASSERT(bounds); 18176 18177 spacing = style->window.spacing; 18178 padding = nk_panel_get_padding(style, layout->type); 18179 panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 18180 layout->bounds.w, layout->row.columns); 18181 18182 #define NK_FRAC(x) (x - (int)x) /* will be used to remove fookin gaps */ 18183 /* calculate the width of one item inside the current layout space */ 18184 switch (layout->row.type) { 18185 case NK_LAYOUT_DYNAMIC_FIXED: { 18186 /* scaling fixed size widgets item width */ 18187 float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns; 18188 item_offset = (float)layout->row.index * w; 18189 item_width = w + NK_FRAC(item_offset); 18190 item_spacing = (float)layout->row.index * spacing.x; 18191 } break; 18192 case NK_LAYOUT_DYNAMIC_ROW: { 18193 /* scaling single ratio widget width */ 18194 float w = layout->row.item_width * panel_space; 18195 item_offset = layout->row.item_offset; 18196 item_width = w + NK_FRAC(item_offset); 18197 item_spacing = 0; 18198 18199 if (modify) { 18200 layout->row.item_offset += w + spacing.x; 18201 layout->row.filled += layout->row.item_width; 18202 layout->row.index = 0; 18203 } 18204 } break; 18205 case NK_LAYOUT_DYNAMIC_FREE: { 18206 /* panel width depended free widget placing */ 18207 bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x); 18208 bounds->x -= (float)*layout->offset_x; 18209 bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); 18210 bounds->y -= (float)*layout->offset_y; 18211 bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x); 18212 bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y); 18213 return; 18214 } 18215 case NK_LAYOUT_DYNAMIC: { 18216 /* scaling arrays of panel width ratios for every widget */ 18217 float ratio, w; 18218 NK_ASSERT(layout->row.ratio); 18219 ratio = (layout->row.ratio[layout->row.index] < 0) ? 18220 layout->row.item_width : layout->row.ratio[layout->row.index]; 18221 18222 w = (ratio * panel_space); 18223 item_spacing = (float)layout->row.index * spacing.x; 18224 item_offset = layout->row.item_offset; 18225 item_width = w + NK_FRAC(item_offset); 18226 18227 if (modify) { 18228 layout->row.item_offset += w; 18229 layout->row.filled += ratio; 18230 } 18231 } break; 18232 case NK_LAYOUT_STATIC_FIXED: { 18233 /* non-scaling fixed widgets item width */ 18234 item_width = layout->row.item_width; 18235 item_offset = (float)layout->row.index * item_width; 18236 item_spacing = (float)layout->row.index * spacing.x; 18237 } break; 18238 case NK_LAYOUT_STATIC_ROW: { 18239 /* scaling single ratio widget width */ 18240 item_width = layout->row.item_width; 18241 item_offset = layout->row.item_offset; 18242 item_spacing = (float)layout->row.index * spacing.x; 18243 if (modify) layout->row.item_offset += item_width; 18244 } break; 18245 case NK_LAYOUT_STATIC_FREE: { 18246 /* free widget placing */ 18247 bounds->x = layout->at_x + layout->row.item.x; 18248 bounds->w = layout->row.item.w; 18249 if (((bounds->x + bounds->w) > layout->max_x) && modify) 18250 layout->max_x = (bounds->x + bounds->w); 18251 bounds->x -= (float)*layout->offset_x; 18252 bounds->y = layout->at_y + layout->row.item.y; 18253 bounds->y -= (float)*layout->offset_y; 18254 bounds->h = layout->row.item.h; 18255 return; 18256 } 18257 case NK_LAYOUT_STATIC: { 18258 /* non-scaling array of panel pixel width for every widget */ 18259 item_spacing = (float)layout->row.index * spacing.x; 18260 item_width = layout->row.ratio[layout->row.index]; 18261 item_offset = layout->row.item_offset; 18262 if (modify) layout->row.item_offset += item_width; 18263 } break; 18264 case NK_LAYOUT_TEMPLATE: { 18265 /* stretchy row layout with combined dynamic/static widget width*/ 18266 float w; 18267 NK_ASSERT(layout->row.index < layout->row.columns); 18268 NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 18269 w = layout->row.templates[layout->row.index]; 18270 item_offset = layout->row.item_offset; 18271 item_width = w + NK_FRAC(item_offset); 18272 item_spacing = (float)layout->row.index * spacing.x; 18273 if (modify) layout->row.item_offset += w; 18274 } break; 18275 #undef NK_FRAC 18276 default: NK_ASSERT(0); break; 18277 }; 18278 18279 /* set the bounds of the newly allocated widget */ 18280 bounds->w = item_width; 18281 bounds->h = layout->row.height - spacing.y; 18282 bounds->y = layout->at_y - (float)*layout->offset_y; 18283 bounds->x = layout->at_x + item_offset + item_spacing + padding.x; 18284 if (((bounds->x + bounds->w) > layout->max_x) && modify) 18285 layout->max_x = bounds->x + bounds->w; 18286 bounds->x -= (float)*layout->offset_x; 18287 } 18288 NK_LIB void 18289 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx) 18290 { 18291 struct nk_window *win; 18292 struct nk_panel *layout; 18293 18294 NK_ASSERT(ctx); 18295 NK_ASSERT(ctx->current); 18296 NK_ASSERT(ctx->current->layout); 18297 if (!ctx || !ctx->current || !ctx->current->layout) 18298 return; 18299 18300 /* check if the end of the row has been hit and begin new row if so */ 18301 win = ctx->current; 18302 layout = win->layout; 18303 if (layout->row.index >= layout->row.columns) 18304 nk_panel_alloc_row(ctx, win); 18305 18306 /* calculate widget position and size */ 18307 nk_layout_widget_space(bounds, ctx, win, nk_true); 18308 layout->row.index++; 18309 } 18310 NK_LIB void 18311 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx) 18312 { 18313 float y; 18314 int index; 18315 struct nk_window *win; 18316 struct nk_panel *layout; 18317 18318 NK_ASSERT(ctx); 18319 NK_ASSERT(ctx->current); 18320 NK_ASSERT(ctx->current->layout); 18321 if (!ctx || !ctx->current || !ctx->current->layout) 18322 return; 18323 18324 win = ctx->current; 18325 layout = win->layout; 18326 y = layout->at_y; 18327 index = layout->row.index; 18328 if (layout->row.index >= layout->row.columns) { 18329 layout->at_y += layout->row.height; 18330 layout->row.index = 0; 18331 } 18332 nk_layout_widget_space(bounds, ctx, win, nk_false); 18333 if (!layout->row.index) { 18334 bounds->x -= layout->row.item_offset; 18335 } 18336 layout->at_y = y; 18337 layout->row.index = index; 18338 } 18339 18340 18341 18342 18343 18344 /* =============================================================== 18345 * 18346 * TREE 18347 * 18348 * ===============================================================*/ 18349 NK_INTERN int 18350 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type, 18351 struct nk_image *img, const char *title, enum nk_collapse_states *state) 18352 { 18353 struct nk_window *win; 18354 struct nk_panel *layout; 18355 const struct nk_style *style; 18356 struct nk_command_buffer *out; 18357 const struct nk_input *in; 18358 const struct nk_style_button *button; 18359 enum nk_symbol_type symbol; 18360 float row_height; 18361 18362 struct nk_vec2 item_spacing; 18363 struct nk_rect header = {0,0,0,0}; 18364 struct nk_rect sym = {0,0,0,0}; 18365 struct nk_text text; 18366 18367 nk_flags ws = 0; 18368 enum nk_widget_layout_states widget_state; 18369 18370 NK_ASSERT(ctx); 18371 NK_ASSERT(ctx->current); 18372 NK_ASSERT(ctx->current->layout); 18373 if (!ctx || !ctx->current || !ctx->current->layout) 18374 return 0; 18375 18376 /* cache some data */ 18377 win = ctx->current; 18378 layout = win->layout; 18379 out = &win->buffer; 18380 style = &ctx->style; 18381 item_spacing = style->window.spacing; 18382 18383 /* calculate header bounds and draw background */ 18384 row_height = style->font->height + 2 * style->tab.padding.y; 18385 nk_layout_set_min_row_height(ctx, row_height); 18386 nk_layout_row_dynamic(ctx, row_height, 1); 18387 nk_layout_reset_min_row_height(ctx); 18388 18389 widget_state = nk_widget(&header, ctx); 18390 if (type == NK_TREE_TAB) { 18391 const struct nk_style_item *background = &style->tab.background; 18392 if (background->type == NK_STYLE_ITEM_IMAGE) { 18393 nk_draw_image(out, header, &background->data.image, nk_white); 18394 text.background = nk_rgba(0,0,0,0); 18395 } else { 18396 text.background = background->data.color; 18397 nk_fill_rect(out, header, 0, style->tab.border_color); 18398 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 18399 style->tab.rounding, background->data.color); 18400 } 18401 } else text.background = style->window.background; 18402 18403 /* update node state */ 18404 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 18405 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 18406 if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT)) 18407 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED; 18408 18409 /* select correct button style */ 18410 if (*state == NK_MAXIMIZED) { 18411 symbol = style->tab.sym_maximize; 18412 if (type == NK_TREE_TAB) 18413 button = &style->tab.tab_maximize_button; 18414 else button = &style->tab.node_maximize_button; 18415 } else { 18416 symbol = style->tab.sym_minimize; 18417 if (type == NK_TREE_TAB) 18418 button = &style->tab.tab_minimize_button; 18419 else button = &style->tab.node_minimize_button; 18420 } 18421 18422 {/* draw triangle button */ 18423 sym.w = sym.h = style->font->height; 18424 sym.y = header.y + style->tab.padding.y; 18425 sym.x = header.x + style->tab.padding.x; 18426 nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, 18427 button, 0, style->font); 18428 18429 if (img) { 18430 /* draw optional image icon */ 18431 sym.x = sym.x + sym.w + 4 * item_spacing.x; 18432 nk_draw_image(&win->buffer, sym, img, nk_white); 18433 sym.w = style->font->height + style->tab.spacing.x;} 18434 } 18435 18436 {/* draw label */ 18437 struct nk_rect label; 18438 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 18439 label.x = sym.x + sym.w + item_spacing.x; 18440 label.y = sym.y; 18441 label.w = header.w - (sym.w + item_spacing.y + style->tab.indent); 18442 label.h = style->font->height; 18443 text.text = style->tab.text; 18444 text.padding = nk_vec2(0,0); 18445 nk_widget_text(out, label, title, nk_strlen(title), &text, 18446 NK_TEXT_LEFT, style->font);} 18447 18448 /* increase x-axis cursor widget position pointer */ 18449 if (*state == NK_MAXIMIZED) { 18450 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 18451 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 18452 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 18453 layout->row.tree_depth++; 18454 return nk_true; 18455 } else return nk_false; 18456 } 18457 NK_INTERN int 18458 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type, 18459 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 18460 const char *hash, int len, int line) 18461 { 18462 struct nk_window *win = ctx->current; 18463 int title_len = 0; 18464 nk_hash tree_hash = 0; 18465 nk_uint *state = 0; 18466 18467 /* retrieve tree state from internal widget state tables */ 18468 if (!hash) { 18469 title_len = (int)nk_strlen(title); 18470 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 18471 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 18472 state = nk_find_value(win, tree_hash); 18473 if (!state) { 18474 state = nk_add_value(ctx, win, tree_hash, 0); 18475 *state = initial_state; 18476 } 18477 return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state); 18478 } 18479 NK_API int 18480 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type, 18481 const char *title, enum nk_collapse_states *state) 18482 { 18483 return nk_tree_state_base(ctx, type, 0, title, state); 18484 } 18485 NK_API int 18486 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type, 18487 struct nk_image img, const char *title, enum nk_collapse_states *state) 18488 { 18489 return nk_tree_state_base(ctx, type, &img, title, state); 18490 } 18491 NK_API void 18492 nk_tree_state_pop(struct nk_context *ctx) 18493 { 18494 struct nk_window *win = 0; 18495 struct nk_panel *layout = 0; 18496 18497 NK_ASSERT(ctx); 18498 NK_ASSERT(ctx->current); 18499 NK_ASSERT(ctx->current->layout); 18500 if (!ctx || !ctx->current || !ctx->current->layout) 18501 return; 18502 18503 win = ctx->current; 18504 layout = win->layout; 18505 layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x; 18506 layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x; 18507 NK_ASSERT(layout->row.tree_depth); 18508 layout->row.tree_depth--; 18509 } 18510 NK_API int 18511 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18512 const char *title, enum nk_collapse_states initial_state, 18513 const char *hash, int len, int line) 18514 { 18515 return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line); 18516 } 18517 NK_API int 18518 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18519 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 18520 const char *hash, int len,int seed) 18521 { 18522 return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed); 18523 } 18524 NK_API void 18525 nk_tree_pop(struct nk_context *ctx) 18526 { 18527 nk_tree_state_pop(ctx); 18528 } 18529 NK_INTERN int 18530 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type, 18531 struct nk_image *img, const char *title, int title_len, 18532 enum nk_collapse_states *state, int *selected) 18533 { 18534 struct nk_window *win; 18535 struct nk_panel *layout; 18536 const struct nk_style *style; 18537 struct nk_command_buffer *out; 18538 const struct nk_input *in; 18539 const struct nk_style_button *button; 18540 enum nk_symbol_type symbol; 18541 float row_height; 18542 struct nk_vec2 padding; 18543 18544 int text_len; 18545 float text_width; 18546 18547 struct nk_vec2 item_spacing; 18548 struct nk_rect header = {0,0,0,0}; 18549 struct nk_rect sym = {0,0,0,0}; 18550 struct nk_text text; 18551 18552 nk_flags ws = 0; 18553 enum nk_widget_layout_states widget_state; 18554 18555 NK_ASSERT(ctx); 18556 NK_ASSERT(ctx->current); 18557 NK_ASSERT(ctx->current->layout); 18558 if (!ctx || !ctx->current || !ctx->current->layout) 18559 return 0; 18560 18561 /* cache some data */ 18562 win = ctx->current; 18563 layout = win->layout; 18564 out = &win->buffer; 18565 style = &ctx->style; 18566 item_spacing = style->window.spacing; 18567 padding = style->selectable.padding; 18568 18569 /* calculate header bounds and draw background */ 18570 row_height = style->font->height + 2 * style->tab.padding.y; 18571 nk_layout_set_min_row_height(ctx, row_height); 18572 nk_layout_row_dynamic(ctx, row_height, 1); 18573 nk_layout_reset_min_row_height(ctx); 18574 18575 widget_state = nk_widget(&header, ctx); 18576 if (type == NK_TREE_TAB) { 18577 const struct nk_style_item *background = &style->tab.background; 18578 if (background->type == NK_STYLE_ITEM_IMAGE) { 18579 nk_draw_image(out, header, &background->data.image, nk_white); 18580 text.background = nk_rgba(0,0,0,0); 18581 } else { 18582 text.background = background->data.color; 18583 nk_fill_rect(out, header, 0, style->tab.border_color); 18584 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 18585 style->tab.rounding, background->data.color); 18586 } 18587 } else text.background = style->window.background; 18588 18589 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 18590 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 18591 18592 /* select correct button style */ 18593 if (*state == NK_MAXIMIZED) { 18594 symbol = style->tab.sym_maximize; 18595 if (type == NK_TREE_TAB) 18596 button = &style->tab.tab_maximize_button; 18597 else button = &style->tab.node_maximize_button; 18598 } else { 18599 symbol = style->tab.sym_minimize; 18600 if (type == NK_TREE_TAB) 18601 button = &style->tab.tab_minimize_button; 18602 else button = &style->tab.node_minimize_button; 18603 } 18604 {/* draw triangle button */ 18605 sym.w = sym.h = style->font->height; 18606 sym.y = header.y + style->tab.padding.y; 18607 sym.x = header.x + style->tab.padding.x; 18608 if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font)) 18609 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;} 18610 18611 /* draw label */ 18612 {nk_flags dummy = 0; 18613 struct nk_rect label; 18614 /* calculate size of the text and tooltip */ 18615 text_len = nk_strlen(title); 18616 text_width = style->font->width(style->font->userdata, style->font->height, title, text_len); 18617 text_width += (4 * padding.x); 18618 18619 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 18620 label.x = sym.x + sym.w + item_spacing.x; 18621 label.y = sym.y; 18622 label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width); 18623 label.h = style->font->height; 18624 18625 if (img) { 18626 nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 18627 selected, img, &style->selectable, in, style->font); 18628 } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 18629 selected, &style->selectable, in, style->font); 18630 } 18631 /* increase x-axis cursor widget position pointer */ 18632 if (*state == NK_MAXIMIZED) { 18633 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 18634 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 18635 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 18636 layout->row.tree_depth++; 18637 return nk_true; 18638 } else return nk_false; 18639 } 18640 NK_INTERN int 18641 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type, 18642 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 18643 int *selected, const char *hash, int len, int line) 18644 { 18645 struct nk_window *win = ctx->current; 18646 int title_len = 0; 18647 nk_hash tree_hash = 0; 18648 nk_uint *state = 0; 18649 18650 /* retrieve tree state from internal widget state tables */ 18651 if (!hash) { 18652 title_len = (int)nk_strlen(title); 18653 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 18654 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 18655 state = nk_find_value(win, tree_hash); 18656 if (!state) { 18657 state = nk_add_value(ctx, win, tree_hash, 0); 18658 *state = initial_state; 18659 } return nk_tree_element_image_push_hashed_base(ctx, type, img, title, 18660 nk_strlen(title), (enum nk_collapse_states*)state, selected); 18661 } 18662 NK_API int 18663 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18664 const char *title, enum nk_collapse_states initial_state, 18665 int *selected, const char *hash, int len, int seed) 18666 { 18667 return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed); 18668 } 18669 NK_API int 18670 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18671 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 18672 int *selected, const char *hash, int len,int seed) 18673 { 18674 return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed); 18675 } 18676 NK_API void 18677 nk_tree_element_pop(struct nk_context *ctx) 18678 { 18679 nk_tree_state_pop(ctx); 18680 } 18681 18682 18683 18684 18685 18686 /* =============================================================== 18687 * 18688 * GROUP 18689 * 18690 * ===============================================================*/ 18691 NK_API int 18692 nk_group_scrolled_offset_begin(struct nk_context *ctx, 18693 nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags) 18694 { 18695 struct nk_rect bounds; 18696 struct nk_window panel; 18697 struct nk_window *win; 18698 18699 win = ctx->current; 18700 nk_panel_alloc_space(&bounds, ctx); 18701 {const struct nk_rect *c = &win->layout->clip; 18702 if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) && 18703 !(flags & NK_WINDOW_MOVABLE)) { 18704 return 0; 18705 }} 18706 if (win->flags & NK_WINDOW_ROM) 18707 flags |= NK_WINDOW_ROM; 18708 18709 /* initialize a fake window to create the panel from */ 18710 nk_zero(&panel, sizeof(panel)); 18711 panel.bounds = bounds; 18712 panel.flags = flags; 18713 panel.scrollbar.x = *x_offset; 18714 panel.scrollbar.y = *y_offset; 18715 panel.buffer = win->buffer; 18716 panel.layout = (struct nk_panel*)nk_create_panel(ctx); 18717 ctx->current = &panel; 18718 nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP); 18719 18720 win->buffer = panel.buffer; 18721 win->buffer.clip = panel.layout->clip; 18722 panel.layout->offset_x = x_offset; 18723 panel.layout->offset_y = y_offset; 18724 panel.layout->parent = win->layout; 18725 win->layout = panel.layout; 18726 18727 ctx->current = win; 18728 if ((panel.layout->flags & NK_WINDOW_CLOSED) || 18729 (panel.layout->flags & NK_WINDOW_MINIMIZED)) 18730 { 18731 nk_flags f = panel.layout->flags; 18732 nk_group_scrolled_end(ctx); 18733 if (f & NK_WINDOW_CLOSED) 18734 return NK_WINDOW_CLOSED; 18735 if (f & NK_WINDOW_MINIMIZED) 18736 return NK_WINDOW_MINIMIZED; 18737 } 18738 return 1; 18739 } 18740 NK_API void 18741 nk_group_scrolled_end(struct nk_context *ctx) 18742 { 18743 struct nk_window *win; 18744 struct nk_panel *parent; 18745 struct nk_panel *g; 18746 18747 struct nk_rect clip; 18748 struct nk_window pan; 18749 struct nk_vec2 panel_padding; 18750 18751 NK_ASSERT(ctx); 18752 NK_ASSERT(ctx->current); 18753 if (!ctx || !ctx->current) 18754 return; 18755 18756 /* make sure nk_group_begin was called correctly */ 18757 NK_ASSERT(ctx->current); 18758 win = ctx->current; 18759 NK_ASSERT(win->layout); 18760 g = win->layout; 18761 NK_ASSERT(g->parent); 18762 parent = g->parent; 18763 18764 /* dummy window */ 18765 nk_zero_struct(pan); 18766 panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP); 18767 pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h); 18768 pan.bounds.x = g->bounds.x - panel_padding.x; 18769 pan.bounds.w = g->bounds.w + 2 * panel_padding.x; 18770 pan.bounds.h = g->bounds.h + g->header_height + g->menu.h; 18771 if (g->flags & NK_WINDOW_BORDER) { 18772 pan.bounds.x -= g->border; 18773 pan.bounds.y -= g->border; 18774 pan.bounds.w += 2*g->border; 18775 pan.bounds.h += 2*g->border; 18776 } 18777 if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) { 18778 pan.bounds.w += ctx->style.window.scrollbar_size.x; 18779 pan.bounds.h += ctx->style.window.scrollbar_size.y; 18780 } 18781 pan.scrollbar.x = *g->offset_x; 18782 pan.scrollbar.y = *g->offset_y; 18783 pan.flags = g->flags; 18784 pan.buffer = win->buffer; 18785 pan.layout = g; 18786 pan.parent = win; 18787 ctx->current = &pan; 18788 18789 /* make sure group has correct clipping rectangle */ 18790 nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y, 18791 pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x); 18792 nk_push_scissor(&pan.buffer, clip); 18793 nk_end(ctx); 18794 18795 win->buffer = pan.buffer; 18796 nk_push_scissor(&win->buffer, parent->clip); 18797 ctx->current = win; 18798 win->layout = parent; 18799 g->bounds = pan.bounds; 18800 return; 18801 } 18802 NK_API int 18803 nk_group_scrolled_begin(struct nk_context *ctx, 18804 struct nk_scroll *scroll, const char *title, nk_flags flags) 18805 { 18806 return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags); 18807 } 18808 NK_API int 18809 nk_group_begin_titled(struct nk_context *ctx, const char *id, 18810 const char *title, nk_flags flags) 18811 { 18812 int id_len; 18813 nk_hash id_hash; 18814 struct nk_window *win; 18815 nk_uint *x_offset; 18816 nk_uint *y_offset; 18817 18818 NK_ASSERT(ctx); 18819 NK_ASSERT(id); 18820 NK_ASSERT(ctx->current); 18821 NK_ASSERT(ctx->current->layout); 18822 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18823 return 0; 18824 18825 /* find persistent group scrollbar value */ 18826 win = ctx->current; 18827 id_len = (int)nk_strlen(id); 18828 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18829 x_offset = nk_find_value(win, id_hash); 18830 if (!x_offset) { 18831 x_offset = nk_add_value(ctx, win, id_hash, 0); 18832 y_offset = nk_add_value(ctx, win, id_hash+1, 0); 18833 18834 NK_ASSERT(x_offset); 18835 NK_ASSERT(y_offset); 18836 if (!x_offset || !y_offset) return 0; 18837 *x_offset = *y_offset = 0; 18838 } else y_offset = nk_find_value(win, id_hash+1); 18839 return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 18840 } 18841 NK_API int 18842 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags) 18843 { 18844 return nk_group_begin_titled(ctx, title, title, flags); 18845 } 18846 NK_API void 18847 nk_group_end(struct nk_context *ctx) 18848 { 18849 nk_group_scrolled_end(ctx); 18850 } 18851 NK_API void 18852 nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset) 18853 { 18854 int id_len; 18855 nk_hash id_hash; 18856 struct nk_window *win; 18857 nk_uint *x_offset_ptr; 18858 nk_uint *y_offset_ptr; 18859 18860 NK_ASSERT(ctx); 18861 NK_ASSERT(id); 18862 NK_ASSERT(ctx->current); 18863 NK_ASSERT(ctx->current->layout); 18864 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18865 return; 18866 18867 /* find persistent group scrollbar value */ 18868 win = ctx->current; 18869 id_len = (int)nk_strlen(id); 18870 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18871 x_offset_ptr = nk_find_value(win, id_hash); 18872 if (!x_offset_ptr) { 18873 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); 18874 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); 18875 18876 NK_ASSERT(x_offset_ptr); 18877 NK_ASSERT(y_offset_ptr); 18878 if (!x_offset_ptr || !y_offset_ptr) return; 18879 *x_offset_ptr = *y_offset_ptr = 0; 18880 } else y_offset_ptr = nk_find_value(win, id_hash+1); 18881 if (x_offset) 18882 *x_offset = *x_offset_ptr; 18883 if (y_offset) 18884 *y_offset = *y_offset_ptr; 18885 } 18886 NK_API void 18887 nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset) 18888 { 18889 int id_len; 18890 nk_hash id_hash; 18891 struct nk_window *win; 18892 nk_uint *x_offset_ptr; 18893 nk_uint *y_offset_ptr; 18894 18895 NK_ASSERT(ctx); 18896 NK_ASSERT(id); 18897 NK_ASSERT(ctx->current); 18898 NK_ASSERT(ctx->current->layout); 18899 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18900 return; 18901 18902 /* find persistent group scrollbar value */ 18903 win = ctx->current; 18904 id_len = (int)nk_strlen(id); 18905 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18906 x_offset_ptr = nk_find_value(win, id_hash); 18907 if (!x_offset_ptr) { 18908 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); 18909 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); 18910 18911 NK_ASSERT(x_offset_ptr); 18912 NK_ASSERT(y_offset_ptr); 18913 if (!x_offset_ptr || !y_offset_ptr) return; 18914 *x_offset_ptr = *y_offset_ptr = 0; 18915 } else y_offset_ptr = nk_find_value(win, id_hash+1); 18916 *x_offset_ptr = x_offset; 18917 *y_offset_ptr = y_offset; 18918 } 18919 18920 18921 18922 18923 /* =============================================================== 18924 * 18925 * LIST VIEW 18926 * 18927 * ===============================================================*/ 18928 NK_API int 18929 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view, 18930 const char *title, nk_flags flags, int row_height, int row_count) 18931 { 18932 int title_len; 18933 nk_hash title_hash; 18934 nk_uint *x_offset; 18935 nk_uint *y_offset; 18936 18937 int result; 18938 struct nk_window *win; 18939 struct nk_panel *layout; 18940 const struct nk_style *style; 18941 struct nk_vec2 item_spacing; 18942 18943 NK_ASSERT(ctx); 18944 NK_ASSERT(view); 18945 NK_ASSERT(title); 18946 if (!ctx || !view || !title) return 0; 18947 18948 win = ctx->current; 18949 style = &ctx->style; 18950 item_spacing = style->window.spacing; 18951 row_height += NK_MAX(0, (int)item_spacing.y); 18952 18953 /* find persistent list view scrollbar offset */ 18954 title_len = (int)nk_strlen(title); 18955 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); 18956 x_offset = nk_find_value(win, title_hash); 18957 if (!x_offset) { 18958 x_offset = nk_add_value(ctx, win, title_hash, 0); 18959 y_offset = nk_add_value(ctx, win, title_hash+1, 0); 18960 18961 NK_ASSERT(x_offset); 18962 NK_ASSERT(y_offset); 18963 if (!x_offset || !y_offset) return 0; 18964 *x_offset = *y_offset = 0; 18965 } else y_offset = nk_find_value(win, title_hash+1); 18966 view->scroll_value = *y_offset; 18967 view->scroll_pointer = y_offset; 18968 18969 *y_offset = 0; 18970 result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 18971 win = ctx->current; 18972 layout = win->layout; 18973 18974 view->total_height = row_height * NK_MAX(row_count,1); 18975 view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f); 18976 view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0); 18977 view->count = NK_MIN(view->count, row_count - view->begin); 18978 view->end = view->begin + view->count; 18979 view->ctx = ctx; 18980 return result; 18981 } 18982 NK_API void 18983 nk_list_view_end(struct nk_list_view *view) 18984 { 18985 struct nk_context *ctx; 18986 struct nk_window *win; 18987 struct nk_panel *layout; 18988 18989 NK_ASSERT(view); 18990 NK_ASSERT(view->ctx); 18991 NK_ASSERT(view->scroll_pointer); 18992 if (!view || !view->ctx) return; 18993 18994 ctx = view->ctx; 18995 win = ctx->current; 18996 layout = win->layout; 18997 layout->at_y = layout->bounds.y + (float)view->total_height; 18998 *view->scroll_pointer = *view->scroll_pointer + view->scroll_value; 18999 nk_group_end(view->ctx); 19000 } 19001 19002 19003 19004 19005 19006 /* =============================================================== 19007 * 19008 * WIDGET 19009 * 19010 * ===============================================================*/ 19011 NK_API struct nk_rect 19012 nk_widget_bounds(struct nk_context *ctx) 19013 { 19014 struct nk_rect bounds; 19015 NK_ASSERT(ctx); 19016 NK_ASSERT(ctx->current); 19017 if (!ctx || !ctx->current) 19018 return nk_rect(0,0,0,0); 19019 nk_layout_peek(&bounds, ctx); 19020 return bounds; 19021 } 19022 NK_API struct nk_vec2 19023 nk_widget_position(struct nk_context *ctx) 19024 { 19025 struct nk_rect bounds; 19026 NK_ASSERT(ctx); 19027 NK_ASSERT(ctx->current); 19028 if (!ctx || !ctx->current) 19029 return nk_vec2(0,0); 19030 19031 nk_layout_peek(&bounds, ctx); 19032 return nk_vec2(bounds.x, bounds.y); 19033 } 19034 NK_API struct nk_vec2 19035 nk_widget_size(struct nk_context *ctx) 19036 { 19037 struct nk_rect bounds; 19038 NK_ASSERT(ctx); 19039 NK_ASSERT(ctx->current); 19040 if (!ctx || !ctx->current) 19041 return nk_vec2(0,0); 19042 19043 nk_layout_peek(&bounds, ctx); 19044 return nk_vec2(bounds.w, bounds.h); 19045 } 19046 NK_API float 19047 nk_widget_width(struct nk_context *ctx) 19048 { 19049 struct nk_rect bounds; 19050 NK_ASSERT(ctx); 19051 NK_ASSERT(ctx->current); 19052 if (!ctx || !ctx->current) 19053 return 0; 19054 19055 nk_layout_peek(&bounds, ctx); 19056 return bounds.w; 19057 } 19058 NK_API float 19059 nk_widget_height(struct nk_context *ctx) 19060 { 19061 struct nk_rect bounds; 19062 NK_ASSERT(ctx); 19063 NK_ASSERT(ctx->current); 19064 if (!ctx || !ctx->current) 19065 return 0; 19066 19067 nk_layout_peek(&bounds, ctx); 19068 return bounds.h; 19069 } 19070 NK_API int 19071 nk_widget_is_hovered(struct nk_context *ctx) 19072 { 19073 struct nk_rect c, v; 19074 struct nk_rect bounds; 19075 NK_ASSERT(ctx); 19076 NK_ASSERT(ctx->current); 19077 if (!ctx || !ctx->current || ctx->active != ctx->current) 19078 return 0; 19079 19080 c = ctx->current->layout->clip; 19081 c.x = (float)((int)c.x); 19082 c.y = (float)((int)c.y); 19083 c.w = (float)((int)c.w); 19084 c.h = (float)((int)c.h); 19085 19086 nk_layout_peek(&bounds, ctx); 19087 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 19088 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 19089 return 0; 19090 return nk_input_is_mouse_hovering_rect(&ctx->input, bounds); 19091 } 19092 NK_API int 19093 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn) 19094 { 19095 struct nk_rect c, v; 19096 struct nk_rect bounds; 19097 NK_ASSERT(ctx); 19098 NK_ASSERT(ctx->current); 19099 if (!ctx || !ctx->current || ctx->active != ctx->current) 19100 return 0; 19101 19102 c = ctx->current->layout->clip; 19103 c.x = (float)((int)c.x); 19104 c.y = (float)((int)c.y); 19105 c.w = (float)((int)c.w); 19106 c.h = (float)((int)c.h); 19107 19108 nk_layout_peek(&bounds, ctx); 19109 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 19110 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 19111 return 0; 19112 return nk_input_mouse_clicked(&ctx->input, btn, bounds); 19113 } 19114 NK_API int 19115 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down) 19116 { 19117 struct nk_rect c, v; 19118 struct nk_rect bounds; 19119 NK_ASSERT(ctx); 19120 NK_ASSERT(ctx->current); 19121 if (!ctx || !ctx->current || ctx->active != ctx->current) 19122 return 0; 19123 19124 c = ctx->current->layout->clip; 19125 c.x = (float)((int)c.x); 19126 c.y = (float)((int)c.y); 19127 c.w = (float)((int)c.w); 19128 c.h = (float)((int)c.h); 19129 19130 nk_layout_peek(&bounds, ctx); 19131 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 19132 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 19133 return 0; 19134 return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down); 19135 } 19136 NK_API enum nk_widget_layout_states 19137 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx) 19138 { 19139 struct nk_rect c, v; 19140 struct nk_window *win; 19141 struct nk_panel *layout; 19142 const struct nk_input *in; 19143 19144 NK_ASSERT(ctx); 19145 NK_ASSERT(ctx->current); 19146 NK_ASSERT(ctx->current->layout); 19147 if (!ctx || !ctx->current || !ctx->current->layout) 19148 return NK_WIDGET_INVALID; 19149 19150 /* allocate space and check if the widget needs to be updated and drawn */ 19151 nk_panel_alloc_space(bounds, ctx); 19152 win = ctx->current; 19153 layout = win->layout; 19154 in = &ctx->input; 19155 c = layout->clip; 19156 19157 /* if one of these triggers you forgot to add an `if` condition around either 19158 a window, group, popup, combobox or contextual menu `begin` and `end` block. 19159 Example: 19160 if (nk_begin(...) {...} nk_end(...); or 19161 if (nk_group_begin(...) { nk_group_end(...);} */ 19162 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 19163 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 19164 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 19165 19166 /* need to convert to int here to remove floating point errors */ 19167 bounds->x = (float)((int)bounds->x); 19168 bounds->y = (float)((int)bounds->y); 19169 bounds->w = (float)((int)bounds->w); 19170 bounds->h = (float)((int)bounds->h); 19171 19172 c.x = (float)((int)c.x); 19173 c.y = (float)((int)c.y); 19174 c.w = (float)((int)c.w); 19175 c.h = (float)((int)c.h); 19176 19177 nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h); 19178 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h)) 19179 return NK_WIDGET_INVALID; 19180 if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h)) 19181 return NK_WIDGET_ROM; 19182 return NK_WIDGET_VALID; 19183 } 19184 NK_API enum nk_widget_layout_states 19185 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx, 19186 struct nk_vec2 item_padding) 19187 { 19188 /* update the bounds to stand without padding */ 19189 struct nk_window *win; 19190 struct nk_style *style; 19191 struct nk_panel *layout; 19192 enum nk_widget_layout_states state; 19193 struct nk_vec2 panel_padding; 19194 19195 NK_ASSERT(ctx); 19196 NK_ASSERT(ctx->current); 19197 NK_ASSERT(ctx->current->layout); 19198 if (!ctx || !ctx->current || !ctx->current->layout) 19199 return NK_WIDGET_INVALID; 19200 19201 win = ctx->current; 19202 style = &ctx->style; 19203 layout = win->layout; 19204 state = nk_widget(bounds, ctx); 19205 19206 panel_padding = nk_panel_get_padding(style, layout->type); 19207 if (layout->row.index == 1) { 19208 bounds->w += panel_padding.x; 19209 bounds->x -= panel_padding.x; 19210 } else bounds->x -= item_padding.x; 19211 19212 if (layout->row.index == layout->row.columns) 19213 bounds->w += panel_padding.x; 19214 else bounds->w += item_padding.x; 19215 return state; 19216 } 19217 NK_API void 19218 nk_spacing(struct nk_context *ctx, int cols) 19219 { 19220 struct nk_window *win; 19221 struct nk_panel *layout; 19222 struct nk_rect none; 19223 int i, index, rows; 19224 19225 NK_ASSERT(ctx); 19226 NK_ASSERT(ctx->current); 19227 NK_ASSERT(ctx->current->layout); 19228 if (!ctx || !ctx->current || !ctx->current->layout) 19229 return; 19230 19231 /* spacing over row boundaries */ 19232 win = ctx->current; 19233 layout = win->layout; 19234 index = (layout->row.index + cols) % layout->row.columns; 19235 rows = (layout->row.index + cols) / layout->row.columns; 19236 if (rows) { 19237 for (i = 0; i < rows; ++i) 19238 nk_panel_alloc_row(ctx, win); 19239 cols = index; 19240 } 19241 /* non table layout need to allocate space */ 19242 if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED && 19243 layout->row.type != NK_LAYOUT_STATIC_FIXED) { 19244 for (i = 0; i < cols; ++i) 19245 nk_panel_alloc_space(&none, ctx); 19246 } layout->row.index = index; 19247 } 19248 19249 19250 19251 19252 19253 /* =============================================================== 19254 * 19255 * TEXT 19256 * 19257 * ===============================================================*/ 19258 NK_LIB void 19259 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, 19260 const char *string, int len, const struct nk_text *t, 19261 nk_flags a, const struct nk_user_font *f) 19262 { 19263 struct nk_rect label; 19264 float text_width; 19265 19266 NK_ASSERT(o); 19267 NK_ASSERT(t); 19268 if (!o || !t) return; 19269 19270 b.h = NK_MAX(b.h, 2 * t->padding.y); 19271 label.x = 0; label.w = 0; 19272 label.y = b.y + t->padding.y; 19273 label.h = NK_MIN(f->height, b.h - 2 * t->padding.y); 19274 19275 text_width = f->width(f->userdata, f->height, (const char*)string, len); 19276 text_width += (2.0f * t->padding.x); 19277 19278 /* align in x-axis */ 19279 if (a & NK_TEXT_ALIGN_LEFT) { 19280 label.x = b.x + t->padding.x; 19281 label.w = NK_MAX(0, b.w - 2 * t->padding.x); 19282 } else if (a & NK_TEXT_ALIGN_CENTERED) { 19283 label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width); 19284 label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); 19285 label.x = NK_MAX(b.x + t->padding.x, label.x); 19286 label.w = NK_MIN(b.x + b.w, label.x + label.w); 19287 if (label.w >= label.x) label.w -= label.x; 19288 } else if (a & NK_TEXT_ALIGN_RIGHT) { 19289 label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); 19290 label.w = (float)text_width + 2 * t->padding.x; 19291 } else return; 19292 19293 /* align in y-axis */ 19294 if (a & NK_TEXT_ALIGN_MIDDLE) { 19295 label.y = b.y + b.h/2.0f - (float)f->height/2.0f; 19296 label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f)); 19297 } else if (a & NK_TEXT_ALIGN_BOTTOM) { 19298 label.y = b.y + b.h - f->height; 19299 label.h = f->height; 19300 } 19301 nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text); 19302 } 19303 NK_LIB void 19304 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, 19305 const char *string, int len, const struct nk_text *t, 19306 const struct nk_user_font *f) 19307 { 19308 float width; 19309 int glyphs = 0; 19310 int fitting = 0; 19311 int done = 0; 19312 struct nk_rect line; 19313 struct nk_text text; 19314 NK_INTERN nk_rune seperator[] = {' '}; 19315 19316 NK_ASSERT(o); 19317 NK_ASSERT(t); 19318 if (!o || !t) return; 19319 19320 text.padding = nk_vec2(0,0); 19321 text.background = t->background; 19322 text.text = t->text; 19323 19324 b.w = NK_MAX(b.w, 2 * t->padding.x); 19325 b.h = NK_MAX(b.h, 2 * t->padding.y); 19326 b.h = b.h - 2 * t->padding.y; 19327 19328 line.x = b.x + t->padding.x; 19329 line.y = b.y + t->padding.y; 19330 line.w = b.w - 2 * t->padding.x; 19331 line.h = 2 * t->padding.y + f->height; 19332 19333 fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 19334 while (done < len) { 19335 if (!fitting || line.y + line.h >= (b.y + b.h)) break; 19336 nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f); 19337 done += fitting; 19338 line.y += f->height + 2 * t->padding.y; 19339 fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 19340 } 19341 } 19342 NK_API void 19343 nk_text_colored(struct nk_context *ctx, const char *str, int len, 19344 nk_flags alignment, struct nk_color color) 19345 { 19346 struct nk_window *win; 19347 const struct nk_style *style; 19348 19349 struct nk_vec2 item_padding; 19350 struct nk_rect bounds; 19351 struct nk_text text; 19352 19353 NK_ASSERT(ctx); 19354 NK_ASSERT(ctx->current); 19355 NK_ASSERT(ctx->current->layout); 19356 if (!ctx || !ctx->current || !ctx->current->layout) return; 19357 19358 win = ctx->current; 19359 style = &ctx->style; 19360 nk_panel_alloc_space(&bounds, ctx); 19361 item_padding = style->text.padding; 19362 19363 text.padding.x = item_padding.x; 19364 text.padding.y = item_padding.y; 19365 text.background = style->window.background; 19366 text.text = color; 19367 nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font); 19368 } 19369 NK_API void 19370 nk_text_wrap_colored(struct nk_context *ctx, const char *str, 19371 int len, struct nk_color color) 19372 { 19373 struct nk_window *win; 19374 const struct nk_style *style; 19375 19376 struct nk_vec2 item_padding; 19377 struct nk_rect bounds; 19378 struct nk_text text; 19379 19380 NK_ASSERT(ctx); 19381 NK_ASSERT(ctx->current); 19382 NK_ASSERT(ctx->current->layout); 19383 if (!ctx || !ctx->current || !ctx->current->layout) return; 19384 19385 win = ctx->current; 19386 style = &ctx->style; 19387 nk_panel_alloc_space(&bounds, ctx); 19388 item_padding = style->text.padding; 19389 19390 text.padding.x = item_padding.x; 19391 text.padding.y = item_padding.y; 19392 text.background = style->window.background; 19393 text.text = color; 19394 nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font); 19395 } 19396 #ifdef NK_INCLUDE_STANDARD_VARARGS 19397 NK_API void 19398 nk_labelf_colored(struct nk_context *ctx, nk_flags flags, 19399 struct nk_color color, const char *fmt, ...) 19400 { 19401 va_list args; 19402 va_start(args, fmt); 19403 nk_labelfv_colored(ctx, flags, color, fmt, args); 19404 va_end(args); 19405 } 19406 NK_API void 19407 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color, 19408 const char *fmt, ...) 19409 { 19410 va_list args; 19411 va_start(args, fmt); 19412 nk_labelfv_colored_wrap(ctx, color, fmt, args); 19413 va_end(args); 19414 } 19415 NK_API void 19416 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...) 19417 { 19418 va_list args; 19419 va_start(args, fmt); 19420 nk_labelfv(ctx, flags, fmt, args); 19421 va_end(args); 19422 } 19423 NK_API void 19424 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...) 19425 { 19426 va_list args; 19427 va_start(args, fmt); 19428 nk_labelfv_wrap(ctx, fmt, args); 19429 va_end(args); 19430 } 19431 NK_API void 19432 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags, 19433 struct nk_color color, const char *fmt, va_list args) 19434 { 19435 char buf[256]; 19436 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19437 nk_label_colored(ctx, buf, flags, color); 19438 } 19439 19440 NK_API void 19441 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color, 19442 const char *fmt, va_list args) 19443 { 19444 char buf[256]; 19445 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19446 nk_label_colored_wrap(ctx, buf, color); 19447 } 19448 19449 NK_API void 19450 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args) 19451 { 19452 char buf[256]; 19453 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19454 nk_label(ctx, buf, flags); 19455 } 19456 19457 NK_API void 19458 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args) 19459 { 19460 char buf[256]; 19461 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19462 nk_label_wrap(ctx, buf); 19463 } 19464 19465 NK_API void 19466 nk_value_bool(struct nk_context *ctx, const char *prefix, int value) 19467 { 19468 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false")); 19469 } 19470 NK_API void 19471 nk_value_int(struct nk_context *ctx, const char *prefix, int value) 19472 { 19473 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value); 19474 } 19475 NK_API void 19476 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value) 19477 { 19478 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value); 19479 } 19480 NK_API void 19481 nk_value_float(struct nk_context *ctx, const char *prefix, float value) 19482 { 19483 double double_value = (double)value; 19484 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value); 19485 } 19486 NK_API void 19487 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c) 19488 { 19489 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a); 19490 } 19491 NK_API void 19492 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color) 19493 { 19494 double c[4]; nk_color_dv(c, color); 19495 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)", 19496 p, c[0], c[1], c[2], c[3]); 19497 } 19498 NK_API void 19499 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color) 19500 { 19501 char hex[16]; 19502 nk_color_hex_rgba(hex, color); 19503 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex); 19504 } 19505 #endif 19506 NK_API void 19507 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment) 19508 { 19509 NK_ASSERT(ctx); 19510 if (!ctx) return; 19511 nk_text_colored(ctx, str, len, alignment, ctx->style.text.color); 19512 } 19513 NK_API void 19514 nk_text_wrap(struct nk_context *ctx, const char *str, int len) 19515 { 19516 NK_ASSERT(ctx); 19517 if (!ctx) return; 19518 nk_text_wrap_colored(ctx, str, len, ctx->style.text.color); 19519 } 19520 NK_API void 19521 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment) 19522 { 19523 nk_text(ctx, str, nk_strlen(str), alignment); 19524 } 19525 NK_API void 19526 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align, 19527 struct nk_color color) 19528 { 19529 nk_text_colored(ctx, str, nk_strlen(str), align, color); 19530 } 19531 NK_API void 19532 nk_label_wrap(struct nk_context *ctx, const char *str) 19533 { 19534 nk_text_wrap(ctx, str, nk_strlen(str)); 19535 } 19536 NK_API void 19537 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color) 19538 { 19539 nk_text_wrap_colored(ctx, str, nk_strlen(str), color); 19540 } 19541 19542 19543 19544 19545 19546 /* =============================================================== 19547 * 19548 * IMAGE 19549 * 19550 * ===============================================================*/ 19551 NK_API nk_handle 19552 nk_handle_ptr(void *ptr) 19553 { 19554 nk_handle handle = {0}; 19555 handle.ptr = ptr; 19556 return handle; 19557 } 19558 NK_API nk_handle 19559 nk_handle_id(int id) 19560 { 19561 nk_handle handle; 19562 nk_zero_struct(handle); 19563 handle.id = id; 19564 return handle; 19565 } 19566 NK_API struct nk_image 19567 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r) 19568 { 19569 struct nk_image s; 19570 nk_zero(&s, sizeof(s)); 19571 s.handle.ptr = ptr; 19572 s.w = w; s.h = h; 19573 s.region[0] = (unsigned short)r.x; 19574 s.region[1] = (unsigned short)r.y; 19575 s.region[2] = (unsigned short)r.w; 19576 s.region[3] = (unsigned short)r.h; 19577 return s; 19578 } 19579 NK_API struct nk_image 19580 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r) 19581 { 19582 struct nk_image s; 19583 nk_zero(&s, sizeof(s)); 19584 s.handle.id = id; 19585 s.w = w; s.h = h; 19586 s.region[0] = (unsigned short)r.x; 19587 s.region[1] = (unsigned short)r.y; 19588 s.region[2] = (unsigned short)r.w; 19589 s.region[3] = (unsigned short)r.h; 19590 return s; 19591 } 19592 NK_API struct nk_image 19593 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h, 19594 struct nk_rect r) 19595 { 19596 struct nk_image s; 19597 nk_zero(&s, sizeof(s)); 19598 s.handle = handle; 19599 s.w = w; s.h = h; 19600 s.region[0] = (unsigned short)r.x; 19601 s.region[1] = (unsigned short)r.y; 19602 s.region[2] = (unsigned short)r.w; 19603 s.region[3] = (unsigned short)r.h; 19604 return s; 19605 } 19606 NK_API struct nk_image 19607 nk_image_handle(nk_handle handle) 19608 { 19609 struct nk_image s; 19610 nk_zero(&s, sizeof(s)); 19611 s.handle = handle; 19612 s.w = 0; s.h = 0; 19613 s.region[0] = 0; 19614 s.region[1] = 0; 19615 s.region[2] = 0; 19616 s.region[3] = 0; 19617 return s; 19618 } 19619 NK_API struct nk_image 19620 nk_image_ptr(void *ptr) 19621 { 19622 struct nk_image s; 19623 nk_zero(&s, sizeof(s)); 19624 NK_ASSERT(ptr); 19625 s.handle.ptr = ptr; 19626 s.w = 0; s.h = 0; 19627 s.region[0] = 0; 19628 s.region[1] = 0; 19629 s.region[2] = 0; 19630 s.region[3] = 0; 19631 return s; 19632 } 19633 NK_API struct nk_image 19634 nk_image_id(int id) 19635 { 19636 struct nk_image s; 19637 nk_zero(&s, sizeof(s)); 19638 s.handle.id = id; 19639 s.w = 0; s.h = 0; 19640 s.region[0] = 0; 19641 s.region[1] = 0; 19642 s.region[2] = 0; 19643 s.region[3] = 0; 19644 return s; 19645 } 19646 NK_API int 19647 nk_image_is_subimage(const struct nk_image* img) 19648 { 19649 NK_ASSERT(img); 19650 return !(img->w == 0 && img->h == 0); 19651 } 19652 NK_API void 19653 nk_image(struct nk_context *ctx, struct nk_image img) 19654 { 19655 struct nk_window *win; 19656 struct nk_rect bounds; 19657 19658 NK_ASSERT(ctx); 19659 NK_ASSERT(ctx->current); 19660 NK_ASSERT(ctx->current->layout); 19661 if (!ctx || !ctx->current || !ctx->current->layout) return; 19662 19663 win = ctx->current; 19664 if (!nk_widget(&bounds, ctx)) return; 19665 nk_draw_image(&win->buffer, bounds, &img, nk_white); 19666 } 19667 NK_API void 19668 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col) 19669 { 19670 struct nk_window *win; 19671 struct nk_rect bounds; 19672 19673 NK_ASSERT(ctx); 19674 NK_ASSERT(ctx->current); 19675 NK_ASSERT(ctx->current->layout); 19676 if (!ctx || !ctx->current || !ctx->current->layout) return; 19677 19678 win = ctx->current; 19679 if (!nk_widget(&bounds, ctx)) return; 19680 nk_draw_image(&win->buffer, bounds, &img, col); 19681 } 19682 19683 19684 19685 19686 19687 /* ============================================================== 19688 * 19689 * BUTTON 19690 * 19691 * ===============================================================*/ 19692 NK_LIB void 19693 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, 19694 struct nk_rect content, struct nk_color background, struct nk_color foreground, 19695 float border_width, const struct nk_user_font *font) 19696 { 19697 switch (type) { 19698 case NK_SYMBOL_X: 19699 case NK_SYMBOL_UNDERSCORE: 19700 case NK_SYMBOL_PLUS: 19701 case NK_SYMBOL_MINUS: { 19702 /* single character text symbol */ 19703 const char *X = (type == NK_SYMBOL_X) ? "x": 19704 (type == NK_SYMBOL_UNDERSCORE) ? "_": 19705 (type == NK_SYMBOL_PLUS) ? "+": "-"; 19706 struct nk_text text; 19707 text.padding = nk_vec2(0,0); 19708 text.background = background; 19709 text.text = foreground; 19710 nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font); 19711 } break; 19712 case NK_SYMBOL_CIRCLE_SOLID: 19713 case NK_SYMBOL_CIRCLE_OUTLINE: 19714 case NK_SYMBOL_RECT_SOLID: 19715 case NK_SYMBOL_RECT_OUTLINE: { 19716 /* simple empty/filled shapes */ 19717 if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) { 19718 nk_fill_rect(out, content, 0, foreground); 19719 if (type == NK_SYMBOL_RECT_OUTLINE) 19720 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background); 19721 } else { 19722 nk_fill_circle(out, content, foreground); 19723 if (type == NK_SYMBOL_CIRCLE_OUTLINE) 19724 nk_fill_circle(out, nk_shrink_rect(content, 1), background); 19725 } 19726 } break; 19727 case NK_SYMBOL_TRIANGLE_UP: 19728 case NK_SYMBOL_TRIANGLE_DOWN: 19729 case NK_SYMBOL_TRIANGLE_LEFT: 19730 case NK_SYMBOL_TRIANGLE_RIGHT: { 19731 enum nk_heading heading; 19732 struct nk_vec2 points[3]; 19733 heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT : 19734 (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT: 19735 (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN; 19736 nk_triangle_from_direction(points, content, 0, 0, heading); 19737 nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, 19738 points[2].x, points[2].y, foreground); 19739 } break; 19740 default: 19741 case NK_SYMBOL_NONE: 19742 case NK_SYMBOL_MAX: break; 19743 } 19744 } 19745 NK_LIB int 19746 nk_button_behavior(nk_flags *state, struct nk_rect r, 19747 const struct nk_input *i, enum nk_button_behavior behavior) 19748 { 19749 int ret = 0; 19750 nk_widget_state_reset(state); 19751 if (!i) return 0; 19752 if (nk_input_is_mouse_hovering_rect(i, r)) { 19753 *state = NK_WIDGET_STATE_HOVERED; 19754 if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT)) 19755 *state = NK_WIDGET_STATE_ACTIVE; 19756 if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) { 19757 ret = (behavior != NK_BUTTON_DEFAULT) ? 19758 nk_input_is_mouse_down(i, NK_BUTTON_LEFT): 19759 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 19760 nk_input_is_mouse_released(i, NK_BUTTON_LEFT); 19761 #else 19762 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT); 19763 #endif 19764 } 19765 } 19766 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r)) 19767 *state |= NK_WIDGET_STATE_ENTERED; 19768 else if (nk_input_is_mouse_prev_hovering_rect(i, r)) 19769 *state |= NK_WIDGET_STATE_LEFT; 19770 return ret; 19771 } 19772 NK_LIB const struct nk_style_item* 19773 nk_draw_button(struct nk_command_buffer *out, 19774 const struct nk_rect *bounds, nk_flags state, 19775 const struct nk_style_button *style) 19776 { 19777 const struct nk_style_item *background; 19778 if (state & NK_WIDGET_STATE_HOVER) 19779 background = &style->hover; 19780 else if (state & NK_WIDGET_STATE_ACTIVED) 19781 background = &style->active; 19782 else background = &style->normal; 19783 19784 if (background->type == NK_STYLE_ITEM_IMAGE) { 19785 nk_draw_image(out, *bounds, &background->data.image, nk_white); 19786 } else { 19787 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 19788 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 19789 } 19790 return background; 19791 } 19792 NK_LIB int 19793 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, 19794 const struct nk_style_button *style, const struct nk_input *in, 19795 enum nk_button_behavior behavior, struct nk_rect *content) 19796 { 19797 struct nk_rect bounds; 19798 NK_ASSERT(style); 19799 NK_ASSERT(state); 19800 NK_ASSERT(out); 19801 if (!out || !style) 19802 return nk_false; 19803 19804 /* calculate button content space */ 19805 content->x = r.x + style->padding.x + style->border + style->rounding; 19806 content->y = r.y + style->padding.y + style->border + style->rounding; 19807 content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2); 19808 content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2); 19809 19810 /* execute button behavior */ 19811 bounds.x = r.x - style->touch_padding.x; 19812 bounds.y = r.y - style->touch_padding.y; 19813 bounds.w = r.w + 2 * style->touch_padding.x; 19814 bounds.h = r.h + 2 * style->touch_padding.y; 19815 return nk_button_behavior(state, bounds, in, behavior); 19816 } 19817 NK_LIB void 19818 nk_draw_button_text(struct nk_command_buffer *out, 19819 const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, 19820 const struct nk_style_button *style, const char *txt, int len, 19821 nk_flags text_alignment, const struct nk_user_font *font) 19822 { 19823 struct nk_text text; 19824 const struct nk_style_item *background; 19825 background = nk_draw_button(out, bounds, state, style); 19826 19827 /* select correct colors/images */ 19828 if (background->type == NK_STYLE_ITEM_COLOR) 19829 text.background = background->data.color; 19830 else text.background = style->text_background; 19831 if (state & NK_WIDGET_STATE_HOVER) 19832 text.text = style->text_hover; 19833 else if (state & NK_WIDGET_STATE_ACTIVED) 19834 text.text = style->text_active; 19835 else text.text = style->text_normal; 19836 19837 text.padding = nk_vec2(0,0); 19838 nk_widget_text(out, *content, txt, len, &text, text_alignment, font); 19839 } 19840 NK_LIB int 19841 nk_do_button_text(nk_flags *state, 19842 struct nk_command_buffer *out, struct nk_rect bounds, 19843 const char *string, int len, nk_flags align, enum nk_button_behavior behavior, 19844 const struct nk_style_button *style, const struct nk_input *in, 19845 const struct nk_user_font *font) 19846 { 19847 struct nk_rect content; 19848 int ret = nk_false; 19849 19850 NK_ASSERT(state); 19851 NK_ASSERT(style); 19852 NK_ASSERT(out); 19853 NK_ASSERT(string); 19854 NK_ASSERT(font); 19855 if (!out || !style || !font || !string) 19856 return nk_false; 19857 19858 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19859 if (style->draw_begin) style->draw_begin(out, style->userdata); 19860 nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font); 19861 if (style->draw_end) style->draw_end(out, style->userdata); 19862 return ret; 19863 } 19864 NK_LIB void 19865 nk_draw_button_symbol(struct nk_command_buffer *out, 19866 const struct nk_rect *bounds, const struct nk_rect *content, 19867 nk_flags state, const struct nk_style_button *style, 19868 enum nk_symbol_type type, const struct nk_user_font *font) 19869 { 19870 struct nk_color sym, bg; 19871 const struct nk_style_item *background; 19872 19873 /* select correct colors/images */ 19874 background = nk_draw_button(out, bounds, state, style); 19875 if (background->type == NK_STYLE_ITEM_COLOR) 19876 bg = background->data.color; 19877 else bg = style->text_background; 19878 19879 if (state & NK_WIDGET_STATE_HOVER) 19880 sym = style->text_hover; 19881 else if (state & NK_WIDGET_STATE_ACTIVED) 19882 sym = style->text_active; 19883 else sym = style->text_normal; 19884 nk_draw_symbol(out, type, *content, bg, sym, 1, font); 19885 } 19886 NK_LIB int 19887 nk_do_button_symbol(nk_flags *state, 19888 struct nk_command_buffer *out, struct nk_rect bounds, 19889 enum nk_symbol_type symbol, enum nk_button_behavior behavior, 19890 const struct nk_style_button *style, const struct nk_input *in, 19891 const struct nk_user_font *font) 19892 { 19893 int ret; 19894 struct nk_rect content; 19895 19896 NK_ASSERT(state); 19897 NK_ASSERT(style); 19898 NK_ASSERT(font); 19899 NK_ASSERT(out); 19900 if (!out || !style || !font || !state) 19901 return nk_false; 19902 19903 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19904 if (style->draw_begin) style->draw_begin(out, style->userdata); 19905 nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); 19906 if (style->draw_end) style->draw_end(out, style->userdata); 19907 return ret; 19908 } 19909 NK_LIB void 19910 nk_draw_button_image(struct nk_command_buffer *out, 19911 const struct nk_rect *bounds, const struct nk_rect *content, 19912 nk_flags state, const struct nk_style_button *style, const struct nk_image *img) 19913 { 19914 nk_draw_button(out, bounds, state, style); 19915 nk_draw_image(out, *content, img, nk_white); 19916 } 19917 NK_LIB int 19918 nk_do_button_image(nk_flags *state, 19919 struct nk_command_buffer *out, struct nk_rect bounds, 19920 struct nk_image img, enum nk_button_behavior b, 19921 const struct nk_style_button *style, const struct nk_input *in) 19922 { 19923 int ret; 19924 struct nk_rect content; 19925 19926 NK_ASSERT(state); 19927 NK_ASSERT(style); 19928 NK_ASSERT(out); 19929 if (!out || !style || !state) 19930 return nk_false; 19931 19932 ret = nk_do_button(state, out, bounds, style, in, b, &content); 19933 content.x += style->image_padding.x; 19934 content.y += style->image_padding.y; 19935 content.w -= 2 * style->image_padding.x; 19936 content.h -= 2 * style->image_padding.y; 19937 19938 if (style->draw_begin) style->draw_begin(out, style->userdata); 19939 nk_draw_button_image(out, &bounds, &content, *state, style, &img); 19940 if (style->draw_end) style->draw_end(out, style->userdata); 19941 return ret; 19942 } 19943 NK_LIB void 19944 nk_draw_button_text_symbol(struct nk_command_buffer *out, 19945 const struct nk_rect *bounds, const struct nk_rect *label, 19946 const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, 19947 const char *str, int len, enum nk_symbol_type type, 19948 const struct nk_user_font *font) 19949 { 19950 struct nk_color sym; 19951 struct nk_text text; 19952 const struct nk_style_item *background; 19953 19954 /* select correct background colors/images */ 19955 background = nk_draw_button(out, bounds, state, style); 19956 if (background->type == NK_STYLE_ITEM_COLOR) 19957 text.background = background->data.color; 19958 else text.background = style->text_background; 19959 19960 /* select correct text colors */ 19961 if (state & NK_WIDGET_STATE_HOVER) { 19962 sym = style->text_hover; 19963 text.text = style->text_hover; 19964 } else if (state & NK_WIDGET_STATE_ACTIVED) { 19965 sym = style->text_active; 19966 text.text = style->text_active; 19967 } else { 19968 sym = style->text_normal; 19969 text.text = style->text_normal; 19970 } 19971 19972 text.padding = nk_vec2(0,0); 19973 nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); 19974 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 19975 } 19976 NK_LIB int 19977 nk_do_button_text_symbol(nk_flags *state, 19978 struct nk_command_buffer *out, struct nk_rect bounds, 19979 enum nk_symbol_type symbol, const char *str, int len, nk_flags align, 19980 enum nk_button_behavior behavior, const struct nk_style_button *style, 19981 const struct nk_user_font *font, const struct nk_input *in) 19982 { 19983 int ret; 19984 struct nk_rect tri = {0,0,0,0}; 19985 struct nk_rect content; 19986 19987 NK_ASSERT(style); 19988 NK_ASSERT(out); 19989 NK_ASSERT(font); 19990 if (!out || !style || !font) 19991 return nk_false; 19992 19993 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19994 tri.y = content.y + (content.h/2) - font->height/2; 19995 tri.w = font->height; tri.h = font->height; 19996 if (align & NK_TEXT_ALIGN_LEFT) { 19997 tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); 19998 tri.x = NK_MAX(tri.x, 0); 19999 } else tri.x = content.x + 2 * style->padding.x; 20000 20001 /* draw button */ 20002 if (style->draw_begin) style->draw_begin(out, style->userdata); 20003 nk_draw_button_text_symbol(out, &bounds, &content, &tri, 20004 *state, style, str, len, symbol, font); 20005 if (style->draw_end) style->draw_end(out, style->userdata); 20006 return ret; 20007 } 20008 NK_LIB void 20009 nk_draw_button_text_image(struct nk_command_buffer *out, 20010 const struct nk_rect *bounds, const struct nk_rect *label, 20011 const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, 20012 const char *str, int len, const struct nk_user_font *font, 20013 const struct nk_image *img) 20014 { 20015 struct nk_text text; 20016 const struct nk_style_item *background; 20017 background = nk_draw_button(out, bounds, state, style); 20018 20019 /* select correct colors */ 20020 if (background->type == NK_STYLE_ITEM_COLOR) 20021 text.background = background->data.color; 20022 else text.background = style->text_background; 20023 if (state & NK_WIDGET_STATE_HOVER) 20024 text.text = style->text_hover; 20025 else if (state & NK_WIDGET_STATE_ACTIVED) 20026 text.text = style->text_active; 20027 else text.text = style->text_normal; 20028 20029 text.padding = nk_vec2(0,0); 20030 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 20031 nk_draw_image(out, *image, img, nk_white); 20032 } 20033 NK_LIB int 20034 nk_do_button_text_image(nk_flags *state, 20035 struct nk_command_buffer *out, struct nk_rect bounds, 20036 struct nk_image img, const char* str, int len, nk_flags align, 20037 enum nk_button_behavior behavior, const struct nk_style_button *style, 20038 const struct nk_user_font *font, const struct nk_input *in) 20039 { 20040 int ret; 20041 struct nk_rect icon; 20042 struct nk_rect content; 20043 20044 NK_ASSERT(style); 20045 NK_ASSERT(state); 20046 NK_ASSERT(font); 20047 NK_ASSERT(out); 20048 if (!out || !font || !style || !str) 20049 return nk_false; 20050 20051 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 20052 icon.y = bounds.y + style->padding.y; 20053 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20054 if (align & NK_TEXT_ALIGN_LEFT) { 20055 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20056 icon.x = NK_MAX(icon.x, 0); 20057 } else icon.x = bounds.x + 2 * style->padding.x; 20058 20059 icon.x += style->image_padding.x; 20060 icon.y += style->image_padding.y; 20061 icon.w -= 2 * style->image_padding.x; 20062 icon.h -= 2 * style->image_padding.y; 20063 20064 if (style->draw_begin) style->draw_begin(out, style->userdata); 20065 nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img); 20066 if (style->draw_end) style->draw_end(out, style->userdata); 20067 return ret; 20068 } 20069 NK_API void 20070 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 20071 { 20072 NK_ASSERT(ctx); 20073 if (!ctx) return; 20074 ctx->button_behavior = behavior; 20075 } 20076 NK_API int 20077 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 20078 { 20079 struct nk_config_stack_button_behavior *button_stack; 20080 struct nk_config_stack_button_behavior_element *element; 20081 20082 NK_ASSERT(ctx); 20083 if (!ctx) return 0; 20084 20085 button_stack = &ctx->stacks.button_behaviors; 20086 NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements)); 20087 if (button_stack->head >= (int)NK_LEN(button_stack->elements)) 20088 return 0; 20089 20090 element = &button_stack->elements[button_stack->head++]; 20091 element->address = &ctx->button_behavior; 20092 element->old_value = ctx->button_behavior; 20093 ctx->button_behavior = behavior; 20094 return 1; 20095 } 20096 NK_API int 20097 nk_button_pop_behavior(struct nk_context *ctx) 20098 { 20099 struct nk_config_stack_button_behavior *button_stack; 20100 struct nk_config_stack_button_behavior_element *element; 20101 20102 NK_ASSERT(ctx); 20103 if (!ctx) return 0; 20104 20105 button_stack = &ctx->stacks.button_behaviors; 20106 NK_ASSERT(button_stack->head > 0); 20107 if (button_stack->head < 1) 20108 return 0; 20109 20110 element = &button_stack->elements[--button_stack->head]; 20111 *element->address = element->old_value; 20112 return 1; 20113 } 20114 NK_API int 20115 nk_button_text_styled(struct nk_context *ctx, 20116 const struct nk_style_button *style, const char *title, int len) 20117 { 20118 struct nk_window *win; 20119 struct nk_panel *layout; 20120 const struct nk_input *in; 20121 20122 struct nk_rect bounds; 20123 enum nk_widget_layout_states state; 20124 20125 NK_ASSERT(ctx); 20126 NK_ASSERT(style); 20127 NK_ASSERT(ctx->current); 20128 NK_ASSERT(ctx->current->layout); 20129 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0; 20130 20131 win = ctx->current; 20132 layout = win->layout; 20133 state = nk_widget(&bounds, ctx); 20134 20135 if (!state) return 0; 20136 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20137 return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 20138 title, len, style->text_alignment, ctx->button_behavior, 20139 style, in, ctx->style.font); 20140 } 20141 NK_API int 20142 nk_button_text(struct nk_context *ctx, const char *title, int len) 20143 { 20144 NK_ASSERT(ctx); 20145 if (!ctx) return 0; 20146 return nk_button_text_styled(ctx, &ctx->style.button, title, len); 20147 } 20148 NK_API int nk_button_label_styled(struct nk_context *ctx, 20149 const struct nk_style_button *style, const char *title) 20150 { 20151 return nk_button_text_styled(ctx, style, title, nk_strlen(title)); 20152 } 20153 NK_API int nk_button_label(struct nk_context *ctx, const char *title) 20154 { 20155 return nk_button_text(ctx, title, nk_strlen(title)); 20156 } 20157 NK_API int 20158 nk_button_color(struct nk_context *ctx, struct nk_color color) 20159 { 20160 struct nk_window *win; 20161 struct nk_panel *layout; 20162 const struct nk_input *in; 20163 struct nk_style_button button; 20164 20165 int ret = 0; 20166 struct nk_rect bounds; 20167 struct nk_rect content; 20168 enum nk_widget_layout_states state; 20169 20170 NK_ASSERT(ctx); 20171 NK_ASSERT(ctx->current); 20172 NK_ASSERT(ctx->current->layout); 20173 if (!ctx || !ctx->current || !ctx->current->layout) 20174 return 0; 20175 20176 win = ctx->current; 20177 layout = win->layout; 20178 20179 state = nk_widget(&bounds, ctx); 20180 if (!state) return 0; 20181 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20182 20183 button = ctx->style.button; 20184 button.normal = nk_style_item_color(color); 20185 button.hover = nk_style_item_color(color); 20186 button.active = nk_style_item_color(color); 20187 ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds, 20188 &button, in, ctx->button_behavior, &content); 20189 nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); 20190 return ret; 20191 } 20192 NK_API int 20193 nk_button_symbol_styled(struct nk_context *ctx, 20194 const struct nk_style_button *style, enum nk_symbol_type symbol) 20195 { 20196 struct nk_window *win; 20197 struct nk_panel *layout; 20198 const struct nk_input *in; 20199 20200 struct nk_rect bounds; 20201 enum nk_widget_layout_states state; 20202 20203 NK_ASSERT(ctx); 20204 NK_ASSERT(ctx->current); 20205 NK_ASSERT(ctx->current->layout); 20206 if (!ctx || !ctx->current || !ctx->current->layout) 20207 return 0; 20208 20209 win = ctx->current; 20210 layout = win->layout; 20211 state = nk_widget(&bounds, ctx); 20212 if (!state) return 0; 20213 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20214 return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20215 symbol, ctx->button_behavior, style, in, ctx->style.font); 20216 } 20217 NK_API int 20218 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol) 20219 { 20220 NK_ASSERT(ctx); 20221 if (!ctx) return 0; 20222 return nk_button_symbol_styled(ctx, &ctx->style.button, symbol); 20223 } 20224 NK_API int 20225 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style, 20226 struct nk_image img) 20227 { 20228 struct nk_window *win; 20229 struct nk_panel *layout; 20230 const struct nk_input *in; 20231 20232 struct nk_rect bounds; 20233 enum nk_widget_layout_states state; 20234 20235 NK_ASSERT(ctx); 20236 NK_ASSERT(ctx->current); 20237 NK_ASSERT(ctx->current->layout); 20238 if (!ctx || !ctx->current || !ctx->current->layout) 20239 return 0; 20240 20241 win = ctx->current; 20242 layout = win->layout; 20243 20244 state = nk_widget(&bounds, ctx); 20245 if (!state) return 0; 20246 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20247 return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, 20248 img, ctx->button_behavior, style, in); 20249 } 20250 NK_API int 20251 nk_button_image(struct nk_context *ctx, struct nk_image img) 20252 { 20253 NK_ASSERT(ctx); 20254 if (!ctx) return 0; 20255 return nk_button_image_styled(ctx, &ctx->style.button, img); 20256 } 20257 NK_API int 20258 nk_button_symbol_text_styled(struct nk_context *ctx, 20259 const struct nk_style_button *style, enum nk_symbol_type symbol, 20260 const char *text, int len, nk_flags align) 20261 { 20262 struct nk_window *win; 20263 struct nk_panel *layout; 20264 const struct nk_input *in; 20265 20266 struct nk_rect bounds; 20267 enum nk_widget_layout_states state; 20268 20269 NK_ASSERT(ctx); 20270 NK_ASSERT(ctx->current); 20271 NK_ASSERT(ctx->current->layout); 20272 if (!ctx || !ctx->current || !ctx->current->layout) 20273 return 0; 20274 20275 win = ctx->current; 20276 layout = win->layout; 20277 20278 state = nk_widget(&bounds, ctx); 20279 if (!state) return 0; 20280 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20281 return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20282 symbol, text, len, align, ctx->button_behavior, 20283 style, ctx->style.font, in); 20284 } 20285 NK_API int 20286 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 20287 const char* text, int len, nk_flags align) 20288 { 20289 NK_ASSERT(ctx); 20290 if (!ctx) return 0; 20291 return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align); 20292 } 20293 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 20294 const char *label, nk_flags align) 20295 { 20296 return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align); 20297 } 20298 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, 20299 const struct nk_style_button *style, enum nk_symbol_type symbol, 20300 const char *title, nk_flags align) 20301 { 20302 return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align); 20303 } 20304 NK_API int 20305 nk_button_image_text_styled(struct nk_context *ctx, 20306 const struct nk_style_button *style, struct nk_image img, const char *text, 20307 int len, nk_flags align) 20308 { 20309 struct nk_window *win; 20310 struct nk_panel *layout; 20311 const struct nk_input *in; 20312 20313 struct nk_rect bounds; 20314 enum nk_widget_layout_states state; 20315 20316 NK_ASSERT(ctx); 20317 NK_ASSERT(ctx->current); 20318 NK_ASSERT(ctx->current->layout); 20319 if (!ctx || !ctx->current || !ctx->current->layout) 20320 return 0; 20321 20322 win = ctx->current; 20323 layout = win->layout; 20324 20325 state = nk_widget(&bounds, ctx); 20326 if (!state) return 0; 20327 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20328 return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 20329 bounds, img, text, len, align, ctx->button_behavior, 20330 style, ctx->style.font, in); 20331 } 20332 NK_API int 20333 nk_button_image_text(struct nk_context *ctx, struct nk_image img, 20334 const char *text, int len, nk_flags align) 20335 { 20336 return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align); 20337 } 20338 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img, 20339 const char *label, nk_flags align) 20340 { 20341 return nk_button_image_text(ctx, img, label, nk_strlen(label), align); 20342 } 20343 NK_API int nk_button_image_label_styled(struct nk_context *ctx, 20344 const struct nk_style_button *style, struct nk_image img, 20345 const char *label, nk_flags text_alignment) 20346 { 20347 return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment); 20348 } 20349 20350 20351 20352 20353 20354 /* =============================================================== 20355 * 20356 * TOGGLE 20357 * 20358 * ===============================================================*/ 20359 NK_LIB int 20360 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, 20361 nk_flags *state, int active) 20362 { 20363 nk_widget_state_reset(state); 20364 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) { 20365 *state = NK_WIDGET_STATE_ACTIVE; 20366 active = !active; 20367 } 20368 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select)) 20369 *state |= NK_WIDGET_STATE_ENTERED; 20370 else if (nk_input_is_mouse_prev_hovering_rect(in, select)) 20371 *state |= NK_WIDGET_STATE_LEFT; 20372 return active; 20373 } 20374 NK_LIB void 20375 nk_draw_checkbox(struct nk_command_buffer *out, 20376 nk_flags state, const struct nk_style_toggle *style, int active, 20377 const struct nk_rect *label, const struct nk_rect *selector, 20378 const struct nk_rect *cursors, const char *string, int len, 20379 const struct nk_user_font *font) 20380 { 20381 const struct nk_style_item *background; 20382 const struct nk_style_item *cursor; 20383 struct nk_text text; 20384 20385 /* select correct colors/images */ 20386 if (state & NK_WIDGET_STATE_HOVER) { 20387 background = &style->hover; 20388 cursor = &style->cursor_hover; 20389 text.text = style->text_hover; 20390 } else if (state & NK_WIDGET_STATE_ACTIVED) { 20391 background = &style->hover; 20392 cursor = &style->cursor_hover; 20393 text.text = style->text_active; 20394 } else { 20395 background = &style->normal; 20396 cursor = &style->cursor_normal; 20397 text.text = style->text_normal; 20398 } 20399 20400 /* draw background and cursor */ 20401 if (background->type == NK_STYLE_ITEM_COLOR) { 20402 nk_fill_rect(out, *selector, 0, style->border_color); 20403 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color); 20404 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 20405 if (active) { 20406 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20407 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 20408 else nk_fill_rect(out, *cursors, 0, cursor->data.color); 20409 } 20410 20411 text.padding.x = 0; 20412 text.padding.y = 0; 20413 text.background = style->text_background; 20414 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 20415 } 20416 NK_LIB void 20417 nk_draw_option(struct nk_command_buffer *out, 20418 nk_flags state, const struct nk_style_toggle *style, int active, 20419 const struct nk_rect *label, const struct nk_rect *selector, 20420 const struct nk_rect *cursors, const char *string, int len, 20421 const struct nk_user_font *font) 20422 { 20423 const struct nk_style_item *background; 20424 const struct nk_style_item *cursor; 20425 struct nk_text text; 20426 20427 /* select correct colors/images */ 20428 if (state & NK_WIDGET_STATE_HOVER) { 20429 background = &style->hover; 20430 cursor = &style->cursor_hover; 20431 text.text = style->text_hover; 20432 } else if (state & NK_WIDGET_STATE_ACTIVED) { 20433 background = &style->hover; 20434 cursor = &style->cursor_hover; 20435 text.text = style->text_active; 20436 } else { 20437 background = &style->normal; 20438 cursor = &style->cursor_normal; 20439 text.text = style->text_normal; 20440 } 20441 20442 /* draw background and cursor */ 20443 if (background->type == NK_STYLE_ITEM_COLOR) { 20444 nk_fill_circle(out, *selector, style->border_color); 20445 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color); 20446 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 20447 if (active) { 20448 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20449 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 20450 else nk_fill_circle(out, *cursors, cursor->data.color); 20451 } 20452 20453 text.padding.x = 0; 20454 text.padding.y = 0; 20455 text.background = style->text_background; 20456 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 20457 } 20458 NK_LIB int 20459 nk_do_toggle(nk_flags *state, 20460 struct nk_command_buffer *out, struct nk_rect r, 20461 int *active, const char *str, int len, enum nk_toggle_type type, 20462 const struct nk_style_toggle *style, const struct nk_input *in, 20463 const struct nk_user_font *font) 20464 { 20465 int was_active; 20466 struct nk_rect bounds; 20467 struct nk_rect select; 20468 struct nk_rect cursor; 20469 struct nk_rect label; 20470 20471 NK_ASSERT(style); 20472 NK_ASSERT(out); 20473 NK_ASSERT(font); 20474 if (!out || !style || !font || !active) 20475 return 0; 20476 20477 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x); 20478 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y); 20479 20480 /* add additional touch padding for touch screen devices */ 20481 bounds.x = r.x - style->touch_padding.x; 20482 bounds.y = r.y - style->touch_padding.y; 20483 bounds.w = r.w + 2 * style->touch_padding.x; 20484 bounds.h = r.h + 2 * style->touch_padding.y; 20485 20486 /* calculate the selector space */ 20487 select.w = font->height; 20488 select.h = select.w; 20489 select.y = r.y + r.h/2.0f - select.h/2.0f; 20490 select.x = r.x; 20491 20492 /* calculate the bounds of the cursor inside the selector */ 20493 cursor.x = select.x + style->padding.x + style->border; 20494 cursor.y = select.y + style->padding.y + style->border; 20495 cursor.w = select.w - (2 * style->padding.x + 2 * style->border); 20496 cursor.h = select.h - (2 * style->padding.y + 2 * style->border); 20497 20498 /* label behind the selector */ 20499 label.x = select.x + select.w + style->spacing; 20500 label.y = select.y; 20501 label.w = NK_MAX(r.x + r.w, label.x) - label.x; 20502 label.h = select.w; 20503 20504 /* update selector */ 20505 was_active = *active; 20506 *active = nk_toggle_behavior(in, bounds, state, *active); 20507 20508 /* draw selector */ 20509 if (style->draw_begin) 20510 style->draw_begin(out, style->userdata); 20511 if (type == NK_TOGGLE_CHECK) { 20512 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font); 20513 } else { 20514 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font); 20515 } 20516 if (style->draw_end) 20517 style->draw_end(out, style->userdata); 20518 return (was_active != *active); 20519 } 20520 /*---------------------------------------------------------------- 20521 * 20522 * CHECKBOX 20523 * 20524 * --------------------------------------------------------------*/ 20525 NK_API int 20526 nk_check_text(struct nk_context *ctx, const char *text, int len, int active) 20527 { 20528 struct nk_window *win; 20529 struct nk_panel *layout; 20530 const struct nk_input *in; 20531 const struct nk_style *style; 20532 20533 struct nk_rect bounds; 20534 enum nk_widget_layout_states state; 20535 20536 NK_ASSERT(ctx); 20537 NK_ASSERT(ctx->current); 20538 NK_ASSERT(ctx->current->layout); 20539 if (!ctx || !ctx->current || !ctx->current->layout) 20540 return active; 20541 20542 win = ctx->current; 20543 style = &ctx->style; 20544 layout = win->layout; 20545 20546 state = nk_widget(&bounds, ctx); 20547 if (!state) return active; 20548 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20549 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, 20550 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font); 20551 return active; 20552 } 20553 NK_API unsigned int 20554 nk_check_flags_text(struct nk_context *ctx, const char *text, int len, 20555 unsigned int flags, unsigned int value) 20556 { 20557 int old_active; 20558 NK_ASSERT(ctx); 20559 NK_ASSERT(text); 20560 if (!ctx || !text) return flags; 20561 old_active = (int)((flags & value) & value); 20562 if (nk_check_text(ctx, text, len, old_active)) 20563 flags |= value; 20564 else flags &= ~value; 20565 return flags; 20566 } 20567 NK_API int 20568 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active) 20569 { 20570 int old_val; 20571 NK_ASSERT(ctx); 20572 NK_ASSERT(text); 20573 NK_ASSERT(active); 20574 if (!ctx || !text || !active) return 0; 20575 old_val = *active; 20576 *active = nk_check_text(ctx, text, len, *active); 20577 return old_val != *active; 20578 } 20579 NK_API int 20580 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len, 20581 unsigned int *flags, unsigned int value) 20582 { 20583 int active; 20584 NK_ASSERT(ctx); 20585 NK_ASSERT(text); 20586 NK_ASSERT(flags); 20587 if (!ctx || !text || !flags) return 0; 20588 20589 active = (int)((*flags & value) & value); 20590 if (nk_checkbox_text(ctx, text, len, &active)) { 20591 if (active) *flags |= value; 20592 else *flags &= ~value; 20593 return 1; 20594 } 20595 return 0; 20596 } 20597 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active) 20598 { 20599 return nk_check_text(ctx, label, nk_strlen(label), active); 20600 } 20601 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label, 20602 unsigned int flags, unsigned int value) 20603 { 20604 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value); 20605 } 20606 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active) 20607 { 20608 return nk_checkbox_text(ctx, label, nk_strlen(label), active); 20609 } 20610 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label, 20611 unsigned int *flags, unsigned int value) 20612 { 20613 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value); 20614 } 20615 /*---------------------------------------------------------------- 20616 * 20617 * OPTION 20618 * 20619 * --------------------------------------------------------------*/ 20620 NK_API int 20621 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active) 20622 { 20623 struct nk_window *win; 20624 struct nk_panel *layout; 20625 const struct nk_input *in; 20626 const struct nk_style *style; 20627 20628 struct nk_rect bounds; 20629 enum nk_widget_layout_states state; 20630 20631 NK_ASSERT(ctx); 20632 NK_ASSERT(ctx->current); 20633 NK_ASSERT(ctx->current->layout); 20634 if (!ctx || !ctx->current || !ctx->current->layout) 20635 return is_active; 20636 20637 win = ctx->current; 20638 style = &ctx->style; 20639 layout = win->layout; 20640 20641 state = nk_widget(&bounds, ctx); 20642 if (!state) return (int)state; 20643 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20644 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, 20645 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font); 20646 return is_active; 20647 } 20648 NK_API int 20649 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active) 20650 { 20651 int old_value; 20652 NK_ASSERT(ctx); 20653 NK_ASSERT(text); 20654 NK_ASSERT(active); 20655 if (!ctx || !text || !active) return 0; 20656 old_value = *active; 20657 *active = nk_option_text(ctx, text, len, old_value); 20658 return old_value != *active; 20659 } 20660 NK_API int 20661 nk_option_label(struct nk_context *ctx, const char *label, int active) 20662 { 20663 return nk_option_text(ctx, label, nk_strlen(label), active); 20664 } 20665 NK_API int 20666 nk_radio_label(struct nk_context *ctx, const char *label, int *active) 20667 { 20668 return nk_radio_text(ctx, label, nk_strlen(label), active); 20669 } 20670 20671 20672 20673 20674 20675 /* =============================================================== 20676 * 20677 * SELECTABLE 20678 * 20679 * ===============================================================*/ 20680 NK_LIB void 20681 nk_draw_selectable(struct nk_command_buffer *out, 20682 nk_flags state, const struct nk_style_selectable *style, int active, 20683 const struct nk_rect *bounds, 20684 const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, 20685 const char *string, int len, nk_flags align, const struct nk_user_font *font) 20686 { 20687 const struct nk_style_item *background; 20688 struct nk_text text; 20689 text.padding = style->padding; 20690 20691 /* select correct colors/images */ 20692 if (!active) { 20693 if (state & NK_WIDGET_STATE_ACTIVED) { 20694 background = &style->pressed; 20695 text.text = style->text_pressed; 20696 } else if (state & NK_WIDGET_STATE_HOVER) { 20697 background = &style->hover; 20698 text.text = style->text_hover; 20699 } else { 20700 background = &style->normal; 20701 text.text = style->text_normal; 20702 } 20703 } else { 20704 if (state & NK_WIDGET_STATE_ACTIVED) { 20705 background = &style->pressed_active; 20706 text.text = style->text_pressed_active; 20707 } else if (state & NK_WIDGET_STATE_HOVER) { 20708 background = &style->hover_active; 20709 text.text = style->text_hover_active; 20710 } else { 20711 background = &style->normal_active; 20712 text.text = style->text_normal_active; 20713 } 20714 } 20715 /* draw selectable background and text */ 20716 if (background->type == NK_STYLE_ITEM_IMAGE) { 20717 nk_draw_image(out, *bounds, &background->data.image, nk_white); 20718 text.background = nk_rgba(0,0,0,0); 20719 } else { 20720 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 20721 text.background = background->data.color; 20722 } 20723 if (icon) { 20724 if (img) nk_draw_image(out, *icon, img, nk_white); 20725 else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font); 20726 } 20727 nk_widget_text(out, *bounds, string, len, &text, align, font); 20728 } 20729 NK_LIB int 20730 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, 20731 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20732 const struct nk_style_selectable *style, const struct nk_input *in, 20733 const struct nk_user_font *font) 20734 { 20735 int old_value; 20736 struct nk_rect touch; 20737 20738 NK_ASSERT(state); 20739 NK_ASSERT(out); 20740 NK_ASSERT(str); 20741 NK_ASSERT(len); 20742 NK_ASSERT(value); 20743 NK_ASSERT(style); 20744 NK_ASSERT(font); 20745 20746 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20747 old_value = *value; 20748 20749 /* remove padding */ 20750 touch.x = bounds.x - style->touch_padding.x; 20751 touch.y = bounds.y - style->touch_padding.y; 20752 touch.w = bounds.w + style->touch_padding.x * 2; 20753 touch.h = bounds.h + style->touch_padding.y * 2; 20754 20755 /* update button */ 20756 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20757 *value = !(*value); 20758 20759 /* draw selectable */ 20760 if (style->draw_begin) style->draw_begin(out, style->userdata); 20761 nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font); 20762 if (style->draw_end) style->draw_end(out, style->userdata); 20763 return old_value != *value; 20764 } 20765 NK_LIB int 20766 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, 20767 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20768 const struct nk_image *img, const struct nk_style_selectable *style, 20769 const struct nk_input *in, const struct nk_user_font *font) 20770 { 20771 int old_value; 20772 struct nk_rect touch; 20773 struct nk_rect icon; 20774 20775 NK_ASSERT(state); 20776 NK_ASSERT(out); 20777 NK_ASSERT(str); 20778 NK_ASSERT(len); 20779 NK_ASSERT(value); 20780 NK_ASSERT(style); 20781 NK_ASSERT(font); 20782 20783 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20784 old_value = *value; 20785 20786 /* toggle behavior */ 20787 touch.x = bounds.x - style->touch_padding.x; 20788 touch.y = bounds.y - style->touch_padding.y; 20789 touch.w = bounds.w + style->touch_padding.x * 2; 20790 touch.h = bounds.h + style->touch_padding.y * 2; 20791 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20792 *value = !(*value); 20793 20794 icon.y = bounds.y + style->padding.y; 20795 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20796 if (align & NK_TEXT_ALIGN_LEFT) { 20797 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20798 icon.x = NK_MAX(icon.x, 0); 20799 } else icon.x = bounds.x + 2 * style->padding.x; 20800 20801 icon.x += style->image_padding.x; 20802 icon.y += style->image_padding.y; 20803 icon.w -= 2 * style->image_padding.x; 20804 icon.h -= 2 * style->image_padding.y; 20805 20806 /* draw selectable */ 20807 if (style->draw_begin) style->draw_begin(out, style->userdata); 20808 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font); 20809 if (style->draw_end) style->draw_end(out, style->userdata); 20810 return old_value != *value; 20811 } 20812 NK_LIB int 20813 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out, 20814 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20815 enum nk_symbol_type sym, const struct nk_style_selectable *style, 20816 const struct nk_input *in, const struct nk_user_font *font) 20817 { 20818 int old_value; 20819 struct nk_rect touch; 20820 struct nk_rect icon; 20821 20822 NK_ASSERT(state); 20823 NK_ASSERT(out); 20824 NK_ASSERT(str); 20825 NK_ASSERT(len); 20826 NK_ASSERT(value); 20827 NK_ASSERT(style); 20828 NK_ASSERT(font); 20829 20830 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20831 old_value = *value; 20832 20833 /* toggle behavior */ 20834 touch.x = bounds.x - style->touch_padding.x; 20835 touch.y = bounds.y - style->touch_padding.y; 20836 touch.w = bounds.w + style->touch_padding.x * 2; 20837 touch.h = bounds.h + style->touch_padding.y * 2; 20838 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20839 *value = !(*value); 20840 20841 icon.y = bounds.y + style->padding.y; 20842 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20843 if (align & NK_TEXT_ALIGN_LEFT) { 20844 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20845 icon.x = NK_MAX(icon.x, 0); 20846 } else icon.x = bounds.x + 2 * style->padding.x; 20847 20848 icon.x += style->image_padding.x; 20849 icon.y += style->image_padding.y; 20850 icon.w -= 2 * style->image_padding.x; 20851 icon.h -= 2 * style->image_padding.y; 20852 20853 /* draw selectable */ 20854 if (style->draw_begin) style->draw_begin(out, style->userdata); 20855 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font); 20856 if (style->draw_end) style->draw_end(out, style->userdata); 20857 return old_value != *value; 20858 } 20859 20860 NK_API int 20861 nk_selectable_text(struct nk_context *ctx, const char *str, int len, 20862 nk_flags align, int *value) 20863 { 20864 struct nk_window *win; 20865 struct nk_panel *layout; 20866 const struct nk_input *in; 20867 const struct nk_style *style; 20868 20869 enum nk_widget_layout_states state; 20870 struct nk_rect bounds; 20871 20872 NK_ASSERT(ctx); 20873 NK_ASSERT(value); 20874 NK_ASSERT(ctx->current); 20875 NK_ASSERT(ctx->current->layout); 20876 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20877 return 0; 20878 20879 win = ctx->current; 20880 layout = win->layout; 20881 style = &ctx->style; 20882 20883 state = nk_widget(&bounds, ctx); 20884 if (!state) return 0; 20885 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20886 return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, 20887 str, len, align, value, &style->selectable, in, style->font); 20888 } 20889 NK_API int 20890 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img, 20891 const char *str, int len, nk_flags align, int *value) 20892 { 20893 struct nk_window *win; 20894 struct nk_panel *layout; 20895 const struct nk_input *in; 20896 const struct nk_style *style; 20897 20898 enum nk_widget_layout_states state; 20899 struct nk_rect bounds; 20900 20901 NK_ASSERT(ctx); 20902 NK_ASSERT(value); 20903 NK_ASSERT(ctx->current); 20904 NK_ASSERT(ctx->current->layout); 20905 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20906 return 0; 20907 20908 win = ctx->current; 20909 layout = win->layout; 20910 style = &ctx->style; 20911 20912 state = nk_widget(&bounds, ctx); 20913 if (!state) return 0; 20914 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20915 return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds, 20916 str, len, align, value, &img, &style->selectable, in, style->font); 20917 } 20918 NK_API int 20919 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 20920 const char *str, int len, nk_flags align, int *value) 20921 { 20922 struct nk_window *win; 20923 struct nk_panel *layout; 20924 const struct nk_input *in; 20925 const struct nk_style *style; 20926 20927 enum nk_widget_layout_states state; 20928 struct nk_rect bounds; 20929 20930 NK_ASSERT(ctx); 20931 NK_ASSERT(value); 20932 NK_ASSERT(ctx->current); 20933 NK_ASSERT(ctx->current->layout); 20934 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20935 return 0; 20936 20937 win = ctx->current; 20938 layout = win->layout; 20939 style = &ctx->style; 20940 20941 state = nk_widget(&bounds, ctx); 20942 if (!state) return 0; 20943 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20944 return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20945 str, len, align, value, sym, &style->selectable, in, style->font); 20946 } 20947 NK_API int 20948 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 20949 const char *title, nk_flags align, int *value) 20950 { 20951 return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 20952 } 20953 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len, 20954 nk_flags align, int value) 20955 { 20956 nk_selectable_text(ctx, str, len, align, &value);return value; 20957 } 20958 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value) 20959 { 20960 return nk_selectable_text(ctx, str, nk_strlen(str), align, value); 20961 } 20962 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img, 20963 const char *str, nk_flags align, int *value) 20964 { 20965 return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value); 20966 } 20967 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value) 20968 { 20969 nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value; 20970 } 20971 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img, 20972 const char *str, nk_flags align, int value) 20973 { 20974 nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value; 20975 } 20976 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img, 20977 const char *str, int len, nk_flags align, int value) 20978 { 20979 nk_selectable_image_text(ctx, img, str, len, align, &value);return value; 20980 } 20981 NK_API int 20982 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 20983 const char *title, int title_len, nk_flags align, int value) 20984 { 20985 nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value; 20986 } 20987 NK_API int 20988 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 20989 const char *title, nk_flags align, int value) 20990 { 20991 return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 20992 } 20993 20994 20995 20996 20997 20998 /* =============================================================== 20999 * 21000 * SLIDER 21001 * 21002 * ===============================================================*/ 21003 NK_LIB float 21004 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, 21005 struct nk_rect *visual_cursor, struct nk_input *in, 21006 struct nk_rect bounds, float slider_min, float slider_max, float slider_value, 21007 float slider_step, float slider_steps) 21008 { 21009 int left_mouse_down; 21010 int left_mouse_click_in_cursor; 21011 21012 /* check if visual cursor is being dragged */ 21013 nk_widget_state_reset(state); 21014 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 21015 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 21016 NK_BUTTON_LEFT, *visual_cursor, nk_true); 21017 21018 if (left_mouse_down && left_mouse_click_in_cursor) { 21019 float ratio = 0; 21020 const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f); 21021 const float pxstep = bounds.w / slider_steps; 21022 21023 /* only update value if the next slider step is reached */ 21024 *state = NK_WIDGET_STATE_ACTIVE; 21025 if (NK_ABS(d) >= pxstep) { 21026 const float steps = (float)((int)(NK_ABS(d) / pxstep)); 21027 slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); 21028 slider_value = NK_CLAMP(slider_min, slider_value, slider_max); 21029 ratio = (slider_value - slider_min)/slider_step; 21030 logical_cursor->x = bounds.x + (logical_cursor->w * ratio); 21031 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x; 21032 } 21033 } 21034 21035 /* slider widget state */ 21036 if (nk_input_is_mouse_hovering_rect(in, bounds)) 21037 *state = NK_WIDGET_STATE_HOVERED; 21038 if (*state & NK_WIDGET_STATE_HOVER && 21039 !nk_input_is_mouse_prev_hovering_rect(in, bounds)) 21040 *state |= NK_WIDGET_STATE_ENTERED; 21041 else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) 21042 *state |= NK_WIDGET_STATE_LEFT; 21043 return slider_value; 21044 } 21045 NK_LIB void 21046 nk_draw_slider(struct nk_command_buffer *out, nk_flags state, 21047 const struct nk_style_slider *style, const struct nk_rect *bounds, 21048 const struct nk_rect *visual_cursor, float min, float value, float max) 21049 { 21050 struct nk_rect fill; 21051 struct nk_rect bar; 21052 const struct nk_style_item *background; 21053 21054 /* select correct slider images/colors */ 21055 struct nk_color bar_color; 21056 const struct nk_style_item *cursor; 21057 21058 NK_UNUSED(min); 21059 NK_UNUSED(max); 21060 NK_UNUSED(value); 21061 21062 if (state & NK_WIDGET_STATE_ACTIVED) { 21063 background = &style->active; 21064 bar_color = style->bar_active; 21065 cursor = &style->cursor_active; 21066 } else if (state & NK_WIDGET_STATE_HOVER) { 21067 background = &style->hover; 21068 bar_color = style->bar_hover; 21069 cursor = &style->cursor_hover; 21070 } else { 21071 background = &style->normal; 21072 bar_color = style->bar_normal; 21073 cursor = &style->cursor_normal; 21074 } 21075 /* calculate slider background bar */ 21076 bar.x = bounds->x; 21077 bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12; 21078 bar.w = bounds->w; 21079 bar.h = bounds->h/6; 21080 21081 /* filled background bar style */ 21082 fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x; 21083 fill.x = bar.x; 21084 fill.y = bar.y; 21085 fill.h = bar.h; 21086 21087 /* draw background */ 21088 if (background->type == NK_STYLE_ITEM_IMAGE) { 21089 nk_draw_image(out, *bounds, &background->data.image, nk_white); 21090 } else { 21091 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21092 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21093 } 21094 21095 /* draw slider bar */ 21096 nk_fill_rect(out, bar, style->rounding, bar_color); 21097 nk_fill_rect(out, fill, style->rounding, style->bar_filled); 21098 21099 /* draw cursor */ 21100 if (cursor->type == NK_STYLE_ITEM_IMAGE) 21101 nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white); 21102 else nk_fill_circle(out, *visual_cursor, cursor->data.color); 21103 } 21104 NK_LIB float 21105 nk_do_slider(nk_flags *state, 21106 struct nk_command_buffer *out, struct nk_rect bounds, 21107 float min, float val, float max, float step, 21108 const struct nk_style_slider *style, struct nk_input *in, 21109 const struct nk_user_font *font) 21110 { 21111 float slider_range; 21112 float slider_min; 21113 float slider_max; 21114 float slider_value; 21115 float slider_steps; 21116 float cursor_offset; 21117 21118 struct nk_rect visual_cursor; 21119 struct nk_rect logical_cursor; 21120 21121 NK_ASSERT(style); 21122 NK_ASSERT(out); 21123 if (!out || !style) 21124 return 0; 21125 21126 /* remove padding from slider bounds */ 21127 bounds.x = bounds.x + style->padding.x; 21128 bounds.y = bounds.y + style->padding.y; 21129 bounds.h = NK_MAX(bounds.h, 2*style->padding.y); 21130 bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x); 21131 bounds.w -= 2 * style->padding.x; 21132 bounds.h -= 2 * style->padding.y; 21133 21134 /* optional buttons */ 21135 if (style->show_buttons) { 21136 nk_flags ws; 21137 struct nk_rect button; 21138 button.y = bounds.y; 21139 button.w = bounds.h; 21140 button.h = bounds.h; 21141 21142 /* decrement button */ 21143 button.x = bounds.x; 21144 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT, 21145 &style->dec_button, in, font)) 21146 val -= step; 21147 21148 /* increment button */ 21149 button.x = (bounds.x + bounds.w) - button.w; 21150 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT, 21151 &style->inc_button, in, font)) 21152 val += step; 21153 21154 bounds.x = bounds.x + button.w + style->spacing.x; 21155 bounds.w = bounds.w - (2*button.w + 2*style->spacing.x); 21156 } 21157 21158 /* remove one cursor size to support visual cursor */ 21159 bounds.x += style->cursor_size.x*0.5f; 21160 bounds.w -= style->cursor_size.x; 21161 21162 /* make sure the provided values are correct */ 21163 slider_max = NK_MAX(min, max); 21164 slider_min = NK_MIN(min, max); 21165 slider_value = NK_CLAMP(slider_min, val, slider_max); 21166 slider_range = slider_max - slider_min; 21167 slider_steps = slider_range / step; 21168 cursor_offset = (slider_value - slider_min) / step; 21169 21170 /* calculate cursor 21171 Basically you have two cursors. One for visual representation and interaction 21172 and one for updating the actual cursor value. */ 21173 logical_cursor.h = bounds.h; 21174 logical_cursor.w = bounds.w / slider_steps; 21175 logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset); 21176 logical_cursor.y = bounds.y; 21177 21178 visual_cursor.h = style->cursor_size.y; 21179 visual_cursor.w = style->cursor_size.x; 21180 visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f; 21181 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 21182 21183 slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor, 21184 in, bounds, slider_min, slider_max, slider_value, step, slider_steps); 21185 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 21186 21187 /* draw slider */ 21188 if (style->draw_begin) style->draw_begin(out, style->userdata); 21189 nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max); 21190 if (style->draw_end) style->draw_end(out, style->userdata); 21191 return slider_value; 21192 } 21193 NK_API int 21194 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value, 21195 float value_step) 21196 { 21197 struct nk_window *win; 21198 struct nk_panel *layout; 21199 struct nk_input *in; 21200 const struct nk_style *style; 21201 21202 int ret = 0; 21203 float old_value; 21204 struct nk_rect bounds; 21205 enum nk_widget_layout_states state; 21206 21207 NK_ASSERT(ctx); 21208 NK_ASSERT(ctx->current); 21209 NK_ASSERT(ctx->current->layout); 21210 NK_ASSERT(value); 21211 if (!ctx || !ctx->current || !ctx->current->layout || !value) 21212 return ret; 21213 21214 win = ctx->current; 21215 style = &ctx->style; 21216 layout = win->layout; 21217 21218 state = nk_widget(&bounds, ctx); 21219 if (!state) return ret; 21220 in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21221 21222 old_value = *value; 21223 *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, 21224 old_value, max_value, value_step, &style->slider, in, style->font); 21225 return (old_value > *value || old_value < *value); 21226 } 21227 NK_API float 21228 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step) 21229 { 21230 nk_slider_float(ctx, min, &val, max, step); return val; 21231 } 21232 NK_API int 21233 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step) 21234 { 21235 float value = (float)val; 21236 nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 21237 return (int)value; 21238 } 21239 NK_API int 21240 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) 21241 { 21242 int ret; 21243 float value = (float)*val; 21244 ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 21245 *val = (int)value; 21246 return ret; 21247 } 21248 21249 21250 21251 21252 21253 /* =============================================================== 21254 * 21255 * PROGRESS 21256 * 21257 * ===============================================================*/ 21258 NK_LIB nk_size 21259 nk_progress_behavior(nk_flags *state, struct nk_input *in, 21260 struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable) 21261 { 21262 int left_mouse_down = 0; 21263 int left_mouse_click_in_cursor = 0; 21264 21265 nk_widget_state_reset(state); 21266 if (!in || !modifiable) return value; 21267 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 21268 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 21269 NK_BUTTON_LEFT, cursor, nk_true); 21270 if (nk_input_is_mouse_hovering_rect(in, r)) 21271 *state = NK_WIDGET_STATE_HOVERED; 21272 21273 if (in && left_mouse_down && left_mouse_click_in_cursor) { 21274 if (left_mouse_down && left_mouse_click_in_cursor) { 21275 float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w; 21276 value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max); 21277 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f; 21278 *state |= NK_WIDGET_STATE_ACTIVE; 21279 } 21280 } 21281 /* set progressbar widget state */ 21282 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r)) 21283 *state |= NK_WIDGET_STATE_ENTERED; 21284 else if (nk_input_is_mouse_prev_hovering_rect(in, r)) 21285 *state |= NK_WIDGET_STATE_LEFT; 21286 return value; 21287 } 21288 NK_LIB void 21289 nk_draw_progress(struct nk_command_buffer *out, nk_flags state, 21290 const struct nk_style_progress *style, const struct nk_rect *bounds, 21291 const struct nk_rect *scursor, nk_size value, nk_size max) 21292 { 21293 const struct nk_style_item *background; 21294 const struct nk_style_item *cursor; 21295 21296 NK_UNUSED(max); 21297 NK_UNUSED(value); 21298 21299 /* select correct colors/images to draw */ 21300 if (state & NK_WIDGET_STATE_ACTIVED) { 21301 background = &style->active; 21302 cursor = &style->cursor_active; 21303 } else if (state & NK_WIDGET_STATE_HOVER){ 21304 background = &style->hover; 21305 cursor = &style->cursor_hover; 21306 } else { 21307 background = &style->normal; 21308 cursor = &style->cursor_normal; 21309 } 21310 21311 /* draw background */ 21312 if (background->type == NK_STYLE_ITEM_COLOR) { 21313 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21314 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21315 } else nk_draw_image(out, *bounds, &background->data.image, nk_white); 21316 21317 /* draw cursor */ 21318 if (cursor->type == NK_STYLE_ITEM_COLOR) { 21319 nk_fill_rect(out, *scursor, style->rounding, cursor->data.color); 21320 nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color); 21321 } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white); 21322 } 21323 NK_LIB nk_size 21324 nk_do_progress(nk_flags *state, 21325 struct nk_command_buffer *out, struct nk_rect bounds, 21326 nk_size value, nk_size max, int modifiable, 21327 const struct nk_style_progress *style, struct nk_input *in) 21328 { 21329 float prog_scale; 21330 nk_size prog_value; 21331 struct nk_rect cursor; 21332 21333 NK_ASSERT(style); 21334 NK_ASSERT(out); 21335 if (!out || !style) return 0; 21336 21337 /* calculate progressbar cursor */ 21338 cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); 21339 cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border); 21340 cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border)); 21341 prog_scale = (float)value / (float)max; 21342 21343 /* update progressbar */ 21344 prog_value = NK_MIN(value, max); 21345 prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable); 21346 cursor.w = cursor.w * prog_scale; 21347 21348 /* draw progressbar */ 21349 if (style->draw_begin) style->draw_begin(out, style->userdata); 21350 nk_draw_progress(out, *state, style, &bounds, &cursor, value, max); 21351 if (style->draw_end) style->draw_end(out, style->userdata); 21352 return prog_value; 21353 } 21354 NK_API int 21355 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable) 21356 { 21357 struct nk_window *win; 21358 struct nk_panel *layout; 21359 const struct nk_style *style; 21360 struct nk_input *in; 21361 21362 struct nk_rect bounds; 21363 enum nk_widget_layout_states state; 21364 nk_size old_value; 21365 21366 NK_ASSERT(ctx); 21367 NK_ASSERT(cur); 21368 NK_ASSERT(ctx->current); 21369 NK_ASSERT(ctx->current->layout); 21370 if (!ctx || !ctx->current || !ctx->current->layout || !cur) 21371 return 0; 21372 21373 win = ctx->current; 21374 style = &ctx->style; 21375 layout = win->layout; 21376 state = nk_widget(&bounds, ctx); 21377 if (!state) return 0; 21378 21379 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21380 old_value = *cur; 21381 *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds, 21382 *cur, max, is_modifyable, &style->progress, in); 21383 return (*cur != old_value); 21384 } 21385 NK_API nk_size 21386 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable) 21387 { 21388 nk_progress(ctx, &cur, max, modifyable); 21389 return cur; 21390 } 21391 21392 21393 21394 21395 21396 /* =============================================================== 21397 * 21398 * SCROLLBAR 21399 * 21400 * ===============================================================*/ 21401 NK_LIB float 21402 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, 21403 int has_scrolling, const struct nk_rect *scroll, 21404 const struct nk_rect *cursor, const struct nk_rect *empty0, 21405 const struct nk_rect *empty1, float scroll_offset, 21406 float target, float scroll_step, enum nk_orientation o) 21407 { 21408 nk_flags ws = 0; 21409 int left_mouse_down; 21410 int left_mouse_clicked; 21411 int left_mouse_click_in_cursor; 21412 float scroll_delta; 21413 21414 nk_widget_state_reset(state); 21415 if (!in) return scroll_offset; 21416 21417 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 21418 left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked; 21419 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 21420 NK_BUTTON_LEFT, *cursor, nk_true); 21421 if (nk_input_is_mouse_hovering_rect(in, *scroll)) 21422 *state = NK_WIDGET_STATE_HOVERED; 21423 21424 scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; 21425 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 21426 /* update cursor by mouse dragging */ 21427 float pixel, delta; 21428 *state = NK_WIDGET_STATE_ACTIVE; 21429 if (o == NK_VERTICAL) { 21430 float cursor_y; 21431 pixel = in->mouse.delta.y; 21432 delta = (pixel / scroll->h) * target; 21433 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); 21434 cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); 21435 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; 21436 } else { 21437 float cursor_x; 21438 pixel = in->mouse.delta.x; 21439 delta = (pixel / scroll->w) * target; 21440 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); 21441 cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); 21442 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; 21443 } 21444 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| 21445 nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { 21446 /* scroll page up by click on empty space or shortcut */ 21447 if (o == NK_VERTICAL) 21448 scroll_offset = NK_MAX(0, scroll_offset - scroll->h); 21449 else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); 21450 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || 21451 nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { 21452 /* scroll page down by click on empty space or shortcut */ 21453 if (o == NK_VERTICAL) 21454 scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); 21455 else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); 21456 } else if (has_scrolling) { 21457 if ((scroll_delta < 0 || (scroll_delta > 0))) { 21458 /* update cursor by mouse scrolling */ 21459 scroll_offset = scroll_offset + scroll_step * (-scroll_delta); 21460 if (o == NK_VERTICAL) 21461 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); 21462 else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); 21463 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { 21464 /* update cursor to the beginning */ 21465 if (o == NK_VERTICAL) scroll_offset = 0; 21466 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { 21467 /* update cursor to the end */ 21468 if (o == NK_VERTICAL) scroll_offset = target - scroll->h; 21469 } 21470 } 21471 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 21472 *state |= NK_WIDGET_STATE_ENTERED; 21473 else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 21474 *state |= NK_WIDGET_STATE_LEFT; 21475 return scroll_offset; 21476 } 21477 NK_LIB void 21478 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, 21479 const struct nk_style_scrollbar *style, const struct nk_rect *bounds, 21480 const struct nk_rect *scroll) 21481 { 21482 const struct nk_style_item *background; 21483 const struct nk_style_item *cursor; 21484 21485 /* select correct colors/images to draw */ 21486 if (state & NK_WIDGET_STATE_ACTIVED) { 21487 background = &style->active; 21488 cursor = &style->cursor_active; 21489 } else if (state & NK_WIDGET_STATE_HOVER) { 21490 background = &style->hover; 21491 cursor = &style->cursor_hover; 21492 } else { 21493 background = &style->normal; 21494 cursor = &style->cursor_normal; 21495 } 21496 21497 /* draw background */ 21498 if (background->type == NK_STYLE_ITEM_COLOR) { 21499 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21500 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21501 } else { 21502 nk_draw_image(out, *bounds, &background->data.image, nk_white); 21503 } 21504 21505 /* draw cursor */ 21506 if (cursor->type == NK_STYLE_ITEM_COLOR) { 21507 nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); 21508 nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); 21509 } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white); 21510 } 21511 NK_LIB float 21512 nk_do_scrollbarv(nk_flags *state, 21513 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 21514 float offset, float target, float step, float button_pixel_inc, 21515 const struct nk_style_scrollbar *style, struct nk_input *in, 21516 const struct nk_user_font *font) 21517 { 21518 struct nk_rect empty_north; 21519 struct nk_rect empty_south; 21520 struct nk_rect cursor; 21521 21522 float scroll_step; 21523 float scroll_offset; 21524 float scroll_off; 21525 float scroll_ratio; 21526 21527 NK_ASSERT(out); 21528 NK_ASSERT(style); 21529 NK_ASSERT(state); 21530 if (!out || !style) return 0; 21531 21532 scroll.w = NK_MAX(scroll.w, 1); 21533 scroll.h = NK_MAX(scroll.h, 0); 21534 if (target <= scroll.h) return 0; 21535 21536 /* optional scrollbar buttons */ 21537 if (style->show_buttons) { 21538 nk_flags ws; 21539 float scroll_h; 21540 struct nk_rect button; 21541 21542 button.x = scroll.x; 21543 button.w = scroll.w; 21544 button.h = scroll.w; 21545 21546 scroll_h = NK_MAX(scroll.h - 2 * button.h,0); 21547 scroll_step = NK_MIN(step, button_pixel_inc); 21548 21549 /* decrement button */ 21550 button.y = scroll.y; 21551 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 21552 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 21553 offset = offset - scroll_step; 21554 21555 /* increment button */ 21556 button.y = scroll.y + scroll.h - button.h; 21557 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 21558 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 21559 offset = offset + scroll_step; 21560 21561 scroll.y = scroll.y + button.h; 21562 scroll.h = scroll_h; 21563 } 21564 21565 /* calculate scrollbar constants */ 21566 scroll_step = NK_MIN(step, scroll.h); 21567 scroll_offset = NK_CLAMP(0, offset, target - scroll.h); 21568 scroll_ratio = scroll.h / target; 21569 scroll_off = scroll_offset / target; 21570 21571 /* calculate scrollbar cursor bounds */ 21572 cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0); 21573 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y; 21574 cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x); 21575 cursor.x = scroll.x + style->border + style->padding.x; 21576 21577 /* calculate empty space around cursor */ 21578 empty_north.x = scroll.x; 21579 empty_north.y = scroll.y; 21580 empty_north.w = scroll.w; 21581 empty_north.h = NK_MAX(cursor.y - scroll.y, 0); 21582 21583 empty_south.x = scroll.x; 21584 empty_south.y = cursor.y + cursor.h; 21585 empty_south.w = scroll.w; 21586 empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0); 21587 21588 /* update scrollbar */ 21589 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 21590 &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL); 21591 scroll_off = scroll_offset / target; 21592 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y; 21593 21594 /* draw scrollbar */ 21595 if (style->draw_begin) style->draw_begin(out, style->userdata); 21596 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 21597 if (style->draw_end) style->draw_end(out, style->userdata); 21598 return scroll_offset; 21599 } 21600 NK_LIB float 21601 nk_do_scrollbarh(nk_flags *state, 21602 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 21603 float offset, float target, float step, float button_pixel_inc, 21604 const struct nk_style_scrollbar *style, struct nk_input *in, 21605 const struct nk_user_font *font) 21606 { 21607 struct nk_rect cursor; 21608 struct nk_rect empty_west; 21609 struct nk_rect empty_east; 21610 21611 float scroll_step; 21612 float scroll_offset; 21613 float scroll_off; 21614 float scroll_ratio; 21615 21616 NK_ASSERT(out); 21617 NK_ASSERT(style); 21618 if (!out || !style) return 0; 21619 21620 /* scrollbar background */ 21621 scroll.h = NK_MAX(scroll.h, 1); 21622 scroll.w = NK_MAX(scroll.w, 2 * scroll.h); 21623 if (target <= scroll.w) return 0; 21624 21625 /* optional scrollbar buttons */ 21626 if (style->show_buttons) { 21627 nk_flags ws; 21628 float scroll_w; 21629 struct nk_rect button; 21630 button.y = scroll.y; 21631 button.w = scroll.h; 21632 button.h = scroll.h; 21633 21634 scroll_w = scroll.w - 2 * button.w; 21635 scroll_step = NK_MIN(step, button_pixel_inc); 21636 21637 /* decrement button */ 21638 button.x = scroll.x; 21639 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 21640 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 21641 offset = offset - scroll_step; 21642 21643 /* increment button */ 21644 button.x = scroll.x + scroll.w - button.w; 21645 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 21646 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 21647 offset = offset + scroll_step; 21648 21649 scroll.x = scroll.x + button.w; 21650 scroll.w = scroll_w; 21651 } 21652 21653 /* calculate scrollbar constants */ 21654 scroll_step = NK_MIN(step, scroll.w); 21655 scroll_offset = NK_CLAMP(0, offset, target - scroll.w); 21656 scroll_ratio = scroll.w / target; 21657 scroll_off = scroll_offset / target; 21658 21659 /* calculate cursor bounds */ 21660 cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); 21661 cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; 21662 cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); 21663 cursor.y = scroll.y + style->border + style->padding.y; 21664 21665 /* calculate empty space around cursor */ 21666 empty_west.x = scroll.x; 21667 empty_west.y = scroll.y; 21668 empty_west.w = cursor.x - scroll.x; 21669 empty_west.h = scroll.h; 21670 21671 empty_east.x = cursor.x + cursor.w; 21672 empty_east.y = scroll.y; 21673 empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); 21674 empty_east.h = scroll.h; 21675 21676 /* update scrollbar */ 21677 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 21678 &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); 21679 scroll_off = scroll_offset / target; 21680 cursor.x = scroll.x + (scroll_off * scroll.w); 21681 21682 /* draw scrollbar */ 21683 if (style->draw_begin) style->draw_begin(out, style->userdata); 21684 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 21685 if (style->draw_end) style->draw_end(out, style->userdata); 21686 return scroll_offset; 21687 } 21688 21689 21690 21691 21692 21693 /* =============================================================== 21694 * 21695 * TEXT EDITOR 21696 * 21697 * ===============================================================*/ 21698 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */ 21699 struct nk_text_find { 21700 float x,y; /* position of n'th character */ 21701 float height; /* height of line */ 21702 int first_char, length; /* first char of row, and length */ 21703 int prev_first; /*_ first char of previous row */ 21704 }; 21705 21706 struct nk_text_edit_row { 21707 float x0,x1; 21708 /* starting x location, end x location (allows for align=right, etc) */ 21709 float baseline_y_delta; 21710 /* position of baseline relative to previous row's baseline*/ 21711 float ymin,ymax; 21712 /* height of row above and below baseline */ 21713 int num_chars; 21714 }; 21715 21716 /* forward declarations */ 21717 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int); 21718 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int); 21719 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int); 21720 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) 21721 21722 NK_INTERN float 21723 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id, 21724 const struct nk_user_font *font) 21725 { 21726 int len = 0; 21727 nk_rune unicode = 0; 21728 const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len); 21729 return font->width(font->userdata, font->height, str, len); 21730 } 21731 NK_INTERN void 21732 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit, 21733 int line_start_id, float row_height, const struct nk_user_font *font) 21734 { 21735 int l; 21736 int glyphs = 0; 21737 nk_rune unicode; 21738 const char *remaining; 21739 int len = nk_str_len_char(&edit->string); 21740 const char *end = nk_str_get_const(&edit->string) + len; 21741 const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l); 21742 const struct nk_vec2 size = nk_text_calculate_text_bounds(font, 21743 text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE); 21744 21745 r->x0 = 0.0f; 21746 r->x1 = size.x; 21747 r->baseline_y_delta = size.y; 21748 r->ymin = 0.0f; 21749 r->ymax = size.y; 21750 r->num_chars = glyphs; 21751 } 21752 NK_INTERN int 21753 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y, 21754 const struct nk_user_font *font, float row_height) 21755 { 21756 struct nk_text_edit_row r; 21757 int n = edit->string.len; 21758 float base_y = 0, prev_x; 21759 int i=0, k; 21760 21761 r.x0 = r.x1 = 0; 21762 r.ymin = r.ymax = 0; 21763 r.num_chars = 0; 21764 21765 /* search rows to find one that straddles 'y' */ 21766 while (i < n) { 21767 nk_textedit_layout_row(&r, edit, i, row_height, font); 21768 if (r.num_chars <= 0) 21769 return n; 21770 21771 if (i==0 && y < base_y + r.ymin) 21772 return 0; 21773 21774 if (y < base_y + r.ymax) 21775 break; 21776 21777 i += r.num_chars; 21778 base_y += r.baseline_y_delta; 21779 } 21780 21781 /* below all text, return 'after' last character */ 21782 if (i >= n) 21783 return n; 21784 21785 /* check if it's before the beginning of the line */ 21786 if (x < r.x0) 21787 return i; 21788 21789 /* check if it's before the end of the line */ 21790 if (x < r.x1) { 21791 /* search characters in row for one that straddles 'x' */ 21792 k = i; 21793 prev_x = r.x0; 21794 for (i=0; i < r.num_chars; ++i) { 21795 float w = nk_textedit_get_width(edit, k, i, font); 21796 if (x < prev_x+w) { 21797 if (x < prev_x+w/2) 21798 return k+i; 21799 else return k+i+1; 21800 } 21801 prev_x += w; 21802 } 21803 /* shouldn't happen, but if it does, fall through to end-of-line case */ 21804 } 21805 21806 /* if the last character is a newline, return that. 21807 * otherwise return 'after' the last character */ 21808 if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n') 21809 return i+r.num_chars-1; 21810 else return i+r.num_chars; 21811 } 21812 NK_LIB void 21813 nk_textedit_click(struct nk_text_edit *state, float x, float y, 21814 const struct nk_user_font *font, float row_height) 21815 { 21816 /* API click: on mouse down, move the cursor to the clicked location, 21817 * and reset the selection */ 21818 state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height); 21819 state->select_start = state->cursor; 21820 state->select_end = state->cursor; 21821 state->has_preferred_x = 0; 21822 } 21823 NK_LIB void 21824 nk_textedit_drag(struct nk_text_edit *state, float x, float y, 21825 const struct nk_user_font *font, float row_height) 21826 { 21827 /* API drag: on mouse drag, move the cursor and selection endpoint 21828 * to the clicked location */ 21829 int p = nk_textedit_locate_coord(state, x, y, font, row_height); 21830 if (state->select_start == state->select_end) 21831 state->select_start = state->cursor; 21832 state->cursor = state->select_end = p; 21833 } 21834 NK_INTERN void 21835 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state, 21836 int n, int single_line, const struct nk_user_font *font, float row_height) 21837 { 21838 /* find the x/y location of a character, and remember info about the previous 21839 * row in case we get a move-up event (for page up, we'll have to rescan) */ 21840 struct nk_text_edit_row r; 21841 int prev_start = 0; 21842 int z = state->string.len; 21843 int i=0, first; 21844 21845 nk_zero_struct(r); 21846 if (n == z) { 21847 /* if it's at the end, then find the last line -- simpler than trying to 21848 explicitly handle this case in the regular code */ 21849 nk_textedit_layout_row(&r, state, 0, row_height, font); 21850 if (single_line) { 21851 find->first_char = 0; 21852 find->length = z; 21853 } else { 21854 while (i < z) { 21855 prev_start = i; 21856 i += r.num_chars; 21857 nk_textedit_layout_row(&r, state, i, row_height, font); 21858 } 21859 21860 find->first_char = i; 21861 find->length = r.num_chars; 21862 } 21863 find->x = r.x1; 21864 find->y = r.ymin; 21865 find->height = r.ymax - r.ymin; 21866 find->prev_first = prev_start; 21867 return; 21868 } 21869 21870 /* search rows to find the one that straddles character n */ 21871 find->y = 0; 21872 21873 for(;;) { 21874 nk_textedit_layout_row(&r, state, i, row_height, font); 21875 if (n < i + r.num_chars) break; 21876 prev_start = i; 21877 i += r.num_chars; 21878 find->y += r.baseline_y_delta; 21879 } 21880 21881 find->first_char = first = i; 21882 find->length = r.num_chars; 21883 find->height = r.ymax - r.ymin; 21884 find->prev_first = prev_start; 21885 21886 /* now scan to find xpos */ 21887 find->x = r.x0; 21888 for (i=0; first+i < n; ++i) 21889 find->x += nk_textedit_get_width(state, first, i, font); 21890 } 21891 NK_INTERN void 21892 nk_textedit_clamp(struct nk_text_edit *state) 21893 { 21894 /* make the selection/cursor state valid if client altered the string */ 21895 int n = state->string.len; 21896 if (NK_TEXT_HAS_SELECTION(state)) { 21897 if (state->select_start > n) state->select_start = n; 21898 if (state->select_end > n) state->select_end = n; 21899 /* if clamping forced them to be equal, move the cursor to match */ 21900 if (state->select_start == state->select_end) 21901 state->cursor = state->select_start; 21902 } 21903 if (state->cursor > n) state->cursor = n; 21904 } 21905 NK_API void 21906 nk_textedit_delete(struct nk_text_edit *state, int where, int len) 21907 { 21908 /* delete characters while updating undo */ 21909 nk_textedit_makeundo_delete(state, where, len); 21910 nk_str_delete_runes(&state->string, where, len); 21911 state->has_preferred_x = 0; 21912 } 21913 NK_API void 21914 nk_textedit_delete_selection(struct nk_text_edit *state) 21915 { 21916 /* delete the section */ 21917 nk_textedit_clamp(state); 21918 if (NK_TEXT_HAS_SELECTION(state)) { 21919 if (state->select_start < state->select_end) { 21920 nk_textedit_delete(state, state->select_start, 21921 state->select_end - state->select_start); 21922 state->select_end = state->cursor = state->select_start; 21923 } else { 21924 nk_textedit_delete(state, state->select_end, 21925 state->select_start - state->select_end); 21926 state->select_start = state->cursor = state->select_end; 21927 } 21928 state->has_preferred_x = 0; 21929 } 21930 } 21931 NK_INTERN void 21932 nk_textedit_sortselection(struct nk_text_edit *state) 21933 { 21934 /* canonicalize the selection so start <= end */ 21935 if (state->select_end < state->select_start) { 21936 int temp = state->select_end; 21937 state->select_end = state->select_start; 21938 state->select_start = temp; 21939 } 21940 } 21941 NK_INTERN void 21942 nk_textedit_move_to_first(struct nk_text_edit *state) 21943 { 21944 /* move cursor to first character of selection */ 21945 if (NK_TEXT_HAS_SELECTION(state)) { 21946 nk_textedit_sortselection(state); 21947 state->cursor = state->select_start; 21948 state->select_end = state->select_start; 21949 state->has_preferred_x = 0; 21950 } 21951 } 21952 NK_INTERN void 21953 nk_textedit_move_to_last(struct nk_text_edit *state) 21954 { 21955 /* move cursor to last character of selection */ 21956 if (NK_TEXT_HAS_SELECTION(state)) { 21957 nk_textedit_sortselection(state); 21958 nk_textedit_clamp(state); 21959 state->cursor = state->select_end; 21960 state->select_start = state->select_end; 21961 state->has_preferred_x = 0; 21962 } 21963 } 21964 NK_INTERN int 21965 nk_is_word_boundary( struct nk_text_edit *state, int idx) 21966 { 21967 int len; 21968 nk_rune c; 21969 if (idx <= 0) return 1; 21970 if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1; 21971 return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' || 21972 c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || 21973 c == '|'); 21974 } 21975 NK_INTERN int 21976 nk_textedit_move_to_word_previous(struct nk_text_edit *state) 21977 { 21978 int c = state->cursor - 1; 21979 while( c >= 0 && !nk_is_word_boundary(state, c)) 21980 --c; 21981 21982 if( c < 0 ) 21983 c = 0; 21984 21985 return c; 21986 } 21987 NK_INTERN int 21988 nk_textedit_move_to_word_next(struct nk_text_edit *state) 21989 { 21990 const int len = state->string.len; 21991 int c = state->cursor+1; 21992 while( c < len && !nk_is_word_boundary(state, c)) 21993 ++c; 21994 21995 if( c > len ) 21996 c = len; 21997 21998 return c; 21999 } 22000 NK_INTERN void 22001 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state) 22002 { 22003 /* update selection and cursor to match each other */ 22004 if (!NK_TEXT_HAS_SELECTION(state)) 22005 state->select_start = state->select_end = state->cursor; 22006 else state->cursor = state->select_end; 22007 } 22008 NK_API int 22009 nk_textedit_cut(struct nk_text_edit *state) 22010 { 22011 /* API cut: delete selection */ 22012 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22013 return 0; 22014 if (NK_TEXT_HAS_SELECTION(state)) { 22015 nk_textedit_delete_selection(state); /* implicitly clamps */ 22016 state->has_preferred_x = 0; 22017 return 1; 22018 } 22019 return 0; 22020 } 22021 NK_API int 22022 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len) 22023 { 22024 /* API paste: replace existing selection with passed-in text */ 22025 int glyphs; 22026 const char *text = (const char *) ctext; 22027 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0; 22028 22029 /* if there's a selection, the paste should delete it */ 22030 nk_textedit_clamp(state); 22031 nk_textedit_delete_selection(state); 22032 22033 /* try to insert the characters */ 22034 glyphs = nk_utf_len(ctext, len); 22035 if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) { 22036 nk_textedit_makeundo_insert(state, state->cursor, glyphs); 22037 state->cursor += len; 22038 state->has_preferred_x = 0; 22039 return 1; 22040 } 22041 /* remove the undo since we didn't actually insert the characters */ 22042 if (state->undo.undo_point) 22043 --state->undo.undo_point; 22044 return 0; 22045 } 22046 NK_API void 22047 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len) 22048 { 22049 nk_rune unicode; 22050 int glyph_len; 22051 int text_len = 0; 22052 22053 NK_ASSERT(state); 22054 NK_ASSERT(text); 22055 if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return; 22056 22057 glyph_len = nk_utf_decode(text, &unicode, total_len); 22058 while ((text_len < total_len) && glyph_len) 22059 { 22060 /* don't insert a backward delete, just process the event */ 22061 if (unicode == 127) goto next; 22062 /* can't add newline in single-line mode */ 22063 if (unicode == '\n' && state->single_line) goto next; 22064 /* filter incoming text */ 22065 if (state->filter && !state->filter(state, unicode)) goto next; 22066 22067 if (!NK_TEXT_HAS_SELECTION(state) && 22068 state->cursor < state->string.len) 22069 { 22070 if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) { 22071 nk_textedit_makeundo_replace(state, state->cursor, 1, 1); 22072 nk_str_delete_runes(&state->string, state->cursor, 1); 22073 } 22074 if (nk_str_insert_text_utf8(&state->string, state->cursor, 22075 text+text_len, 1)) 22076 { 22077 ++state->cursor; 22078 state->has_preferred_x = 0; 22079 } 22080 } else { 22081 nk_textedit_delete_selection(state); /* implicitly clamps */ 22082 if (nk_str_insert_text_utf8(&state->string, state->cursor, 22083 text+text_len, 1)) 22084 { 22085 nk_textedit_makeundo_insert(state, state->cursor, 1); 22086 ++state->cursor; 22087 state->has_preferred_x = 0; 22088 } 22089 } 22090 next: 22091 text_len += glyph_len; 22092 glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); 22093 } 22094 } 22095 NK_LIB void 22096 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, 22097 const struct nk_user_font *font, float row_height) 22098 { 22099 retry: 22100 switch (key) 22101 { 22102 case NK_KEY_NONE: 22103 case NK_KEY_CTRL: 22104 case NK_KEY_ENTER: 22105 case NK_KEY_SHIFT: 22106 case NK_KEY_TAB: 22107 case NK_KEY_COPY: 22108 case NK_KEY_CUT: 22109 case NK_KEY_PASTE: 22110 case NK_KEY_MAX: 22111 default: break; 22112 case NK_KEY_TEXT_UNDO: 22113 nk_textedit_undo(state); 22114 state->has_preferred_x = 0; 22115 break; 22116 22117 case NK_KEY_TEXT_REDO: 22118 nk_textedit_redo(state); 22119 state->has_preferred_x = 0; 22120 break; 22121 22122 case NK_KEY_TEXT_SELECT_ALL: 22123 nk_textedit_select_all(state); 22124 state->has_preferred_x = 0; 22125 break; 22126 22127 case NK_KEY_TEXT_INSERT_MODE: 22128 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22129 state->mode = NK_TEXT_EDIT_MODE_INSERT; 22130 break; 22131 case NK_KEY_TEXT_REPLACE_MODE: 22132 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22133 state->mode = NK_TEXT_EDIT_MODE_REPLACE; 22134 break; 22135 case NK_KEY_TEXT_RESET_MODE: 22136 if (state->mode == NK_TEXT_EDIT_MODE_INSERT || 22137 state->mode == NK_TEXT_EDIT_MODE_REPLACE) 22138 state->mode = NK_TEXT_EDIT_MODE_VIEW; 22139 break; 22140 22141 case NK_KEY_LEFT: 22142 if (shift_mod) { 22143 nk_textedit_clamp(state); 22144 nk_textedit_prep_selection_at_cursor(state); 22145 /* move selection left */ 22146 if (state->select_end > 0) 22147 --state->select_end; 22148 state->cursor = state->select_end; 22149 state->has_preferred_x = 0; 22150 } else { 22151 /* if currently there's a selection, 22152 * move cursor to start of selection */ 22153 if (NK_TEXT_HAS_SELECTION(state)) 22154 nk_textedit_move_to_first(state); 22155 else if (state->cursor > 0) 22156 --state->cursor; 22157 state->has_preferred_x = 0; 22158 } break; 22159 22160 case NK_KEY_RIGHT: 22161 if (shift_mod) { 22162 nk_textedit_prep_selection_at_cursor(state); 22163 /* move selection right */ 22164 ++state->select_end; 22165 nk_textedit_clamp(state); 22166 state->cursor = state->select_end; 22167 state->has_preferred_x = 0; 22168 } else { 22169 /* if currently there's a selection, 22170 * move cursor to end of selection */ 22171 if (NK_TEXT_HAS_SELECTION(state)) 22172 nk_textedit_move_to_last(state); 22173 else ++state->cursor; 22174 nk_textedit_clamp(state); 22175 state->has_preferred_x = 0; 22176 } break; 22177 22178 case NK_KEY_TEXT_WORD_LEFT: 22179 if (shift_mod) { 22180 if( !NK_TEXT_HAS_SELECTION( state ) ) 22181 nk_textedit_prep_selection_at_cursor(state); 22182 state->cursor = nk_textedit_move_to_word_previous(state); 22183 state->select_end = state->cursor; 22184 nk_textedit_clamp(state ); 22185 } else { 22186 if (NK_TEXT_HAS_SELECTION(state)) 22187 nk_textedit_move_to_first(state); 22188 else { 22189 state->cursor = nk_textedit_move_to_word_previous(state); 22190 nk_textedit_clamp(state ); 22191 } 22192 } break; 22193 22194 case NK_KEY_TEXT_WORD_RIGHT: 22195 if (shift_mod) { 22196 if( !NK_TEXT_HAS_SELECTION( state ) ) 22197 nk_textedit_prep_selection_at_cursor(state); 22198 state->cursor = nk_textedit_move_to_word_next(state); 22199 state->select_end = state->cursor; 22200 nk_textedit_clamp(state); 22201 } else { 22202 if (NK_TEXT_HAS_SELECTION(state)) 22203 nk_textedit_move_to_last(state); 22204 else { 22205 state->cursor = nk_textedit_move_to_word_next(state); 22206 nk_textedit_clamp(state ); 22207 } 22208 } break; 22209 22210 case NK_KEY_DOWN: { 22211 struct nk_text_find find; 22212 struct nk_text_edit_row row; 22213 int i, sel = shift_mod; 22214 22215 if (state->single_line) { 22216 /* on windows, up&down in single-line behave like left&right */ 22217 key = NK_KEY_RIGHT; 22218 goto retry; 22219 } 22220 22221 if (sel) 22222 nk_textedit_prep_selection_at_cursor(state); 22223 else if (NK_TEXT_HAS_SELECTION(state)) 22224 nk_textedit_move_to_last(state); 22225 22226 /* compute current position of cursor point */ 22227 nk_textedit_clamp(state); 22228 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22229 font, row_height); 22230 22231 /* now find character position down a row */ 22232 if (find.length) 22233 { 22234 float x; 22235 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 22236 int start = find.first_char + find.length; 22237 22238 state->cursor = start; 22239 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 22240 x = row.x0; 22241 22242 for (i=0; i < row.num_chars && x < row.x1; ++i) { 22243 float dx = nk_textedit_get_width(state, start, i, font); 22244 x += dx; 22245 if (x > goal_x) 22246 break; 22247 ++state->cursor; 22248 } 22249 nk_textedit_clamp(state); 22250 22251 state->has_preferred_x = 1; 22252 state->preferred_x = goal_x; 22253 if (sel) 22254 state->select_end = state->cursor; 22255 } 22256 } break; 22257 22258 case NK_KEY_UP: { 22259 struct nk_text_find find; 22260 struct nk_text_edit_row row; 22261 int i, sel = shift_mod; 22262 22263 if (state->single_line) { 22264 /* on windows, up&down become left&right */ 22265 key = NK_KEY_LEFT; 22266 goto retry; 22267 } 22268 22269 if (sel) 22270 nk_textedit_prep_selection_at_cursor(state); 22271 else if (NK_TEXT_HAS_SELECTION(state)) 22272 nk_textedit_move_to_first(state); 22273 22274 /* compute current position of cursor point */ 22275 nk_textedit_clamp(state); 22276 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22277 font, row_height); 22278 22279 /* can only go up if there's a previous row */ 22280 if (find.prev_first != find.first_char) { 22281 /* now find character position up a row */ 22282 float x; 22283 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 22284 22285 state->cursor = find.prev_first; 22286 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 22287 x = row.x0; 22288 22289 for (i=0; i < row.num_chars && x < row.x1; ++i) { 22290 float dx = nk_textedit_get_width(state, find.prev_first, i, font); 22291 x += dx; 22292 if (x > goal_x) 22293 break; 22294 ++state->cursor; 22295 } 22296 nk_textedit_clamp(state); 22297 22298 state->has_preferred_x = 1; 22299 state->preferred_x = goal_x; 22300 if (sel) state->select_end = state->cursor; 22301 } 22302 } break; 22303 22304 case NK_KEY_DEL: 22305 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22306 break; 22307 if (NK_TEXT_HAS_SELECTION(state)) 22308 nk_textedit_delete_selection(state); 22309 else { 22310 int n = state->string.len; 22311 if (state->cursor < n) 22312 nk_textedit_delete(state, state->cursor, 1); 22313 } 22314 state->has_preferred_x = 0; 22315 break; 22316 22317 case NK_KEY_BACKSPACE: 22318 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22319 break; 22320 if (NK_TEXT_HAS_SELECTION(state)) 22321 nk_textedit_delete_selection(state); 22322 else { 22323 nk_textedit_clamp(state); 22324 if (state->cursor > 0) { 22325 nk_textedit_delete(state, state->cursor-1, 1); 22326 --state->cursor; 22327 } 22328 } 22329 state->has_preferred_x = 0; 22330 break; 22331 22332 case NK_KEY_TEXT_START: 22333 if (shift_mod) { 22334 nk_textedit_prep_selection_at_cursor(state); 22335 state->cursor = state->select_end = 0; 22336 state->has_preferred_x = 0; 22337 } else { 22338 state->cursor = state->select_start = state->select_end = 0; 22339 state->has_preferred_x = 0; 22340 } 22341 break; 22342 22343 case NK_KEY_TEXT_END: 22344 if (shift_mod) { 22345 nk_textedit_prep_selection_at_cursor(state); 22346 state->cursor = state->select_end = state->string.len; 22347 state->has_preferred_x = 0; 22348 } else { 22349 state->cursor = state->string.len; 22350 state->select_start = state->select_end = 0; 22351 state->has_preferred_x = 0; 22352 } 22353 break; 22354 22355 case NK_KEY_TEXT_LINE_START: { 22356 if (shift_mod) { 22357 struct nk_text_find find; 22358 nk_textedit_clamp(state); 22359 nk_textedit_prep_selection_at_cursor(state); 22360 if (state->string.len && state->cursor == state->string.len) 22361 --state->cursor; 22362 nk_textedit_find_charpos(&find, state,state->cursor, state->single_line, 22363 font, row_height); 22364 state->cursor = state->select_end = find.first_char; 22365 state->has_preferred_x = 0; 22366 } else { 22367 struct nk_text_find find; 22368 if (state->string.len && state->cursor == state->string.len) 22369 --state->cursor; 22370 nk_textedit_clamp(state); 22371 nk_textedit_move_to_first(state); 22372 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22373 font, row_height); 22374 state->cursor = find.first_char; 22375 state->has_preferred_x = 0; 22376 } 22377 } break; 22378 22379 case NK_KEY_TEXT_LINE_END: { 22380 if (shift_mod) { 22381 struct nk_text_find find; 22382 nk_textedit_clamp(state); 22383 nk_textedit_prep_selection_at_cursor(state); 22384 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22385 font, row_height); 22386 state->has_preferred_x = 0; 22387 state->cursor = find.first_char + find.length; 22388 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 22389 --state->cursor; 22390 state->select_end = state->cursor; 22391 } else { 22392 struct nk_text_find find; 22393 nk_textedit_clamp(state); 22394 nk_textedit_move_to_first(state); 22395 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22396 font, row_height); 22397 22398 state->has_preferred_x = 0; 22399 state->cursor = find.first_char + find.length; 22400 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 22401 --state->cursor; 22402 }} break; 22403 } 22404 } 22405 NK_INTERN void 22406 nk_textedit_flush_redo(struct nk_text_undo_state *state) 22407 { 22408 state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 22409 state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 22410 } 22411 NK_INTERN void 22412 nk_textedit_discard_undo(struct nk_text_undo_state *state) 22413 { 22414 /* discard the oldest entry in the undo list */ 22415 if (state->undo_point > 0) { 22416 /* if the 0th undo state has characters, clean those up */ 22417 if (state->undo_rec[0].char_storage >= 0) { 22418 int n = state->undo_rec[0].insert_length, i; 22419 /* delete n characters from all other records */ 22420 state->undo_char_point = (short)(state->undo_char_point - n); 22421 NK_MEMCPY(state->undo_char, state->undo_char + n, 22422 (nk_size)state->undo_char_point*sizeof(nk_rune)); 22423 for (i=0; i < state->undo_point; ++i) { 22424 if (state->undo_rec[i].char_storage >= 0) 22425 state->undo_rec[i].char_storage = (short) 22426 (state->undo_rec[i].char_storage - n); 22427 } 22428 } 22429 --state->undo_point; 22430 NK_MEMCPY(state->undo_rec, state->undo_rec+1, 22431 (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0]))); 22432 } 22433 } 22434 NK_INTERN void 22435 nk_textedit_discard_redo(struct nk_text_undo_state *state) 22436 { 22437 /* discard the oldest entry in the redo list--it's bad if this 22438 ever happens, but because undo & redo have to store the actual 22439 characters in different cases, the redo character buffer can 22440 fill up even though the undo buffer didn't */ 22441 nk_size num; 22442 int k = NK_TEXTEDIT_UNDOSTATECOUNT-1; 22443 if (state->redo_point <= k) { 22444 /* if the k'th undo state has characters, clean those up */ 22445 if (state->undo_rec[k].char_storage >= 0) { 22446 int n = state->undo_rec[k].insert_length, i; 22447 /* delete n characters from all other records */ 22448 state->redo_char_point = (short)(state->redo_char_point + n); 22449 num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point); 22450 NK_MEMCPY(state->undo_char + state->redo_char_point, 22451 state->undo_char + state->redo_char_point-n, num * sizeof(char)); 22452 for (i = state->redo_point; i < k; ++i) { 22453 if (state->undo_rec[i].char_storage >= 0) { 22454 state->undo_rec[i].char_storage = (short) 22455 (state->undo_rec[i].char_storage + n); 22456 } 22457 } 22458 } 22459 ++state->redo_point; 22460 num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point); 22461 if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1, 22462 state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0])); 22463 } 22464 } 22465 NK_INTERN struct nk_text_undo_record* 22466 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars) 22467 { 22468 /* any time we create a new undo record, we discard redo*/ 22469 nk_textedit_flush_redo(state); 22470 22471 /* if we have no free records, we have to make room, 22472 * by sliding the existing records down */ 22473 if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22474 nk_textedit_discard_undo(state); 22475 22476 /* if the characters to store won't possibly fit in the buffer, 22477 * we can't undo */ 22478 if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) { 22479 state->undo_point = 0; 22480 state->undo_char_point = 0; 22481 return 0; 22482 } 22483 22484 /* if we don't have enough free characters in the buffer, 22485 * we have to make room */ 22486 while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT) 22487 nk_textedit_discard_undo(state); 22488 return &state->undo_rec[state->undo_point++]; 22489 } 22490 NK_INTERN nk_rune* 22491 nk_textedit_createundo(struct nk_text_undo_state *state, int pos, 22492 int insert_len, int delete_len) 22493 { 22494 struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len); 22495 if (r == 0) 22496 return 0; 22497 22498 r->where = pos; 22499 r->insert_length = (short) insert_len; 22500 r->delete_length = (short) delete_len; 22501 22502 if (insert_len == 0) { 22503 r->char_storage = -1; 22504 return 0; 22505 } else { 22506 r->char_storage = state->undo_char_point; 22507 state->undo_char_point = (short)(state->undo_char_point + insert_len); 22508 return &state->undo_char[r->char_storage]; 22509 } 22510 } 22511 NK_API void 22512 nk_textedit_undo(struct nk_text_edit *state) 22513 { 22514 struct nk_text_undo_state *s = &state->undo; 22515 struct nk_text_undo_record u, *r; 22516 if (s->undo_point == 0) 22517 return; 22518 22519 /* we need to do two things: apply the undo record, and create a redo record */ 22520 u = s->undo_rec[s->undo_point-1]; 22521 r = &s->undo_rec[s->redo_point-1]; 22522 r->char_storage = -1; 22523 22524 r->insert_length = u.delete_length; 22525 r->delete_length = u.insert_length; 22526 r->where = u.where; 22527 22528 if (u.delete_length) 22529 { 22530 /* if the undo record says to delete characters, then the redo record will 22531 need to re-insert the characters that get deleted, so we need to store 22532 them. 22533 there are three cases: 22534 - there's enough room to store the characters 22535 - characters stored for *redoing* don't leave room for redo 22536 - characters stored for *undoing* don't leave room for redo 22537 if the last is true, we have to bail */ 22538 if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) { 22539 /* the undo records take up too much character space; there's no space 22540 * to store the redo characters */ 22541 r->insert_length = 0; 22542 } else { 22543 int i; 22544 /* there's definitely room to store the characters eventually */ 22545 while (s->undo_char_point + u.delete_length > s->redo_char_point) { 22546 /* there's currently not enough room, so discard a redo record */ 22547 nk_textedit_discard_redo(s); 22548 /* should never happen: */ 22549 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22550 return; 22551 } 22552 22553 r = &s->undo_rec[s->redo_point-1]; 22554 r->char_storage = (short)(s->redo_char_point - u.delete_length); 22555 s->redo_char_point = (short)(s->redo_char_point - u.delete_length); 22556 22557 /* now save the characters */ 22558 for (i=0; i < u.delete_length; ++i) 22559 s->undo_char[r->char_storage + i] = 22560 nk_str_rune_at(&state->string, u.where + i); 22561 } 22562 /* now we can carry out the deletion */ 22563 nk_str_delete_runes(&state->string, u.where, u.delete_length); 22564 } 22565 22566 /* check type of recorded action: */ 22567 if (u.insert_length) { 22568 /* easy case: was a deletion, so we need to insert n characters */ 22569 nk_str_insert_text_runes(&state->string, u.where, 22570 &s->undo_char[u.char_storage], u.insert_length); 22571 s->undo_char_point = (short)(s->undo_char_point - u.insert_length); 22572 } 22573 state->cursor = (short)(u.where + u.insert_length); 22574 22575 s->undo_point--; 22576 s->redo_point--; 22577 } 22578 NK_API void 22579 nk_textedit_redo(struct nk_text_edit *state) 22580 { 22581 struct nk_text_undo_state *s = &state->undo; 22582 struct nk_text_undo_record *u, r; 22583 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22584 return; 22585 22586 /* we need to do two things: apply the redo record, and create an undo record */ 22587 u = &s->undo_rec[s->undo_point]; 22588 r = s->undo_rec[s->redo_point]; 22589 22590 /* we KNOW there must be room for the undo record, because the redo record 22591 was derived from an undo record */ 22592 u->delete_length = r.insert_length; 22593 u->insert_length = r.delete_length; 22594 u->where = r.where; 22595 u->char_storage = -1; 22596 22597 if (r.delete_length) { 22598 /* the redo record requires us to delete characters, so the undo record 22599 needs to store the characters */ 22600 if (s->undo_char_point + u->insert_length > s->redo_char_point) { 22601 u->insert_length = 0; 22602 u->delete_length = 0; 22603 } else { 22604 int i; 22605 u->char_storage = s->undo_char_point; 22606 s->undo_char_point = (short)(s->undo_char_point + u->insert_length); 22607 22608 /* now save the characters */ 22609 for (i=0; i < u->insert_length; ++i) { 22610 s->undo_char[u->char_storage + i] = 22611 nk_str_rune_at(&state->string, u->where + i); 22612 } 22613 } 22614 nk_str_delete_runes(&state->string, r.where, r.delete_length); 22615 } 22616 22617 if (r.insert_length) { 22618 /* easy case: need to insert n characters */ 22619 nk_str_insert_text_runes(&state->string, r.where, 22620 &s->undo_char[r.char_storage], r.insert_length); 22621 } 22622 state->cursor = r.where + r.insert_length; 22623 22624 s->undo_point++; 22625 s->redo_point++; 22626 } 22627 NK_INTERN void 22628 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length) 22629 { 22630 nk_textedit_createundo(&state->undo, where, 0, length); 22631 } 22632 NK_INTERN void 22633 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length) 22634 { 22635 int i; 22636 nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0); 22637 if (p) { 22638 for (i=0; i < length; ++i) 22639 p[i] = nk_str_rune_at(&state->string, where+i); 22640 } 22641 } 22642 NK_INTERN void 22643 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where, 22644 int old_length, int new_length) 22645 { 22646 int i; 22647 nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length); 22648 if (p) { 22649 for (i=0; i < old_length; ++i) 22650 p[i] = nk_str_rune_at(&state->string, where+i); 22651 } 22652 } 22653 NK_LIB void 22654 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, 22655 nk_plugin_filter filter) 22656 { 22657 /* reset the state to default */ 22658 state->undo.undo_point = 0; 22659 state->undo.undo_char_point = 0; 22660 state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 22661 state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 22662 state->select_end = state->select_start = 0; 22663 state->cursor = 0; 22664 state->has_preferred_x = 0; 22665 state->preferred_x = 0; 22666 state->cursor_at_end_of_line = 0; 22667 state->initialized = 1; 22668 state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE); 22669 state->mode = NK_TEXT_EDIT_MODE_VIEW; 22670 state->filter = filter; 22671 state->scrollbar = nk_vec2(0,0); 22672 } 22673 NK_API void 22674 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size) 22675 { 22676 NK_ASSERT(state); 22677 NK_ASSERT(memory); 22678 if (!state || !memory || !size) return; 22679 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22680 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22681 nk_str_init_fixed(&state->string, memory, size); 22682 } 22683 NK_API void 22684 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size) 22685 { 22686 NK_ASSERT(state); 22687 NK_ASSERT(alloc); 22688 if (!state || !alloc) return; 22689 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22690 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22691 nk_str_init(&state->string, alloc, size); 22692 } 22693 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 22694 NK_API void 22695 nk_textedit_init_default(struct nk_text_edit *state) 22696 { 22697 NK_ASSERT(state); 22698 if (!state) return; 22699 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22700 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22701 nk_str_init_default(&state->string); 22702 } 22703 #endif 22704 NK_API void 22705 nk_textedit_select_all(struct nk_text_edit *state) 22706 { 22707 NK_ASSERT(state); 22708 state->select_start = 0; 22709 state->select_end = state->string.len; 22710 } 22711 NK_API void 22712 nk_textedit_free(struct nk_text_edit *state) 22713 { 22714 NK_ASSERT(state); 22715 if (!state) return; 22716 nk_str_free(&state->string); 22717 } 22718 22719 22720 22721 22722 22723 /* =============================================================== 22724 * 22725 * FILTER 22726 * 22727 * ===============================================================*/ 22728 NK_API int 22729 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode) 22730 { 22731 NK_UNUSED(unicode); 22732 NK_UNUSED(box); 22733 return nk_true; 22734 } 22735 NK_API int 22736 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode) 22737 { 22738 NK_UNUSED(box); 22739 if (unicode > 128) return nk_false; 22740 else return nk_true; 22741 } 22742 NK_API int 22743 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode) 22744 { 22745 NK_UNUSED(box); 22746 if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') 22747 return nk_false; 22748 else return nk_true; 22749 } 22750 NK_API int 22751 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode) 22752 { 22753 NK_UNUSED(box); 22754 if ((unicode < '0' || unicode > '9') && unicode != '-') 22755 return nk_false; 22756 else return nk_true; 22757 } 22758 NK_API int 22759 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode) 22760 { 22761 NK_UNUSED(box); 22762 if ((unicode < '0' || unicode > '9') && 22763 (unicode < 'a' || unicode > 'f') && 22764 (unicode < 'A' || unicode > 'F')) 22765 return nk_false; 22766 else return nk_true; 22767 } 22768 NK_API int 22769 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode) 22770 { 22771 NK_UNUSED(box); 22772 if (unicode < '0' || unicode > '7') 22773 return nk_false; 22774 else return nk_true; 22775 } 22776 NK_API int 22777 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode) 22778 { 22779 NK_UNUSED(box); 22780 if (unicode != '0' && unicode != '1') 22781 return nk_false; 22782 else return nk_true; 22783 } 22784 22785 /* =============================================================== 22786 * 22787 * EDIT 22788 * 22789 * ===============================================================*/ 22790 NK_LIB void 22791 nk_edit_draw_text(struct nk_command_buffer *out, 22792 const struct nk_style_edit *style, float pos_x, float pos_y, 22793 float x_offset, const char *text, int byte_len, float row_height, 22794 const struct nk_user_font *font, struct nk_color background, 22795 struct nk_color foreground, int is_selected) 22796 { 22797 NK_ASSERT(out); 22798 NK_ASSERT(font); 22799 NK_ASSERT(style); 22800 if (!text || !byte_len || !out || !style) return; 22801 22802 {int glyph_len = 0; 22803 nk_rune unicode = 0; 22804 int text_len = 0; 22805 float line_width = 0; 22806 float glyph_width; 22807 const char *line = text; 22808 float line_offset = 0; 22809 int line_count = 0; 22810 22811 struct nk_text txt; 22812 txt.padding = nk_vec2(0,0); 22813 txt.background = background; 22814 txt.text = foreground; 22815 22816 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len); 22817 if (!glyph_len) return; 22818 while ((text_len < byte_len) && glyph_len) 22819 { 22820 if (unicode == '\n') { 22821 /* new line separator so draw previous line */ 22822 struct nk_rect label; 22823 label.y = pos_y + line_offset; 22824 label.h = row_height; 22825 label.w = line_width; 22826 label.x = pos_x; 22827 if (!line_count) 22828 label.x += x_offset; 22829 22830 if (is_selected) /* selection needs to draw different background color */ 22831 nk_fill_rect(out, label, 0, background); 22832 nk_widget_text(out, label, line, (int)((text + text_len) - line), 22833 &txt, NK_TEXT_CENTERED, font); 22834 22835 text_len++; 22836 line_count++; 22837 line_width = 0; 22838 line = text + text_len; 22839 line_offset += row_height; 22840 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len)); 22841 continue; 22842 } 22843 if (unicode == '\r') { 22844 text_len++; 22845 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 22846 continue; 22847 } 22848 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 22849 line_width += (float)glyph_width; 22850 text_len += glyph_len; 22851 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 22852 continue; 22853 } 22854 if (line_width > 0) { 22855 /* draw last line */ 22856 struct nk_rect label; 22857 label.y = pos_y + line_offset; 22858 label.h = row_height; 22859 label.w = line_width; 22860 label.x = pos_x; 22861 if (!line_count) 22862 label.x += x_offset; 22863 22864 if (is_selected) 22865 nk_fill_rect(out, label, 0, background); 22866 nk_widget_text(out, label, line, (int)((text + text_len) - line), 22867 &txt, NK_TEXT_LEFT, font); 22868 }} 22869 } 22870 NK_LIB nk_flags 22871 nk_do_edit(nk_flags *state, struct nk_command_buffer *out, 22872 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, 22873 struct nk_text_edit *edit, const struct nk_style_edit *style, 22874 struct nk_input *in, const struct nk_user_font *font) 22875 { 22876 struct nk_rect area; 22877 nk_flags ret = 0; 22878 float row_height; 22879 char prev_state = 0; 22880 char is_hovered = 0; 22881 char select_all = 0; 22882 char cursor_follow = 0; 22883 struct nk_rect old_clip; 22884 struct nk_rect clip; 22885 22886 NK_ASSERT(state); 22887 NK_ASSERT(out); 22888 NK_ASSERT(style); 22889 if (!state || !out || !style) 22890 return ret; 22891 22892 /* visible text area calculation */ 22893 area.x = bounds.x + style->padding.x + style->border; 22894 area.y = bounds.y + style->padding.y + style->border; 22895 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border); 22896 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border); 22897 if (flags & NK_EDIT_MULTILINE) 22898 area.w = NK_MAX(0, area.w - style->scrollbar_size.x); 22899 row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h; 22900 22901 /* calculate clipping rectangle */ 22902 old_clip = out->clip; 22903 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h); 22904 22905 /* update edit state */ 22906 prev_state = (char)edit->active; 22907 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds); 22908 if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { 22909 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, 22910 bounds.x, bounds.y, bounds.w, bounds.h); 22911 } 22912 22913 /* (de)activate text editor */ 22914 if (!prev_state && edit->active) { 22915 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ? 22916 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE; 22917 nk_textedit_clear_state(edit, type, filter); 22918 if (flags & NK_EDIT_AUTO_SELECT) 22919 select_all = nk_true; 22920 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) { 22921 edit->cursor = edit->string.len; 22922 in = 0; 22923 } 22924 } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW; 22925 if (flags & NK_EDIT_READ_ONLY) 22926 edit->mode = NK_TEXT_EDIT_MODE_VIEW; 22927 else if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 22928 edit->mode = NK_TEXT_EDIT_MODE_INSERT; 22929 22930 ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE; 22931 if (prev_state != edit->active) 22932 ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED; 22933 22934 /* handle user input */ 22935 if (edit->active && in) 22936 { 22937 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down; 22938 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x; 22939 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y; 22940 22941 /* mouse click handler */ 22942 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area); 22943 if (select_all) { 22944 nk_textedit_select_all(edit); 22945 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 22946 in->mouse.buttons[NK_BUTTON_LEFT].clicked) { 22947 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height); 22948 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 22949 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) { 22950 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height); 22951 cursor_follow = nk_true; 22952 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked && 22953 in->mouse.buttons[NK_BUTTON_RIGHT].down) { 22954 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height); 22955 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height); 22956 cursor_follow = nk_true; 22957 } 22958 22959 {int i; /* keyboard input */ 22960 int old_mode = edit->mode; 22961 for (i = 0; i < NK_KEY_MAX; ++i) { 22962 if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */ 22963 if (nk_input_is_key_pressed(in, (enum nk_keys)i)) { 22964 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height); 22965 cursor_follow = nk_true; 22966 } 22967 } 22968 if (old_mode != edit->mode) { 22969 in->keyboard.text_len = 0; 22970 }} 22971 22972 /* text input */ 22973 edit->filter = filter; 22974 if (in->keyboard.text_len) { 22975 nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len); 22976 cursor_follow = nk_true; 22977 in->keyboard.text_len = 0; 22978 } 22979 22980 /* enter key handler */ 22981 if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) { 22982 cursor_follow = nk_true; 22983 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod) 22984 nk_textedit_text(edit, "\n", 1); 22985 else if (flags & NK_EDIT_SIG_ENTER) 22986 ret |= NK_EDIT_COMMITED; 22987 else nk_textedit_text(edit, "\n", 1); 22988 } 22989 22990 /* cut & copy handler */ 22991 {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY); 22992 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT); 22993 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD)) 22994 { 22995 int glyph_len; 22996 nk_rune unicode; 22997 const char *text; 22998 int b = edit->select_start; 22999 int e = edit->select_end; 23000 23001 int begin = NK_MIN(b, e); 23002 int end = NK_MAX(b, e); 23003 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len); 23004 if (edit->clip.copy) 23005 edit->clip.copy(edit->clip.userdata, text, end - begin); 23006 if (cut && !(flags & NK_EDIT_READ_ONLY)){ 23007 nk_textedit_cut(edit); 23008 cursor_follow = nk_true; 23009 } 23010 }} 23011 23012 /* paste handler */ 23013 {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE); 23014 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) { 23015 edit->clip.paste(edit->clip.userdata, edit); 23016 cursor_follow = nk_true; 23017 }} 23018 23019 /* tab handler */ 23020 {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB); 23021 if (tab && (flags & NK_EDIT_ALLOW_TAB)) { 23022 nk_textedit_text(edit, " ", 4); 23023 cursor_follow = nk_true; 23024 }} 23025 } 23026 23027 /* set widget state */ 23028 if (edit->active) 23029 *state = NK_WIDGET_STATE_ACTIVE; 23030 else nk_widget_state_reset(state); 23031 23032 if (is_hovered) 23033 *state |= NK_WIDGET_STATE_HOVERED; 23034 23035 /* DRAW EDIT */ 23036 {const char *text = nk_str_get_const(&edit->string); 23037 int len = nk_str_len_char(&edit->string); 23038 23039 {/* select background colors/images */ 23040 const struct nk_style_item *background; 23041 if (*state & NK_WIDGET_STATE_ACTIVED) 23042 background = &style->active; 23043 else if (*state & NK_WIDGET_STATE_HOVER) 23044 background = &style->hover; 23045 else background = &style->normal; 23046 23047 /* draw background frame */ 23048 if (background->type == NK_STYLE_ITEM_COLOR) { 23049 nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color); 23050 nk_fill_rect(out, bounds, style->rounding, background->data.color); 23051 } else nk_draw_image(out, bounds, &background->data.image, nk_white);} 23052 23053 area.w = NK_MAX(0, area.w - style->cursor_size); 23054 if (edit->active) 23055 { 23056 int total_lines = 1; 23057 struct nk_vec2 text_size = nk_vec2(0,0); 23058 23059 /* text pointer positions */ 23060 const char *cursor_ptr = 0; 23061 const char *select_begin_ptr = 0; 23062 const char *select_end_ptr = 0; 23063 23064 /* 2D pixel positions */ 23065 struct nk_vec2 cursor_pos = nk_vec2(0,0); 23066 struct nk_vec2 selection_offset_start = nk_vec2(0,0); 23067 struct nk_vec2 selection_offset_end = nk_vec2(0,0); 23068 23069 int selection_begin = NK_MIN(edit->select_start, edit->select_end); 23070 int selection_end = NK_MAX(edit->select_start, edit->select_end); 23071 23072 /* calculate total line count + total space + cursor/selection position */ 23073 float line_width = 0.0f; 23074 if (text && len) 23075 { 23076 /* utf8 encoding */ 23077 float glyph_width; 23078 int glyph_len = 0; 23079 nk_rune unicode = 0; 23080 int text_len = 0; 23081 int glyphs = 0; 23082 int row_begin = 0; 23083 23084 glyph_len = nk_utf_decode(text, &unicode, len); 23085 glyph_width = font->width(font->userdata, font->height, text, glyph_len); 23086 line_width = 0; 23087 23088 /* iterate all lines */ 23089 while ((text_len < len) && glyph_len) 23090 { 23091 /* set cursor 2D position and line */ 23092 if (!cursor_ptr && glyphs == edit->cursor) 23093 { 23094 int glyph_offset; 23095 struct nk_vec2 out_offset; 23096 struct nk_vec2 row_size; 23097 const char *remaining; 23098 23099 /* calculate 2d position */ 23100 cursor_pos.y = (float)(total_lines-1) * row_height; 23101 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 23102 text_len-row_begin, row_height, &remaining, 23103 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 23104 cursor_pos.x = row_size.x; 23105 cursor_ptr = text + text_len; 23106 } 23107 23108 /* set start selection 2D position and line */ 23109 if (!select_begin_ptr && edit->select_start != edit->select_end && 23110 glyphs == selection_begin) 23111 { 23112 int glyph_offset; 23113 struct nk_vec2 out_offset; 23114 struct nk_vec2 row_size; 23115 const char *remaining; 23116 23117 /* calculate 2d position */ 23118 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height; 23119 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 23120 text_len-row_begin, row_height, &remaining, 23121 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 23122 selection_offset_start.x = row_size.x; 23123 select_begin_ptr = text + text_len; 23124 } 23125 23126 /* set end selection 2D position and line */ 23127 if (!select_end_ptr && edit->select_start != edit->select_end && 23128 glyphs == selection_end) 23129 { 23130 int glyph_offset; 23131 struct nk_vec2 out_offset; 23132 struct nk_vec2 row_size; 23133 const char *remaining; 23134 23135 /* calculate 2d position */ 23136 selection_offset_end.y = (float)(total_lines-1) * row_height; 23137 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 23138 text_len-row_begin, row_height, &remaining, 23139 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 23140 selection_offset_end.x = row_size.x; 23141 select_end_ptr = text + text_len; 23142 } 23143 if (unicode == '\n') { 23144 text_size.x = NK_MAX(text_size.x, line_width); 23145 total_lines++; 23146 line_width = 0; 23147 text_len++; 23148 glyphs++; 23149 row_begin = text_len; 23150 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 23151 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 23152 continue; 23153 } 23154 23155 glyphs++; 23156 text_len += glyph_len; 23157 line_width += (float)glyph_width; 23158 23159 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 23160 glyph_width = font->width(font->userdata, font->height, 23161 text+text_len, glyph_len); 23162 continue; 23163 } 23164 text_size.y = (float)total_lines * row_height; 23165 23166 /* handle case when cursor is at end of text buffer */ 23167 if (!cursor_ptr && edit->cursor == edit->string.len) { 23168 cursor_pos.x = line_width; 23169 cursor_pos.y = text_size.y - row_height; 23170 } 23171 } 23172 { 23173 /* scrollbar */ 23174 if (cursor_follow) 23175 { 23176 /* update scrollbar to follow cursor */ 23177 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) { 23178 /* horizontal scroll */ 23179 const float scroll_increment = area.w * 0.25f; 23180 if (cursor_pos.x < edit->scrollbar.x) 23181 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment); 23182 if (cursor_pos.x >= edit->scrollbar.x + area.w) 23183 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment); 23184 } else edit->scrollbar.x = 0; 23185 23186 if (flags & NK_EDIT_MULTILINE) { 23187 /* vertical scroll */ 23188 if (cursor_pos.y < edit->scrollbar.y) 23189 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height); 23190 if (cursor_pos.y >= edit->scrollbar.y + area.h) 23191 edit->scrollbar.y = edit->scrollbar.y + row_height; 23192 } else edit->scrollbar.y = 0; 23193 } 23194 23195 /* scrollbar widget */ 23196 if (flags & NK_EDIT_MULTILINE) 23197 { 23198 nk_flags ws; 23199 struct nk_rect scroll; 23200 float scroll_target; 23201 float scroll_offset; 23202 float scroll_step; 23203 float scroll_inc; 23204 23205 scroll = area; 23206 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x; 23207 scroll.w = style->scrollbar_size.x; 23208 23209 scroll_offset = edit->scrollbar.y; 23210 scroll_step = scroll.h * 0.10f; 23211 scroll_inc = scroll.h * 0.01f; 23212 scroll_target = text_size.y; 23213 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0, 23214 scroll_offset, scroll_target, scroll_step, scroll_inc, 23215 &style->scrollbar, in, font); 23216 } 23217 } 23218 23219 /* draw text */ 23220 {struct nk_color background_color; 23221 struct nk_color text_color; 23222 struct nk_color sel_background_color; 23223 struct nk_color sel_text_color; 23224 struct nk_color cursor_color; 23225 struct nk_color cursor_text_color; 23226 const struct nk_style_item *background; 23227 nk_push_scissor(out, clip); 23228 23229 /* select correct colors to draw */ 23230 if (*state & NK_WIDGET_STATE_ACTIVED) { 23231 background = &style->active; 23232 text_color = style->text_active; 23233 sel_text_color = style->selected_text_hover; 23234 sel_background_color = style->selected_hover; 23235 cursor_color = style->cursor_hover; 23236 cursor_text_color = style->cursor_text_hover; 23237 } else if (*state & NK_WIDGET_STATE_HOVER) { 23238 background = &style->hover; 23239 text_color = style->text_hover; 23240 sel_text_color = style->selected_text_hover; 23241 sel_background_color = style->selected_hover; 23242 cursor_text_color = style->cursor_text_hover; 23243 cursor_color = style->cursor_hover; 23244 } else { 23245 background = &style->normal; 23246 text_color = style->text_normal; 23247 sel_text_color = style->selected_text_normal; 23248 sel_background_color = style->selected_normal; 23249 cursor_color = style->cursor_normal; 23250 cursor_text_color = style->cursor_text_normal; 23251 } 23252 if (background->type == NK_STYLE_ITEM_IMAGE) 23253 background_color = nk_rgba(0,0,0,0); 23254 else background_color = background->data.color; 23255 23256 23257 if (edit->select_start == edit->select_end) { 23258 /* no selection so just draw the complete text */ 23259 const char *begin = nk_str_get_const(&edit->string); 23260 int l = nk_str_len_char(&edit->string); 23261 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23262 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 23263 background_color, text_color, nk_false); 23264 } else { 23265 /* edit has selection so draw 1-3 text chunks */ 23266 if (edit->select_start != edit->select_end && selection_begin > 0){ 23267 /* draw unselected text before selection */ 23268 const char *begin = nk_str_get_const(&edit->string); 23269 NK_ASSERT(select_begin_ptr); 23270 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23271 area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin), 23272 row_height, font, background_color, text_color, nk_false); 23273 } 23274 if (edit->select_start != edit->select_end) { 23275 /* draw selected text */ 23276 NK_ASSERT(select_begin_ptr); 23277 if (!select_end_ptr) { 23278 const char *begin = nk_str_get_const(&edit->string); 23279 select_end_ptr = begin + nk_str_len_char(&edit->string); 23280 } 23281 nk_edit_draw_text(out, style, 23282 area.x - edit->scrollbar.x, 23283 area.y + selection_offset_start.y - edit->scrollbar.y, 23284 selection_offset_start.x, 23285 select_begin_ptr, (int)(select_end_ptr - select_begin_ptr), 23286 row_height, font, sel_background_color, sel_text_color, nk_true); 23287 } 23288 if ((edit->select_start != edit->select_end && 23289 selection_end < edit->string.len)) 23290 { 23291 /* draw unselected text after selected text */ 23292 const char *begin = select_end_ptr; 23293 const char *end = nk_str_get_const(&edit->string) + 23294 nk_str_len_char(&edit->string); 23295 NK_ASSERT(select_end_ptr); 23296 nk_edit_draw_text(out, style, 23297 area.x - edit->scrollbar.x, 23298 area.y + selection_offset_end.y - edit->scrollbar.y, 23299 selection_offset_end.x, 23300 begin, (int)(end - begin), row_height, font, 23301 background_color, text_color, nk_true); 23302 } 23303 } 23304 23305 /* cursor */ 23306 if (edit->select_start == edit->select_end) 23307 { 23308 if (edit->cursor >= nk_str_len(&edit->string) || 23309 (cursor_ptr && *cursor_ptr == '\n')) { 23310 /* draw cursor at end of line */ 23311 struct nk_rect cursor; 23312 cursor.w = style->cursor_size; 23313 cursor.h = font->height; 23314 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x; 23315 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f; 23316 cursor.y -= edit->scrollbar.y; 23317 nk_fill_rect(out, cursor, 0, cursor_color); 23318 } else { 23319 /* draw cursor inside text */ 23320 int glyph_len; 23321 struct nk_rect label; 23322 struct nk_text txt; 23323 23324 nk_rune unicode; 23325 NK_ASSERT(cursor_ptr); 23326 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4); 23327 23328 label.x = area.x + cursor_pos.x - edit->scrollbar.x; 23329 label.y = area.y + cursor_pos.y - edit->scrollbar.y; 23330 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len); 23331 label.h = row_height; 23332 23333 txt.padding = nk_vec2(0,0); 23334 txt.background = cursor_color;; 23335 txt.text = cursor_text_color; 23336 nk_fill_rect(out, label, 0, cursor_color); 23337 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font); 23338 } 23339 }} 23340 } else { 23341 /* not active so just draw text */ 23342 int l = nk_str_len_char(&edit->string); 23343 const char *begin = nk_str_get_const(&edit->string); 23344 23345 const struct nk_style_item *background; 23346 struct nk_color background_color; 23347 struct nk_color text_color; 23348 nk_push_scissor(out, clip); 23349 if (*state & NK_WIDGET_STATE_ACTIVED) { 23350 background = &style->active; 23351 text_color = style->text_active; 23352 } else if (*state & NK_WIDGET_STATE_HOVER) { 23353 background = &style->hover; 23354 text_color = style->text_hover; 23355 } else { 23356 background = &style->normal; 23357 text_color = style->text_normal; 23358 } 23359 if (background->type == NK_STYLE_ITEM_IMAGE) 23360 background_color = nk_rgba(0,0,0,0); 23361 else background_color = background->data.color; 23362 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23363 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 23364 background_color, text_color, nk_false); 23365 } 23366 nk_push_scissor(out, old_clip);} 23367 return ret; 23368 } 23369 NK_API void 23370 nk_edit_focus(struct nk_context *ctx, nk_flags flags) 23371 { 23372 nk_hash hash; 23373 struct nk_window *win; 23374 23375 NK_ASSERT(ctx); 23376 NK_ASSERT(ctx->current); 23377 if (!ctx || !ctx->current) return; 23378 23379 win = ctx->current; 23380 hash = win->edit.seq; 23381 win->edit.active = nk_true; 23382 win->edit.name = hash; 23383 if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 23384 win->edit.mode = NK_TEXT_EDIT_MODE_INSERT; 23385 } 23386 NK_API void 23387 nk_edit_unfocus(struct nk_context *ctx) 23388 { 23389 struct nk_window *win; 23390 NK_ASSERT(ctx); 23391 NK_ASSERT(ctx->current); 23392 if (!ctx || !ctx->current) return; 23393 23394 win = ctx->current; 23395 win->edit.active = nk_false; 23396 win->edit.name = 0; 23397 } 23398 NK_API nk_flags 23399 nk_edit_string(struct nk_context *ctx, nk_flags flags, 23400 char *memory, int *len, int max, nk_plugin_filter filter) 23401 { 23402 nk_hash hash; 23403 nk_flags state; 23404 struct nk_text_edit *edit; 23405 struct nk_window *win; 23406 23407 NK_ASSERT(ctx); 23408 NK_ASSERT(memory); 23409 NK_ASSERT(len); 23410 if (!ctx || !memory || !len) 23411 return 0; 23412 23413 filter = (!filter) ? nk_filter_default: filter; 23414 win = ctx->current; 23415 hash = win->edit.seq; 23416 edit = &ctx->text_edit; 23417 nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)? 23418 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter); 23419 23420 if (win->edit.active && hash == win->edit.name) { 23421 if (flags & NK_EDIT_NO_CURSOR) 23422 edit->cursor = nk_utf_len(memory, *len); 23423 else edit->cursor = win->edit.cursor; 23424 if (!(flags & NK_EDIT_SELECTABLE)) { 23425 edit->select_start = win->edit.cursor; 23426 edit->select_end = win->edit.cursor; 23427 } else { 23428 edit->select_start = win->edit.sel_start; 23429 edit->select_end = win->edit.sel_end; 23430 } 23431 edit->mode = win->edit.mode; 23432 edit->scrollbar.x = (float)win->edit.scrollbar.x; 23433 edit->scrollbar.y = (float)win->edit.scrollbar.y; 23434 edit->active = nk_true; 23435 } else edit->active = nk_false; 23436 23437 max = NK_MAX(1, max); 23438 *len = NK_MIN(*len, max-1); 23439 nk_str_init_fixed(&edit->string, memory, (nk_size)max); 23440 edit->string.buffer.allocated = (nk_size)*len; 23441 edit->string.len = nk_utf_len(memory, *len); 23442 state = nk_edit_buffer(ctx, flags, edit, filter); 23443 *len = (int)edit->string.buffer.allocated; 23444 23445 if (edit->active) { 23446 win->edit.cursor = edit->cursor; 23447 win->edit.sel_start = edit->select_start; 23448 win->edit.sel_end = edit->select_end; 23449 win->edit.mode = edit->mode; 23450 win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x; 23451 win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y; 23452 } return state; 23453 } 23454 NK_API nk_flags 23455 nk_edit_buffer(struct nk_context *ctx, nk_flags flags, 23456 struct nk_text_edit *edit, nk_plugin_filter filter) 23457 { 23458 struct nk_window *win; 23459 struct nk_style *style; 23460 struct nk_input *in; 23461 23462 enum nk_widget_layout_states state; 23463 struct nk_rect bounds; 23464 23465 nk_flags ret_flags = 0; 23466 unsigned char prev_state; 23467 nk_hash hash; 23468 23469 /* make sure correct values */ 23470 NK_ASSERT(ctx); 23471 NK_ASSERT(edit); 23472 NK_ASSERT(ctx->current); 23473 NK_ASSERT(ctx->current->layout); 23474 if (!ctx || !ctx->current || !ctx->current->layout) 23475 return 0; 23476 23477 win = ctx->current; 23478 style = &ctx->style; 23479 state = nk_widget(&bounds, ctx); 23480 if (!state) return state; 23481 in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 23482 23483 /* check if edit is currently hot item */ 23484 hash = win->edit.seq++; 23485 if (win->edit.active && hash == win->edit.name) { 23486 if (flags & NK_EDIT_NO_CURSOR) 23487 edit->cursor = edit->string.len; 23488 if (!(flags & NK_EDIT_SELECTABLE)) { 23489 edit->select_start = edit->cursor; 23490 edit->select_end = edit->cursor; 23491 } 23492 if (flags & NK_EDIT_CLIPBOARD) 23493 edit->clip = ctx->clip; 23494 edit->active = (unsigned char)win->edit.active; 23495 } else edit->active = nk_false; 23496 edit->mode = win->edit.mode; 23497 23498 filter = (!filter) ? nk_filter_default: filter; 23499 prev_state = (unsigned char)edit->active; 23500 in = (flags & NK_EDIT_READ_ONLY) ? 0: in; 23501 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags, 23502 filter, edit, &style->edit, in, style->font); 23503 23504 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 23505 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT]; 23506 if (edit->active && prev_state != edit->active) { 23507 /* current edit is now hot */ 23508 win->edit.active = nk_true; 23509 win->edit.name = hash; 23510 } else if (prev_state && !edit->active) { 23511 /* current edit is now cold */ 23512 win->edit.active = nk_false; 23513 } return ret_flags; 23514 } 23515 NK_API nk_flags 23516 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags, 23517 char *buffer, int max, nk_plugin_filter filter) 23518 { 23519 nk_flags result; 23520 int len = nk_strlen(buffer); 23521 result = nk_edit_string(ctx, flags, buffer, &len, max, filter); 23522 buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0'; 23523 return result; 23524 } 23525 23526 23527 23528 23529 23530 /* =============================================================== 23531 * 23532 * PROPERTY 23533 * 23534 * ===============================================================*/ 23535 NK_LIB void 23536 nk_drag_behavior(nk_flags *state, const struct nk_input *in, 23537 struct nk_rect drag, struct nk_property_variant *variant, 23538 float inc_per_pixel) 23539 { 23540 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 23541 int left_mouse_click_in_cursor = in && 23542 nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true); 23543 23544 nk_widget_state_reset(state); 23545 if (nk_input_is_mouse_hovering_rect(in, drag)) 23546 *state = NK_WIDGET_STATE_HOVERED; 23547 23548 if (left_mouse_down && left_mouse_click_in_cursor) { 23549 float delta, pixels; 23550 pixels = in->mouse.delta.x; 23551 delta = pixels * inc_per_pixel; 23552 switch (variant->kind) { 23553 default: break; 23554 case NK_PROPERTY_INT: 23555 variant->value.i = variant->value.i + (int)delta; 23556 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 23557 break; 23558 case NK_PROPERTY_FLOAT: 23559 variant->value.f = variant->value.f + (float)delta; 23560 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 23561 break; 23562 case NK_PROPERTY_DOUBLE: 23563 variant->value.d = variant->value.d + (double)delta; 23564 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 23565 break; 23566 } 23567 *state = NK_WIDGET_STATE_ACTIVE; 23568 } 23569 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag)) 23570 *state |= NK_WIDGET_STATE_ENTERED; 23571 else if (nk_input_is_mouse_prev_hovering_rect(in, drag)) 23572 *state |= NK_WIDGET_STATE_LEFT; 23573 } 23574 NK_LIB void 23575 nk_property_behavior(nk_flags *ws, const struct nk_input *in, 23576 struct nk_rect property, struct nk_rect label, struct nk_rect edit, 23577 struct nk_rect empty, int *state, struct nk_property_variant *variant, 23578 float inc_per_pixel) 23579 { 23580 if (in && *state == NK_PROPERTY_DEFAULT) { 23581 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT)) 23582 *state = NK_PROPERTY_EDIT; 23583 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true)) 23584 *state = NK_PROPERTY_DRAG; 23585 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true)) 23586 *state = NK_PROPERTY_DRAG; 23587 } 23588 if (*state == NK_PROPERTY_DRAG) { 23589 nk_drag_behavior(ws, in, property, variant, inc_per_pixel); 23590 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT; 23591 } 23592 } 23593 NK_LIB void 23594 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, 23595 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, 23596 const char *name, int len, const struct nk_user_font *font) 23597 { 23598 struct nk_text text; 23599 const struct nk_style_item *background; 23600 23601 /* select correct background and text color */ 23602 if (state & NK_WIDGET_STATE_ACTIVED) { 23603 background = &style->active; 23604 text.text = style->label_active; 23605 } else if (state & NK_WIDGET_STATE_HOVER) { 23606 background = &style->hover; 23607 text.text = style->label_hover; 23608 } else { 23609 background = &style->normal; 23610 text.text = style->label_normal; 23611 } 23612 23613 /* draw background */ 23614 if (background->type == NK_STYLE_ITEM_IMAGE) { 23615 nk_draw_image(out, *bounds, &background->data.image, nk_white); 23616 text.background = nk_rgba(0,0,0,0); 23617 } else { 23618 text.background = background->data.color; 23619 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 23620 nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color); 23621 } 23622 23623 /* draw label */ 23624 text.padding = nk_vec2(0,0); 23625 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font); 23626 } 23627 NK_LIB void 23628 nk_do_property(nk_flags *ws, 23629 struct nk_command_buffer *out, struct nk_rect property, 23630 const char *name, struct nk_property_variant *variant, 23631 float inc_per_pixel, char *buffer, int *len, 23632 int *state, int *cursor, int *select_begin, int *select_end, 23633 const struct nk_style_property *style, 23634 enum nk_property_filter filter, struct nk_input *in, 23635 const struct nk_user_font *font, struct nk_text_edit *text_edit, 23636 enum nk_button_behavior behavior) 23637 { 23638 const nk_plugin_filter filters[] = { 23639 nk_filter_decimal, 23640 nk_filter_float 23641 }; 23642 int active, old; 23643 int num_len, name_len; 23644 char string[NK_MAX_NUMBER_BUFFER]; 23645 float size; 23646 23647 char *dst = 0; 23648 int *length; 23649 23650 struct nk_rect left; 23651 struct nk_rect right; 23652 struct nk_rect label; 23653 struct nk_rect edit; 23654 struct nk_rect empty; 23655 23656 /* left decrement button */ 23657 left.h = font->height/2; 23658 left.w = left.h; 23659 left.x = property.x + style->border + style->padding.x; 23660 left.y = property.y + style->border + property.h/2.0f - left.h/2; 23661 23662 /* text label */ 23663 name_len = nk_strlen(name); 23664 size = font->width(font->userdata, font->height, name, name_len); 23665 label.x = left.x + left.w + style->padding.x; 23666 label.w = (float)size + 2 * style->padding.x; 23667 label.y = property.y + style->border + style->padding.y; 23668 label.h = property.h - (2 * style->border + 2 * style->padding.y); 23669 23670 /* right increment button */ 23671 right.y = left.y; 23672 right.w = left.w; 23673 right.h = left.h; 23674 right.x = property.x + property.w - (right.w + style->padding.x); 23675 23676 /* edit */ 23677 if (*state == NK_PROPERTY_EDIT) { 23678 size = font->width(font->userdata, font->height, buffer, *len); 23679 size += style->edit.cursor_size; 23680 length = len; 23681 dst = buffer; 23682 } else { 23683 switch (variant->kind) { 23684 default: break; 23685 case NK_PROPERTY_INT: 23686 nk_itoa(string, variant->value.i); 23687 num_len = nk_strlen(string); 23688 break; 23689 case NK_PROPERTY_FLOAT: 23690 NK_DTOA(string, (double)variant->value.f); 23691 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 23692 break; 23693 case NK_PROPERTY_DOUBLE: 23694 NK_DTOA(string, variant->value.d); 23695 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 23696 break; 23697 } 23698 size = font->width(font->userdata, font->height, string, num_len); 23699 dst = string; 23700 length = &num_len; 23701 } 23702 23703 edit.w = (float)size + 2 * style->padding.x; 23704 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w)); 23705 edit.x = right.x - (edit.w + style->padding.x); 23706 edit.y = property.y + style->border; 23707 edit.h = property.h - (2 * style->border); 23708 23709 /* empty left space activator */ 23710 empty.w = edit.x - (label.x + label.w); 23711 empty.x = label.x + label.w; 23712 empty.y = property.y; 23713 empty.h = property.h; 23714 23715 /* update property */ 23716 old = (*state == NK_PROPERTY_EDIT); 23717 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel); 23718 23719 /* draw property */ 23720 if (style->draw_begin) style->draw_begin(out, style->userdata); 23721 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font); 23722 if (style->draw_end) style->draw_end(out, style->userdata); 23723 23724 /* execute right button */ 23725 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) { 23726 switch (variant->kind) { 23727 default: break; 23728 case NK_PROPERTY_INT: 23729 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break; 23730 case NK_PROPERTY_FLOAT: 23731 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break; 23732 case NK_PROPERTY_DOUBLE: 23733 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break; 23734 } 23735 } 23736 /* execute left button */ 23737 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) { 23738 switch (variant->kind) { 23739 default: break; 23740 case NK_PROPERTY_INT: 23741 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break; 23742 case NK_PROPERTY_FLOAT: 23743 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break; 23744 case NK_PROPERTY_DOUBLE: 23745 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break; 23746 } 23747 } 23748 if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) { 23749 /* property has been activated so setup buffer */ 23750 NK_MEMCPY(buffer, dst, (nk_size)*length); 23751 *cursor = nk_utf_len(buffer, *length); 23752 *len = *length; 23753 length = len; 23754 dst = buffer; 23755 active = 0; 23756 } else active = (*state == NK_PROPERTY_EDIT); 23757 23758 /* execute and run text edit field */ 23759 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]); 23760 text_edit->active = (unsigned char)active; 23761 text_edit->string.len = *length; 23762 text_edit->cursor = NK_CLAMP(0, *cursor, *length); 23763 text_edit->select_start = NK_CLAMP(0,*select_begin, *length); 23764 text_edit->select_end = NK_CLAMP(0,*select_end, *length); 23765 text_edit->string.buffer.allocated = (nk_size)*length; 23766 text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER; 23767 text_edit->string.buffer.memory.ptr = dst; 23768 text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER; 23769 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT; 23770 nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT, 23771 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font); 23772 23773 *length = text_edit->string.len; 23774 *cursor = text_edit->cursor; 23775 *select_begin = text_edit->select_start; 23776 *select_end = text_edit->select_end; 23777 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER)) 23778 text_edit->active = nk_false; 23779 23780 if (active && !text_edit->active) { 23781 /* property is now not active so convert edit text to value*/ 23782 *state = NK_PROPERTY_DEFAULT; 23783 buffer[*len] = '\0'; 23784 switch (variant->kind) { 23785 default: break; 23786 case NK_PROPERTY_INT: 23787 variant->value.i = nk_strtoi(buffer, 0); 23788 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 23789 break; 23790 case NK_PROPERTY_FLOAT: 23791 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 23792 variant->value.f = nk_strtof(buffer, 0); 23793 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 23794 break; 23795 case NK_PROPERTY_DOUBLE: 23796 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 23797 variant->value.d = nk_strtod(buffer, 0); 23798 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 23799 break; 23800 } 23801 } 23802 } 23803 NK_LIB struct nk_property_variant 23804 nk_property_variant_int(int value, int min_value, int max_value, int step) 23805 { 23806 struct nk_property_variant result; 23807 result.kind = NK_PROPERTY_INT; 23808 result.value.i = value; 23809 result.min_value.i = min_value; 23810 result.max_value.i = max_value; 23811 result.step.i = step; 23812 return result; 23813 } 23814 NK_LIB struct nk_property_variant 23815 nk_property_variant_float(float value, float min_value, float max_value, float step) 23816 { 23817 struct nk_property_variant result; 23818 result.kind = NK_PROPERTY_FLOAT; 23819 result.value.f = value; 23820 result.min_value.f = min_value; 23821 result.max_value.f = max_value; 23822 result.step.f = step; 23823 return result; 23824 } 23825 NK_LIB struct nk_property_variant 23826 nk_property_variant_double(double value, double min_value, double max_value, 23827 double step) 23828 { 23829 struct nk_property_variant result; 23830 result.kind = NK_PROPERTY_DOUBLE; 23831 result.value.d = value; 23832 result.min_value.d = min_value; 23833 result.max_value.d = max_value; 23834 result.step.d = step; 23835 return result; 23836 } 23837 NK_LIB void 23838 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, 23839 float inc_per_pixel, const enum nk_property_filter filter) 23840 { 23841 struct nk_window *win; 23842 struct nk_panel *layout; 23843 struct nk_input *in; 23844 const struct nk_style *style; 23845 23846 struct nk_rect bounds; 23847 enum nk_widget_layout_states s; 23848 23849 int *state = 0; 23850 nk_hash hash = 0; 23851 char *buffer = 0; 23852 int *len = 0; 23853 int *cursor = 0; 23854 int *select_begin = 0; 23855 int *select_end = 0; 23856 int old_state; 23857 23858 char dummy_buffer[NK_MAX_NUMBER_BUFFER]; 23859 int dummy_state = NK_PROPERTY_DEFAULT; 23860 int dummy_length = 0; 23861 int dummy_cursor = 0; 23862 int dummy_select_begin = 0; 23863 int dummy_select_end = 0; 23864 23865 NK_ASSERT(ctx); 23866 NK_ASSERT(ctx->current); 23867 NK_ASSERT(ctx->current->layout); 23868 if (!ctx || !ctx->current || !ctx->current->layout) 23869 return; 23870 23871 win = ctx->current; 23872 layout = win->layout; 23873 style = &ctx->style; 23874 s = nk_widget(&bounds, ctx); 23875 if (!s) return; 23876 23877 /* calculate hash from name */ 23878 if (name[0] == '#') { 23879 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++); 23880 name++; /* special number hash */ 23881 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42); 23882 23883 /* check if property is currently hot item */ 23884 if (win->property.active && hash == win->property.name) { 23885 buffer = win->property.buffer; 23886 len = &win->property.length; 23887 cursor = &win->property.cursor; 23888 state = &win->property.state; 23889 select_begin = &win->property.select_start; 23890 select_end = &win->property.select_end; 23891 } else { 23892 buffer = dummy_buffer; 23893 len = &dummy_length; 23894 cursor = &dummy_cursor; 23895 state = &dummy_state; 23896 select_begin = &dummy_select_begin; 23897 select_end = &dummy_select_end; 23898 } 23899 23900 /* execute property widget */ 23901 old_state = *state; 23902 ctx->text_edit.clip = ctx->clip; 23903 in = ((s == NK_WIDGET_ROM && !win->property.active) || 23904 layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 23905 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, 23906 variant, inc_per_pixel, buffer, len, state, cursor, select_begin, 23907 select_end, &style->property, filter, in, style->font, &ctx->text_edit, 23908 ctx->button_behavior); 23909 23910 if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) { 23911 /* current property is now hot */ 23912 win->property.active = 1; 23913 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len); 23914 win->property.length = *len; 23915 win->property.cursor = *cursor; 23916 win->property.state = *state; 23917 win->property.name = hash; 23918 win->property.select_start = *select_begin; 23919 win->property.select_end = *select_end; 23920 if (*state == NK_PROPERTY_DRAG) { 23921 ctx->input.mouse.grab = nk_true; 23922 ctx->input.mouse.grabbed = nk_true; 23923 } 23924 } 23925 /* check if previously active property is now inactive */ 23926 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) { 23927 if (old_state == NK_PROPERTY_DRAG) { 23928 ctx->input.mouse.grab = nk_false; 23929 ctx->input.mouse.grabbed = nk_false; 23930 ctx->input.mouse.ungrab = nk_true; 23931 } 23932 win->property.select_start = 0; 23933 win->property.select_end = 0; 23934 win->property.active = 0; 23935 } 23936 } 23937 NK_API void 23938 nk_property_int(struct nk_context *ctx, const char *name, 23939 int min, int *val, int max, int step, float inc_per_pixel) 23940 { 23941 struct nk_property_variant variant; 23942 NK_ASSERT(ctx); 23943 NK_ASSERT(name); 23944 NK_ASSERT(val); 23945 23946 if (!ctx || !ctx->current || !name || !val) return; 23947 variant = nk_property_variant_int(*val, min, max, step); 23948 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 23949 *val = variant.value.i; 23950 } 23951 NK_API void 23952 nk_property_float(struct nk_context *ctx, const char *name, 23953 float min, float *val, float max, float step, float inc_per_pixel) 23954 { 23955 struct nk_property_variant variant; 23956 NK_ASSERT(ctx); 23957 NK_ASSERT(name); 23958 NK_ASSERT(val); 23959 23960 if (!ctx || !ctx->current || !name || !val) return; 23961 variant = nk_property_variant_float(*val, min, max, step); 23962 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23963 *val = variant.value.f; 23964 } 23965 NK_API void 23966 nk_property_double(struct nk_context *ctx, const char *name, 23967 double min, double *val, double max, double step, float inc_per_pixel) 23968 { 23969 struct nk_property_variant variant; 23970 NK_ASSERT(ctx); 23971 NK_ASSERT(name); 23972 NK_ASSERT(val); 23973 23974 if (!ctx || !ctx->current || !name || !val) return; 23975 variant = nk_property_variant_double(*val, min, max, step); 23976 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23977 *val = variant.value.d; 23978 } 23979 NK_API int 23980 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, 23981 int max, int step, float inc_per_pixel) 23982 { 23983 struct nk_property_variant variant; 23984 NK_ASSERT(ctx); 23985 NK_ASSERT(name); 23986 23987 if (!ctx || !ctx->current || !name) return val; 23988 variant = nk_property_variant_int(val, min, max, step); 23989 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 23990 val = variant.value.i; 23991 return val; 23992 } 23993 NK_API float 23994 nk_propertyf(struct nk_context *ctx, const char *name, float min, 23995 float val, float max, float step, float inc_per_pixel) 23996 { 23997 struct nk_property_variant variant; 23998 NK_ASSERT(ctx); 23999 NK_ASSERT(name); 24000 24001 if (!ctx || !ctx->current || !name) return val; 24002 variant = nk_property_variant_float(val, min, max, step); 24003 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 24004 val = variant.value.f; 24005 return val; 24006 } 24007 NK_API double 24008 nk_propertyd(struct nk_context *ctx, const char *name, double min, 24009 double val, double max, double step, float inc_per_pixel) 24010 { 24011 struct nk_property_variant variant; 24012 NK_ASSERT(ctx); 24013 NK_ASSERT(name); 24014 24015 if (!ctx || !ctx->current || !name) return val; 24016 variant = nk_property_variant_double(val, min, max, step); 24017 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 24018 val = variant.value.d; 24019 return val; 24020 } 24021 24022 24023 24024 24025 24026 /* ============================================================== 24027 * 24028 * CHART 24029 * 24030 * ===============================================================*/ 24031 NK_API int 24032 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type, 24033 struct nk_color color, struct nk_color highlight, 24034 int count, float min_value, float max_value) 24035 { 24036 struct nk_window *win; 24037 struct nk_chart *chart; 24038 const struct nk_style *config; 24039 const struct nk_style_chart *style; 24040 24041 const struct nk_style_item *background; 24042 struct nk_rect bounds = {0, 0, 0, 0}; 24043 24044 NK_ASSERT(ctx); 24045 NK_ASSERT(ctx->current); 24046 NK_ASSERT(ctx->current->layout); 24047 24048 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 24049 if (!nk_widget(&bounds, ctx)) { 24050 chart = &ctx->current->layout->chart; 24051 nk_zero(chart, sizeof(*chart)); 24052 return 0; 24053 } 24054 24055 win = ctx->current; 24056 config = &ctx->style; 24057 chart = &win->layout->chart; 24058 style = &config->chart; 24059 24060 /* setup basic generic chart */ 24061 nk_zero(chart, sizeof(*chart)); 24062 chart->x = bounds.x + style->padding.x; 24063 chart->y = bounds.y + style->padding.y; 24064 chart->w = bounds.w - 2 * style->padding.x; 24065 chart->h = bounds.h - 2 * style->padding.y; 24066 chart->w = NK_MAX(chart->w, 2 * style->padding.x); 24067 chart->h = NK_MAX(chart->h, 2 * style->padding.y); 24068 24069 /* add first slot into chart */ 24070 {struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 24071 slot->type = type; 24072 slot->count = count; 24073 slot->color = color; 24074 slot->highlight = highlight; 24075 slot->min = NK_MIN(min_value, max_value); 24076 slot->max = NK_MAX(min_value, max_value); 24077 slot->range = slot->max - slot->min;} 24078 24079 /* draw chart background */ 24080 background = &style->background; 24081 if (background->type == NK_STYLE_ITEM_IMAGE) { 24082 nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white); 24083 } else { 24084 nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color); 24085 nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border), 24086 style->rounding, style->background.data.color); 24087 } 24088 return 1; 24089 } 24090 NK_API int 24091 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type, 24092 int count, float min_value, float max_value) 24093 { 24094 return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, 24095 ctx->style.chart.selected_color, count, min_value, max_value); 24096 } 24097 NK_API void 24098 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type, 24099 struct nk_color color, struct nk_color highlight, 24100 int count, float min_value, float max_value) 24101 { 24102 NK_ASSERT(ctx); 24103 NK_ASSERT(ctx->current); 24104 NK_ASSERT(ctx->current->layout); 24105 NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT); 24106 if (!ctx || !ctx->current || !ctx->current->layout) return; 24107 if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return; 24108 24109 /* add another slot into the graph */ 24110 {struct nk_chart *chart = &ctx->current->layout->chart; 24111 struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 24112 slot->type = type; 24113 slot->count = count; 24114 slot->color = color; 24115 slot->highlight = highlight; 24116 slot->min = NK_MIN(min_value, max_value); 24117 slot->max = NK_MAX(min_value, max_value); 24118 slot->range = slot->max - slot->min;} 24119 } 24120 NK_API void 24121 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type, 24122 int count, float min_value, float max_value) 24123 { 24124 nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, 24125 ctx->style.chart.selected_color, count, min_value, max_value); 24126 } 24127 NK_INTERN nk_flags 24128 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win, 24129 struct nk_chart *g, float value, int slot) 24130 { 24131 struct nk_panel *layout = win->layout; 24132 const struct nk_input *i = &ctx->input; 24133 struct nk_command_buffer *out = &win->buffer; 24134 24135 nk_flags ret = 0; 24136 struct nk_vec2 cur; 24137 struct nk_rect bounds; 24138 struct nk_color color; 24139 float step; 24140 float range; 24141 float ratio; 24142 24143 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24144 step = g->w / (float)g->slots[slot].count; 24145 range = g->slots[slot].max - g->slots[slot].min; 24146 ratio = (value - g->slots[slot].min) / range; 24147 24148 if (g->slots[slot].index == 0) { 24149 /* first data point does not have a connection */ 24150 g->slots[slot].last.x = g->x; 24151 g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h; 24152 24153 bounds.x = g->slots[slot].last.x - 2; 24154 bounds.y = g->slots[slot].last.y - 2; 24155 bounds.w = bounds.h = 4; 24156 24157 color = g->slots[slot].color; 24158 if (!(layout->flags & NK_WINDOW_ROM) && 24159 NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){ 24160 ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0; 24161 ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down && 24162 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24163 color = g->slots[slot].highlight; 24164 } 24165 nk_fill_rect(out, bounds, 0, color); 24166 g->slots[slot].index += 1; 24167 return ret; 24168 } 24169 24170 /* draw a line between the last data point and the new one */ 24171 color = g->slots[slot].color; 24172 cur.x = g->x + (float)(step * (float)g->slots[slot].index); 24173 cur.y = (g->y + g->h) - (ratio * (float)g->h); 24174 nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color); 24175 24176 bounds.x = cur.x - 3; 24177 bounds.y = cur.y - 3; 24178 bounds.w = bounds.h = 6; 24179 24180 /* user selection of current data point */ 24181 if (!(layout->flags & NK_WINDOW_ROM)) { 24182 if (nk_input_is_mouse_hovering_rect(i, bounds)) { 24183 ret = NK_CHART_HOVERING; 24184 ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down && 24185 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24186 color = g->slots[slot].highlight; 24187 } 24188 } 24189 nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); 24190 24191 /* save current data point position */ 24192 g->slots[slot].last.x = cur.x; 24193 g->slots[slot].last.y = cur.y; 24194 g->slots[slot].index += 1; 24195 return ret; 24196 } 24197 NK_INTERN nk_flags 24198 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win, 24199 struct nk_chart *chart, float value, int slot) 24200 { 24201 struct nk_command_buffer *out = &win->buffer; 24202 const struct nk_input *in = &ctx->input; 24203 struct nk_panel *layout = win->layout; 24204 24205 float ratio; 24206 nk_flags ret = 0; 24207 struct nk_color color; 24208 struct nk_rect item = {0,0,0,0}; 24209 24210 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24211 if (chart->slots[slot].index >= chart->slots[slot].count) 24212 return nk_false; 24213 if (chart->slots[slot].count) { 24214 float padding = (float)(chart->slots[slot].count-1); 24215 item.w = (chart->w - padding) / (float)(chart->slots[slot].count); 24216 } 24217 24218 /* calculate bounds of current bar chart entry */ 24219 color = chart->slots[slot].color;; 24220 item.h = chart->h * NK_ABS((value/chart->slots[slot].range)); 24221 if (value >= 0) { 24222 ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range); 24223 item.y = (chart->y + chart->h) - chart->h * ratio; 24224 } else { 24225 ratio = (value - chart->slots[slot].max) / chart->slots[slot].range; 24226 item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h; 24227 } 24228 item.x = chart->x + ((float)chart->slots[slot].index * item.w); 24229 item.x = item.x + ((float)chart->slots[slot].index); 24230 24231 /* user chart bar selection */ 24232 if (!(layout->flags & NK_WINDOW_ROM) && 24233 NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) { 24234 ret = NK_CHART_HOVERING; 24235 ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down && 24236 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24237 color = chart->slots[slot].highlight; 24238 } 24239 nk_fill_rect(out, item, 0, color); 24240 chart->slots[slot].index += 1; 24241 return ret; 24242 } 24243 NK_API nk_flags 24244 nk_chart_push_slot(struct nk_context *ctx, float value, int slot) 24245 { 24246 nk_flags flags; 24247 struct nk_window *win; 24248 24249 NK_ASSERT(ctx); 24250 NK_ASSERT(ctx->current); 24251 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24252 NK_ASSERT(slot < ctx->current->layout->chart.slot); 24253 if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false; 24254 if (slot >= ctx->current->layout->chart.slot) return nk_false; 24255 24256 win = ctx->current; 24257 if (win->layout->chart.slot < slot) return nk_false; 24258 switch (win->layout->chart.slots[slot].type) { 24259 case NK_CHART_LINES: 24260 flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break; 24261 case NK_CHART_COLUMN: 24262 flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break; 24263 default: 24264 case NK_CHART_MAX: 24265 flags = 0; 24266 } 24267 return flags; 24268 } 24269 NK_API nk_flags 24270 nk_chart_push(struct nk_context *ctx, float value) 24271 { 24272 return nk_chart_push_slot(ctx, value, 0); 24273 } 24274 NK_API void 24275 nk_chart_end(struct nk_context *ctx) 24276 { 24277 struct nk_window *win; 24278 struct nk_chart *chart; 24279 24280 NK_ASSERT(ctx); 24281 NK_ASSERT(ctx->current); 24282 if (!ctx || !ctx->current) 24283 return; 24284 24285 win = ctx->current; 24286 chart = &win->layout->chart; 24287 NK_MEMSET(chart, 0, sizeof(*chart)); 24288 return; 24289 } 24290 NK_API void 24291 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values, 24292 int count, int offset) 24293 { 24294 int i = 0; 24295 float min_value; 24296 float max_value; 24297 24298 NK_ASSERT(ctx); 24299 NK_ASSERT(values); 24300 if (!ctx || !values || !count) return; 24301 24302 min_value = values[offset]; 24303 max_value = values[offset]; 24304 for (i = 0; i < count; ++i) { 24305 min_value = NK_MIN(values[i + offset], min_value); 24306 max_value = NK_MAX(values[i + offset], max_value); 24307 } 24308 24309 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 24310 for (i = 0; i < count; ++i) 24311 nk_chart_push(ctx, values[i + offset]); 24312 nk_chart_end(ctx); 24313 } 24314 } 24315 NK_API void 24316 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata, 24317 float(*value_getter)(void* user, int index), int count, int offset) 24318 { 24319 int i = 0; 24320 float min_value; 24321 float max_value; 24322 24323 NK_ASSERT(ctx); 24324 NK_ASSERT(value_getter); 24325 if (!ctx || !value_getter || !count) return; 24326 24327 max_value = min_value = value_getter(userdata, offset); 24328 for (i = 0; i < count; ++i) { 24329 float value = value_getter(userdata, i + offset); 24330 min_value = NK_MIN(value, min_value); 24331 max_value = NK_MAX(value, max_value); 24332 } 24333 24334 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 24335 for (i = 0; i < count; ++i) 24336 nk_chart_push(ctx, value_getter(userdata, i + offset)); 24337 nk_chart_end(ctx); 24338 } 24339 } 24340 24341 24342 24343 24344 24345 /* ============================================================== 24346 * 24347 * COLOR PICKER 24348 * 24349 * ===============================================================*/ 24350 NK_LIB int 24351 nk_color_picker_behavior(nk_flags *state, 24352 const struct nk_rect *bounds, const struct nk_rect *matrix, 24353 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 24354 struct nk_colorf *color, const struct nk_input *in) 24355 { 24356 float hsva[4]; 24357 int value_changed = 0; 24358 int hsv_changed = 0; 24359 24360 NK_ASSERT(state); 24361 NK_ASSERT(matrix); 24362 NK_ASSERT(hue_bar); 24363 NK_ASSERT(color); 24364 24365 /* color matrix */ 24366 nk_colorf_hsva_fv(hsva, *color); 24367 if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) { 24368 hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); 24369 hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); 24370 value_changed = hsv_changed = 1; 24371 } 24372 /* hue bar */ 24373 if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) { 24374 hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); 24375 value_changed = hsv_changed = 1; 24376 } 24377 /* alpha bar */ 24378 if (alpha_bar) { 24379 if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) { 24380 hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); 24381 value_changed = 1; 24382 } 24383 } 24384 nk_widget_state_reset(state); 24385 if (hsv_changed) { 24386 *color = nk_hsva_colorfv(hsva); 24387 *state = NK_WIDGET_STATE_ACTIVE; 24388 } 24389 if (value_changed) { 24390 color->a = hsva[3]; 24391 *state = NK_WIDGET_STATE_ACTIVE; 24392 } 24393 /* set color picker widget state */ 24394 if (nk_input_is_mouse_hovering_rect(in, *bounds)) 24395 *state = NK_WIDGET_STATE_HOVERED; 24396 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 24397 *state |= NK_WIDGET_STATE_ENTERED; 24398 else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 24399 *state |= NK_WIDGET_STATE_LEFT; 24400 return value_changed; 24401 } 24402 NK_LIB void 24403 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, 24404 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 24405 struct nk_colorf col) 24406 { 24407 NK_STORAGE const struct nk_color black = {0,0,0,255}; 24408 NK_STORAGE const struct nk_color white = {255, 255, 255, 255}; 24409 NK_STORAGE const struct nk_color black_trans = {0,0,0,0}; 24410 24411 const float crosshair_size = 7.0f; 24412 struct nk_color temp; 24413 float hsva[4]; 24414 float line_y; 24415 int i; 24416 24417 NK_ASSERT(o); 24418 NK_ASSERT(matrix); 24419 NK_ASSERT(hue_bar); 24420 24421 /* draw hue bar */ 24422 nk_colorf_hsva_fv(hsva, col); 24423 for (i = 0; i < 6; ++i) { 24424 NK_GLOBAL const struct nk_color hue_colors[] = { 24425 {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255}, 24426 {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255} 24427 }; 24428 nk_fill_rect_multi_color(o, 24429 nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, 24430 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], 24431 hue_colors[i+1], hue_colors[i+1]); 24432 } 24433 line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); 24434 nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, 24435 line_y, 1, nk_rgb(255,255,255)); 24436 24437 /* draw alpha bar */ 24438 if (alpha_bar) { 24439 float alpha = NK_SATURATE(col.a); 24440 line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); 24441 24442 nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); 24443 nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, 24444 line_y, 1, nk_rgb(255,255,255)); 24445 } 24446 24447 /* draw color matrix */ 24448 temp = nk_hsv_f(hsva[0], 1.0f, 1.0f); 24449 nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white); 24450 nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); 24451 24452 /* draw cross-hair */ 24453 {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2]; 24454 p.x = (float)(int)(matrix->x + S * matrix->w); 24455 p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h); 24456 nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); 24457 nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white); 24458 nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white); 24459 nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);} 24460 } 24461 NK_LIB int 24462 nk_do_color_picker(nk_flags *state, 24463 struct nk_command_buffer *out, struct nk_colorf *col, 24464 enum nk_color_format fmt, struct nk_rect bounds, 24465 struct nk_vec2 padding, const struct nk_input *in, 24466 const struct nk_user_font *font) 24467 { 24468 int ret = 0; 24469 struct nk_rect matrix; 24470 struct nk_rect hue_bar; 24471 struct nk_rect alpha_bar; 24472 float bar_w; 24473 24474 NK_ASSERT(out); 24475 NK_ASSERT(col); 24476 NK_ASSERT(state); 24477 NK_ASSERT(font); 24478 if (!out || !col || !state || !font) 24479 return ret; 24480 24481 bar_w = font->height; 24482 bounds.x += padding.x; 24483 bounds.y += padding.x; 24484 bounds.w -= 2 * padding.x; 24485 bounds.h -= 2 * padding.y; 24486 24487 matrix.x = bounds.x; 24488 matrix.y = bounds.y; 24489 matrix.h = bounds.h; 24490 matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); 24491 24492 hue_bar.w = bar_w; 24493 hue_bar.y = bounds.y; 24494 hue_bar.h = matrix.h; 24495 hue_bar.x = matrix.x + matrix.w + padding.x; 24496 24497 alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; 24498 alpha_bar.y = bounds.y; 24499 alpha_bar.w = bar_w; 24500 alpha_bar.h = matrix.h; 24501 24502 ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar, 24503 (fmt == NK_RGBA) ? &alpha_bar:0, col, in); 24504 nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col); 24505 return ret; 24506 } 24507 NK_API int 24508 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color, 24509 enum nk_color_format fmt) 24510 { 24511 struct nk_window *win; 24512 struct nk_panel *layout; 24513 const struct nk_style *config; 24514 const struct nk_input *in; 24515 24516 enum nk_widget_layout_states state; 24517 struct nk_rect bounds; 24518 24519 NK_ASSERT(ctx); 24520 NK_ASSERT(color); 24521 NK_ASSERT(ctx->current); 24522 NK_ASSERT(ctx->current->layout); 24523 if (!ctx || !ctx->current || !ctx->current->layout || !color) 24524 return 0; 24525 24526 win = ctx->current; 24527 config = &ctx->style; 24528 layout = win->layout; 24529 state = nk_widget(&bounds, ctx); 24530 if (!state) return 0; 24531 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24532 return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds, 24533 nk_vec2(0,0), in, config->font); 24534 } 24535 NK_API struct nk_colorf 24536 nk_color_picker(struct nk_context *ctx, struct nk_colorf color, 24537 enum nk_color_format fmt) 24538 { 24539 nk_color_pick(ctx, &color, fmt); 24540 return color; 24541 } 24542 24543 24544 24545 24546 24547 /* ============================================================== 24548 * 24549 * COMBO 24550 * 24551 * ===============================================================*/ 24552 NK_INTERN int 24553 nk_combo_begin(struct nk_context *ctx, struct nk_window *win, 24554 struct nk_vec2 size, int is_clicked, struct nk_rect header) 24555 { 24556 struct nk_window *popup; 24557 int is_open = 0; 24558 int is_active = 0; 24559 struct nk_rect body; 24560 nk_hash hash; 24561 24562 NK_ASSERT(ctx); 24563 NK_ASSERT(ctx->current); 24564 NK_ASSERT(ctx->current->layout); 24565 if (!ctx || !ctx->current || !ctx->current->layout) 24566 return 0; 24567 24568 popup = win->popup.win; 24569 body.x = header.x; 24570 body.w = size.x; 24571 body.y = header.y + header.h-ctx->style.window.combo_border; 24572 body.h = size.y; 24573 24574 hash = win->popup.combo_count++; 24575 is_open = (popup) ? nk_true:nk_false; 24576 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO); 24577 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 24578 (!is_open && !is_active && !is_clicked)) return 0; 24579 if (!nk_nonblock_begin(ctx, 0, body, 24580 (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0; 24581 24582 win->popup.type = NK_PANEL_COMBO; 24583 win->popup.name = hash; 24584 return 1; 24585 } 24586 NK_API int 24587 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len, 24588 struct nk_vec2 size) 24589 { 24590 const struct nk_input *in; 24591 struct nk_window *win; 24592 struct nk_style *style; 24593 24594 enum nk_widget_layout_states s; 24595 int is_clicked = nk_false; 24596 struct nk_rect header; 24597 const struct nk_style_item *background; 24598 struct nk_text text; 24599 24600 NK_ASSERT(ctx); 24601 NK_ASSERT(selected); 24602 NK_ASSERT(ctx->current); 24603 NK_ASSERT(ctx->current->layout); 24604 if (!ctx || !ctx->current || !ctx->current->layout || !selected) 24605 return 0; 24606 24607 win = ctx->current; 24608 style = &ctx->style; 24609 s = nk_widget(&header, ctx); 24610 if (s == NK_WIDGET_INVALID) 24611 return 0; 24612 24613 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24614 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24615 is_clicked = nk_true; 24616 24617 /* draw combo box header background and border */ 24618 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24619 background = &style->combo.active; 24620 text.text = style->combo.label_active; 24621 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24622 background = &style->combo.hover; 24623 text.text = style->combo.label_hover; 24624 } else { 24625 background = &style->combo.normal; 24626 text.text = style->combo.label_normal; 24627 } 24628 if (background->type == NK_STYLE_ITEM_IMAGE) { 24629 text.background = nk_rgba(0,0,0,0); 24630 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24631 } else { 24632 text.background = background->data.color; 24633 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24634 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24635 } 24636 { 24637 /* print currently selected text item */ 24638 struct nk_rect label; 24639 struct nk_rect button; 24640 struct nk_rect content; 24641 24642 enum nk_symbol_type sym; 24643 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24644 sym = style->combo.sym_hover; 24645 else if (is_clicked) 24646 sym = style->combo.sym_active; 24647 else sym = style->combo.sym_normal; 24648 24649 /* calculate button */ 24650 button.w = header.h - 2 * style->combo.button_padding.y; 24651 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24652 button.y = header.y + style->combo.button_padding.y; 24653 button.h = button.w; 24654 24655 content.x = button.x + style->combo.button.padding.x; 24656 content.y = button.y + style->combo.button.padding.y; 24657 content.w = button.w - 2 * style->combo.button.padding.x; 24658 content.h = button.h - 2 * style->combo.button.padding.y; 24659 24660 /* draw selected label */ 24661 text.padding = nk_vec2(0,0); 24662 label.x = header.x + style->combo.content_padding.x; 24663 label.y = header.y + style->combo.content_padding.y; 24664 label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;; 24665 label.h = header.h - 2 * style->combo.content_padding.y; 24666 nk_widget_text(&win->buffer, label, selected, len, &text, 24667 NK_TEXT_LEFT, ctx->style.font); 24668 24669 /* draw open/close button */ 24670 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24671 &ctx->style.combo.button, sym, style->font); 24672 } 24673 return nk_combo_begin(ctx, win, size, is_clicked, header); 24674 } 24675 NK_API int 24676 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size) 24677 { 24678 return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size); 24679 } 24680 NK_API int 24681 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size) 24682 { 24683 struct nk_window *win; 24684 struct nk_style *style; 24685 const struct nk_input *in; 24686 24687 struct nk_rect header; 24688 int is_clicked = nk_false; 24689 enum nk_widget_layout_states s; 24690 const struct nk_style_item *background; 24691 24692 NK_ASSERT(ctx); 24693 NK_ASSERT(ctx->current); 24694 NK_ASSERT(ctx->current->layout); 24695 if (!ctx || !ctx->current || !ctx->current->layout) 24696 return 0; 24697 24698 win = ctx->current; 24699 style = &ctx->style; 24700 s = nk_widget(&header, ctx); 24701 if (s == NK_WIDGET_INVALID) 24702 return 0; 24703 24704 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24705 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24706 is_clicked = nk_true; 24707 24708 /* draw combo box header background and border */ 24709 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 24710 background = &style->combo.active; 24711 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24712 background = &style->combo.hover; 24713 else background = &style->combo.normal; 24714 24715 if (background->type == NK_STYLE_ITEM_IMAGE) { 24716 nk_draw_image(&win->buffer, header, &background->data.image,nk_white); 24717 } else { 24718 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24719 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24720 } 24721 { 24722 struct nk_rect content; 24723 struct nk_rect button; 24724 struct nk_rect bounds; 24725 24726 enum nk_symbol_type sym; 24727 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24728 sym = style->combo.sym_hover; 24729 else if (is_clicked) 24730 sym = style->combo.sym_active; 24731 else sym = style->combo.sym_normal; 24732 24733 /* calculate button */ 24734 button.w = header.h - 2 * style->combo.button_padding.y; 24735 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24736 button.y = header.y + style->combo.button_padding.y; 24737 button.h = button.w; 24738 24739 content.x = button.x + style->combo.button.padding.x; 24740 content.y = button.y + style->combo.button.padding.y; 24741 content.w = button.w - 2 * style->combo.button.padding.x; 24742 content.h = button.h - 2 * style->combo.button.padding.y; 24743 24744 /* draw color */ 24745 bounds.h = header.h - 4 * style->combo.content_padding.y; 24746 bounds.y = header.y + 2 * style->combo.content_padding.y; 24747 bounds.x = header.x + 2 * style->combo.content_padding.x; 24748 bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; 24749 nk_fill_rect(&win->buffer, bounds, 0, color); 24750 24751 /* draw open/close button */ 24752 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24753 &ctx->style.combo.button, sym, style->font); 24754 } 24755 return nk_combo_begin(ctx, win, size, is_clicked, header); 24756 } 24757 NK_API int 24758 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size) 24759 { 24760 struct nk_window *win; 24761 struct nk_style *style; 24762 const struct nk_input *in; 24763 24764 struct nk_rect header; 24765 int is_clicked = nk_false; 24766 enum nk_widget_layout_states s; 24767 const struct nk_style_item *background; 24768 struct nk_color sym_background; 24769 struct nk_color symbol_color; 24770 24771 NK_ASSERT(ctx); 24772 NK_ASSERT(ctx->current); 24773 NK_ASSERT(ctx->current->layout); 24774 if (!ctx || !ctx->current || !ctx->current->layout) 24775 return 0; 24776 24777 win = ctx->current; 24778 style = &ctx->style; 24779 s = nk_widget(&header, ctx); 24780 if (s == NK_WIDGET_INVALID) 24781 return 0; 24782 24783 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24784 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24785 is_clicked = nk_true; 24786 24787 /* draw combo box header background and border */ 24788 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24789 background = &style->combo.active; 24790 symbol_color = style->combo.symbol_active; 24791 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24792 background = &style->combo.hover; 24793 symbol_color = style->combo.symbol_hover; 24794 } else { 24795 background = &style->combo.normal; 24796 symbol_color = style->combo.symbol_hover; 24797 } 24798 24799 if (background->type == NK_STYLE_ITEM_IMAGE) { 24800 sym_background = nk_rgba(0,0,0,0); 24801 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24802 } else { 24803 sym_background = background->data.color; 24804 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24805 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24806 } 24807 { 24808 struct nk_rect bounds = {0,0,0,0}; 24809 struct nk_rect content; 24810 struct nk_rect button; 24811 24812 enum nk_symbol_type sym; 24813 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24814 sym = style->combo.sym_hover; 24815 else if (is_clicked) 24816 sym = style->combo.sym_active; 24817 else sym = style->combo.sym_normal; 24818 24819 /* calculate button */ 24820 button.w = header.h - 2 * style->combo.button_padding.y; 24821 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 24822 button.y = header.y + style->combo.button_padding.y; 24823 button.h = button.w; 24824 24825 content.x = button.x + style->combo.button.padding.x; 24826 content.y = button.y + style->combo.button.padding.y; 24827 content.w = button.w - 2 * style->combo.button.padding.x; 24828 content.h = button.h - 2 * style->combo.button.padding.y; 24829 24830 /* draw symbol */ 24831 bounds.h = header.h - 2 * style->combo.content_padding.y; 24832 bounds.y = header.y + style->combo.content_padding.y; 24833 bounds.x = header.x + style->combo.content_padding.x; 24834 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 24835 nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, 24836 1.0f, style->font); 24837 24838 /* draw open/close button */ 24839 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 24840 &ctx->style.combo.button, sym, style->font); 24841 } 24842 return nk_combo_begin(ctx, win, size, is_clicked, header); 24843 } 24844 NK_API int 24845 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len, 24846 enum nk_symbol_type symbol, struct nk_vec2 size) 24847 { 24848 struct nk_window *win; 24849 struct nk_style *style; 24850 struct nk_input *in; 24851 24852 struct nk_rect header; 24853 int is_clicked = nk_false; 24854 enum nk_widget_layout_states s; 24855 const struct nk_style_item *background; 24856 struct nk_color symbol_color; 24857 struct nk_text text; 24858 24859 NK_ASSERT(ctx); 24860 NK_ASSERT(ctx->current); 24861 NK_ASSERT(ctx->current->layout); 24862 if (!ctx || !ctx->current || !ctx->current->layout) 24863 return 0; 24864 24865 win = ctx->current; 24866 style = &ctx->style; 24867 s = nk_widget(&header, ctx); 24868 if (!s) return 0; 24869 24870 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24871 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24872 is_clicked = nk_true; 24873 24874 /* draw combo box header background and border */ 24875 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24876 background = &style->combo.active; 24877 symbol_color = style->combo.symbol_active; 24878 text.text = style->combo.label_active; 24879 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24880 background = &style->combo.hover; 24881 symbol_color = style->combo.symbol_hover; 24882 text.text = style->combo.label_hover; 24883 } else { 24884 background = &style->combo.normal; 24885 symbol_color = style->combo.symbol_normal; 24886 text.text = style->combo.label_normal; 24887 } 24888 if (background->type == NK_STYLE_ITEM_IMAGE) { 24889 text.background = nk_rgba(0,0,0,0); 24890 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24891 } else { 24892 text.background = background->data.color; 24893 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24894 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24895 } 24896 { 24897 struct nk_rect content; 24898 struct nk_rect button; 24899 struct nk_rect label; 24900 struct nk_rect image; 24901 24902 enum nk_symbol_type sym; 24903 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24904 sym = style->combo.sym_hover; 24905 else if (is_clicked) 24906 sym = style->combo.sym_active; 24907 else sym = style->combo.sym_normal; 24908 24909 /* calculate button */ 24910 button.w = header.h - 2 * style->combo.button_padding.y; 24911 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24912 button.y = header.y + style->combo.button_padding.y; 24913 button.h = button.w; 24914 24915 content.x = button.x + style->combo.button.padding.x; 24916 content.y = button.y + style->combo.button.padding.y; 24917 content.w = button.w - 2 * style->combo.button.padding.x; 24918 content.h = button.h - 2 * style->combo.button.padding.y; 24919 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24920 &ctx->style.combo.button, sym, style->font); 24921 24922 /* draw symbol */ 24923 image.x = header.x + style->combo.content_padding.x; 24924 image.y = header.y + style->combo.content_padding.y; 24925 image.h = header.h - 2 * style->combo.content_padding.y; 24926 image.w = image.h; 24927 nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, 24928 1.0f, style->font); 24929 24930 /* draw label */ 24931 text.padding = nk_vec2(0,0); 24932 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 24933 label.y = header.y + style->combo.content_padding.y; 24934 label.w = (button.x - style->combo.content_padding.x) - label.x; 24935 label.h = header.h - 2 * style->combo.content_padding.y; 24936 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 24937 } 24938 return nk_combo_begin(ctx, win, size, is_clicked, header); 24939 } 24940 NK_API int 24941 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) 24942 { 24943 struct nk_window *win; 24944 struct nk_style *style; 24945 const struct nk_input *in; 24946 24947 struct nk_rect header; 24948 int is_clicked = nk_false; 24949 enum nk_widget_layout_states s; 24950 const struct nk_style_item *background; 24951 24952 NK_ASSERT(ctx); 24953 NK_ASSERT(ctx->current); 24954 NK_ASSERT(ctx->current->layout); 24955 if (!ctx || !ctx->current || !ctx->current->layout) 24956 return 0; 24957 24958 win = ctx->current; 24959 style = &ctx->style; 24960 s = nk_widget(&header, ctx); 24961 if (s == NK_WIDGET_INVALID) 24962 return 0; 24963 24964 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24965 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24966 is_clicked = nk_true; 24967 24968 /* draw combo box header background and border */ 24969 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 24970 background = &style->combo.active; 24971 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24972 background = &style->combo.hover; 24973 else background = &style->combo.normal; 24974 24975 if (background->type == NK_STYLE_ITEM_IMAGE) { 24976 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24977 } else { 24978 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24979 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24980 } 24981 { 24982 struct nk_rect bounds = {0,0,0,0}; 24983 struct nk_rect content; 24984 struct nk_rect button; 24985 24986 enum nk_symbol_type sym; 24987 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24988 sym = style->combo.sym_hover; 24989 else if (is_clicked) 24990 sym = style->combo.sym_active; 24991 else sym = style->combo.sym_normal; 24992 24993 /* calculate button */ 24994 button.w = header.h - 2 * style->combo.button_padding.y; 24995 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 24996 button.y = header.y + style->combo.button_padding.y; 24997 button.h = button.w; 24998 24999 content.x = button.x + style->combo.button.padding.x; 25000 content.y = button.y + style->combo.button.padding.y; 25001 content.w = button.w - 2 * style->combo.button.padding.x; 25002 content.h = button.h - 2 * style->combo.button.padding.y; 25003 25004 /* draw image */ 25005 bounds.h = header.h - 2 * style->combo.content_padding.y; 25006 bounds.y = header.y + style->combo.content_padding.y; 25007 bounds.x = header.x + style->combo.content_padding.x; 25008 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 25009 nk_draw_image(&win->buffer, bounds, &img, nk_white); 25010 25011 /* draw open/close button */ 25012 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 25013 &ctx->style.combo.button, sym, style->font); 25014 } 25015 return nk_combo_begin(ctx, win, size, is_clicked, header); 25016 } 25017 NK_API int 25018 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, 25019 struct nk_image img, struct nk_vec2 size) 25020 { 25021 struct nk_window *win; 25022 struct nk_style *style; 25023 struct nk_input *in; 25024 25025 struct nk_rect header; 25026 int is_clicked = nk_false; 25027 enum nk_widget_layout_states s; 25028 const struct nk_style_item *background; 25029 struct nk_text text; 25030 25031 NK_ASSERT(ctx); 25032 NK_ASSERT(ctx->current); 25033 NK_ASSERT(ctx->current->layout); 25034 if (!ctx || !ctx->current || !ctx->current->layout) 25035 return 0; 25036 25037 win = ctx->current; 25038 style = &ctx->style; 25039 s = nk_widget(&header, ctx); 25040 if (!s) return 0; 25041 25042 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 25043 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 25044 is_clicked = nk_true; 25045 25046 /* draw combo box header background and border */ 25047 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 25048 background = &style->combo.active; 25049 text.text = style->combo.label_active; 25050 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 25051 background = &style->combo.hover; 25052 text.text = style->combo.label_hover; 25053 } else { 25054 background = &style->combo.normal; 25055 text.text = style->combo.label_normal; 25056 } 25057 if (background->type == NK_STYLE_ITEM_IMAGE) { 25058 text.background = nk_rgba(0,0,0,0); 25059 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 25060 } else { 25061 text.background = background->data.color; 25062 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 25063 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 25064 } 25065 { 25066 struct nk_rect content; 25067 struct nk_rect button; 25068 struct nk_rect label; 25069 struct nk_rect image; 25070 25071 enum nk_symbol_type sym; 25072 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 25073 sym = style->combo.sym_hover; 25074 else if (is_clicked) 25075 sym = style->combo.sym_active; 25076 else sym = style->combo.sym_normal; 25077 25078 /* calculate button */ 25079 button.w = header.h - 2 * style->combo.button_padding.y; 25080 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 25081 button.y = header.y + style->combo.button_padding.y; 25082 button.h = button.w; 25083 25084 content.x = button.x + style->combo.button.padding.x; 25085 content.y = button.y + style->combo.button.padding.y; 25086 content.w = button.w - 2 * style->combo.button.padding.x; 25087 content.h = button.h - 2 * style->combo.button.padding.y; 25088 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 25089 &ctx->style.combo.button, sym, style->font); 25090 25091 /* draw image */ 25092 image.x = header.x + style->combo.content_padding.x; 25093 image.y = header.y + style->combo.content_padding.y; 25094 image.h = header.h - 2 * style->combo.content_padding.y; 25095 image.w = image.h; 25096 nk_draw_image(&win->buffer, image, &img, nk_white); 25097 25098 /* draw label */ 25099 text.padding = nk_vec2(0,0); 25100 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 25101 label.y = header.y + style->combo.content_padding.y; 25102 label.w = (button.x - style->combo.content_padding.x) - label.x; 25103 label.h = header.h - 2 * style->combo.content_padding.y; 25104 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 25105 } 25106 return nk_combo_begin(ctx, win, size, is_clicked, header); 25107 } 25108 NK_API int 25109 nk_combo_begin_symbol_label(struct nk_context *ctx, 25110 const char *selected, enum nk_symbol_type type, struct nk_vec2 size) 25111 { 25112 return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size); 25113 } 25114 NK_API int 25115 nk_combo_begin_image_label(struct nk_context *ctx, 25116 const char *selected, struct nk_image img, struct nk_vec2 size) 25117 { 25118 return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size); 25119 } 25120 NK_API int 25121 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align) 25122 { 25123 return nk_contextual_item_text(ctx, text, len, align); 25124 } 25125 NK_API int 25126 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align) 25127 { 25128 return nk_contextual_item_label(ctx, label, align); 25129 } 25130 NK_API int 25131 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text, 25132 int len, nk_flags alignment) 25133 { 25134 return nk_contextual_item_image_text(ctx, img, text, len, alignment); 25135 } 25136 NK_API int 25137 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img, 25138 const char *text, nk_flags alignment) 25139 { 25140 return nk_contextual_item_image_label(ctx, img, text, alignment); 25141 } 25142 NK_API int 25143 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 25144 const char *text, int len, nk_flags alignment) 25145 { 25146 return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment); 25147 } 25148 NK_API int 25149 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 25150 const char *label, nk_flags alignment) 25151 { 25152 return nk_contextual_item_symbol_label(ctx, sym, label, alignment); 25153 } 25154 NK_API void nk_combo_end(struct nk_context *ctx) 25155 { 25156 nk_contextual_end(ctx); 25157 } 25158 NK_API void nk_combo_close(struct nk_context *ctx) 25159 { 25160 nk_contextual_close(ctx); 25161 } 25162 NK_API int 25163 nk_combo(struct nk_context *ctx, const char **items, int count, 25164 int selected, int item_height, struct nk_vec2 size) 25165 { 25166 int i = 0; 25167 int max_height; 25168 struct nk_vec2 item_spacing; 25169 struct nk_vec2 window_padding; 25170 25171 NK_ASSERT(ctx); 25172 NK_ASSERT(items); 25173 NK_ASSERT(ctx->current); 25174 if (!ctx || !items ||!count) 25175 return selected; 25176 25177 item_spacing = ctx->style.window.spacing; 25178 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25179 max_height = count * item_height + count * (int)item_spacing.y; 25180 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25181 size.y = NK_MIN(size.y, (float)max_height); 25182 if (nk_combo_begin_label(ctx, items[selected], size)) { 25183 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25184 for (i = 0; i < count; ++i) { 25185 if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) 25186 selected = i; 25187 } 25188 nk_combo_end(ctx); 25189 } 25190 return selected; 25191 } 25192 NK_API int 25193 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, 25194 int separator, int selected, int count, int item_height, struct nk_vec2 size) 25195 { 25196 int i; 25197 int max_height; 25198 struct nk_vec2 item_spacing; 25199 struct nk_vec2 window_padding; 25200 const char *current_item; 25201 const char *iter; 25202 int length = 0; 25203 25204 NK_ASSERT(ctx); 25205 NK_ASSERT(items_separated_by_separator); 25206 if (!ctx || !items_separated_by_separator) 25207 return selected; 25208 25209 /* calculate popup window */ 25210 item_spacing = ctx->style.window.spacing; 25211 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25212 max_height = count * item_height + count * (int)item_spacing.y; 25213 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25214 size.y = NK_MIN(size.y, (float)max_height); 25215 25216 /* find selected item */ 25217 current_item = items_separated_by_separator; 25218 for (i = 0; i < count; ++i) { 25219 iter = current_item; 25220 while (*iter && *iter != separator) iter++; 25221 length = (int)(iter - current_item); 25222 if (i == selected) break; 25223 current_item = iter + 1; 25224 } 25225 25226 if (nk_combo_begin_text(ctx, current_item, length, size)) { 25227 current_item = items_separated_by_separator; 25228 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25229 for (i = 0; i < count; ++i) { 25230 iter = current_item; 25231 while (*iter && *iter != separator) iter++; 25232 length = (int)(iter - current_item); 25233 if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) 25234 selected = i; 25235 current_item = current_item + length + 1; 25236 } 25237 nk_combo_end(ctx); 25238 } 25239 return selected; 25240 } 25241 NK_API int 25242 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros, 25243 int selected, int count, int item_height, struct nk_vec2 size) 25244 { 25245 return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size); 25246 } 25247 NK_API int 25248 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), 25249 void *userdata, int selected, int count, int item_height, struct nk_vec2 size) 25250 { 25251 int i; 25252 int max_height; 25253 struct nk_vec2 item_spacing; 25254 struct nk_vec2 window_padding; 25255 const char *item; 25256 25257 NK_ASSERT(ctx); 25258 NK_ASSERT(item_getter); 25259 if (!ctx || !item_getter) 25260 return selected; 25261 25262 /* calculate popup window */ 25263 item_spacing = ctx->style.window.spacing; 25264 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25265 max_height = count * item_height + count * (int)item_spacing.y; 25266 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25267 size.y = NK_MIN(size.y, (float)max_height); 25268 25269 item_getter(userdata, selected, &item); 25270 if (nk_combo_begin_label(ctx, item, size)) { 25271 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25272 for (i = 0; i < count; ++i) { 25273 item_getter(userdata, i, &item); 25274 if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) 25275 selected = i; 25276 } 25277 nk_combo_end(ctx); 25278 } return selected; 25279 } 25280 NK_API void 25281 nk_combobox(struct nk_context *ctx, const char **items, int count, 25282 int *selected, int item_height, struct nk_vec2 size) 25283 { 25284 *selected = nk_combo(ctx, items, count, *selected, item_height, size); 25285 } 25286 NK_API void 25287 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros, 25288 int *selected, int count, int item_height, struct nk_vec2 size) 25289 { 25290 *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size); 25291 } 25292 NK_API void 25293 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator, 25294 int separator,int *selected, int count, int item_height, struct nk_vec2 size) 25295 { 25296 *selected = nk_combo_separator(ctx, items_separated_by_separator, separator, 25297 *selected, count, item_height, size); 25298 } 25299 NK_API void 25300 nk_combobox_callback(struct nk_context *ctx, 25301 void(*item_getter)(void* data, int id, const char **out_text), 25302 void *userdata, int *selected, int count, int item_height, struct nk_vec2 size) 25303 { 25304 *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size); 25305 } 25306 25307 25308 25309 25310 25311 /* =============================================================== 25312 * 25313 * TOOLTIP 25314 * 25315 * ===============================================================*/ 25316 NK_API int 25317 nk_tooltip_begin(struct nk_context *ctx, float width) 25318 { 25319 int x,y,w,h; 25320 struct nk_window *win; 25321 const struct nk_input *in; 25322 struct nk_rect bounds; 25323 int ret; 25324 25325 NK_ASSERT(ctx); 25326 NK_ASSERT(ctx->current); 25327 NK_ASSERT(ctx->current->layout); 25328 if (!ctx || !ctx->current || !ctx->current->layout) 25329 return 0; 25330 25331 /* make sure that no nonblocking popup is currently active */ 25332 win = ctx->current; 25333 in = &ctx->input; 25334 if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK)) 25335 return 0; 25336 25337 w = nk_iceilf(width); 25338 h = nk_iceilf(nk_null_rect.h); 25339 x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x; 25340 y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y; 25341 25342 bounds.x = (float)x; 25343 bounds.y = (float)y; 25344 bounds.w = (float)w; 25345 bounds.h = (float)h; 25346 25347 ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC, 25348 "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds); 25349 if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 25350 win->popup.type = NK_PANEL_TOOLTIP; 25351 ctx->current->layout->type = NK_PANEL_TOOLTIP; 25352 return ret; 25353 } 25354 25355 NK_API void 25356 nk_tooltip_end(struct nk_context *ctx) 25357 { 25358 NK_ASSERT(ctx); 25359 NK_ASSERT(ctx->current); 25360 if (!ctx || !ctx->current) return; 25361 ctx->current->seq--; 25362 nk_popup_close(ctx); 25363 nk_popup_end(ctx); 25364 } 25365 NK_API void 25366 nk_tooltip(struct nk_context *ctx, const char *text) 25367 { 25368 const struct nk_style *style; 25369 struct nk_vec2 padding; 25370 25371 int text_len; 25372 float text_width; 25373 float text_height; 25374 25375 NK_ASSERT(ctx); 25376 NK_ASSERT(ctx->current); 25377 NK_ASSERT(ctx->current->layout); 25378 NK_ASSERT(text); 25379 if (!ctx || !ctx->current || !ctx->current->layout || !text) 25380 return; 25381 25382 /* fetch configuration data */ 25383 style = &ctx->style; 25384 padding = style->window.padding; 25385 25386 /* calculate size of the text and tooltip */ 25387 text_len = nk_strlen(text); 25388 text_width = style->font->width(style->font->userdata, 25389 style->font->height, text, text_len); 25390 text_width += (4 * padding.x); 25391 text_height = (style->font->height + 2 * padding.y); 25392 25393 /* execute tooltip and fill with text */ 25394 if (nk_tooltip_begin(ctx, (float)text_width)) { 25395 nk_layout_row_dynamic(ctx, (float)text_height, 1); 25396 nk_text(ctx, text, text_len, NK_TEXT_LEFT); 25397 nk_tooltip_end(ctx); 25398 } 25399 } 25400 #ifdef NK_INCLUDE_STANDARD_VARARGS 25401 NK_API void 25402 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...) 25403 { 25404 va_list args; 25405 va_start(args, fmt); 25406 nk_tooltipfv(ctx, fmt, args); 25407 va_end(args); 25408 } 25409 NK_API void 25410 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) 25411 { 25412 char buf[256]; 25413 nk_strfmt(buf, NK_LEN(buf), fmt, args); 25414 nk_tooltip(ctx, buf); 25415 } 25416 #endif 25417 25418 25419 25420 #endif /* NK_IMPLEMENTATION */ 25421 25422 /* 25423 /// ## License 25424 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 25425 /// ------------------------------------------------------------------------------ 25426 /// This software is available under 2 licenses -- choose whichever you prefer. 25427 /// ------------------------------------------------------------------------------ 25428 /// ALTERNATIVE A - MIT License 25429 /// Copyright (c) 2016-2018 Micha Mettke 25430 /// Permission is hereby granted, free of charge, to any person obtaining a copy of 25431 /// this software and associated documentation files (the "Software"), to deal in 25432 /// the Software without restriction, including without limitation the rights to 25433 /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 25434 /// of the Software, and to permit persons to whom the Software is furnished to do 25435 /// so, subject to the following conditions: 25436 /// The above copyright notice and this permission notice shall be included in all 25437 /// copies or substantial portions of the Software. 25438 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25439 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25440 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25441 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25442 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25443 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25444 /// SOFTWARE. 25445 /// ------------------------------------------------------------------------------ 25446 /// ALTERNATIVE B - Public Domain (www.unlicense.org) 25447 /// This is free and unencumbered software released into the public domain. 25448 /// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 25449 /// software, either in source code form or as a compiled binary, for any purpose, 25450 /// commercial or non-commercial, and by any means. 25451 /// In jurisdictions that recognize copyright laws, the author or authors of this 25452 /// software dedicate any and all copyright interest in the software to the public 25453 /// domain. We make this dedication for the benefit of the public at large and to 25454 /// the detriment of our heirs and successors. We intend this dedication to be an 25455 /// overt act of relinquishment in perpetuity of all present and future rights to 25456 /// this software under copyright law. 25457 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25458 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25459 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25460 /// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 25461 /// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25462 /// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25463 /// ------------------------------------------------------------------------------ 25464 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25465 25466 /// ## Changelog 25467 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 25468 /// [date][x.yy.zz]-[description] 25469 /// -[date]: date on which the change has been pushed 25470 /// -[x.yy.zz]: Numerical version string representation. Each version number on the right 25471 /// resets back to zero if version on the left is incremented. 25472 /// - [x]: Major version with API and library breaking changes 25473 /// - [yy]: Minor version with non-breaking API and library changes 25474 /// - [zz]: Bug fix version with no direct changes to API 25475 /// 25476 /// - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header 25477 /// when NK_BUTTON_TRIGGER_ON_RELEASE is defined. 25478 /// - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly. 25479 /// - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation 25480 /// fault due to dst_font->glyph_count not being zeroed on subsequent 25481 /// bakes of the same set of fonts. 25482 /// - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups. 25483 /// - 2019/06/12 (4.00.3) - Fix panel background drawing bug. 25484 /// - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends 25485 /// like GLFW without breaking key repeat behavior on event based. 25486 /// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame. 25487 /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to 25488 /// clear provided buffers. So make sure to either free 25489 /// or clear each passed buffer after calling nk_convert. 25490 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior. 25491 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process. 25492 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype. 25493 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug. 25494 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title. 25495 /// - 2018/01/07 (3.00.1) - Started to change documentation style. 25496 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken 25497 /// because of conversions between float and byte color representation. 25498 /// Color pickers now use floating point values to represent 25499 /// HSV values. To get back the old behavior I added some additional 25500 /// color conversion functions to cast between nk_color and 25501 /// nk_colorf. 25502 /// - 2017/12/23 (2.00.7) - Fixed small warning. 25503 /// - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input. 25504 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior. 25505 /// - 2017/12/04 (2.00.6) - Added formated string tooltip widget. 25506 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`. 25507 /// - 2017/11/15 (2.00.4) - Fixed font merging. 25508 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions. 25509 /// - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior. 25510 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior. 25511 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now 25512 /// require the name of the window and must happen outside the window 25513 /// building process (between function call nk_begin and nk_end). 25514 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last. 25515 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows. 25516 /// - 2017/08/27 (1.40.7) - Fixed window background flag. 25517 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked 25518 /// query for widgets. 25519 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked 25520 /// and filled rectangles. 25521 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in 25522 /// process of being destroyed. 25523 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in 25524 /// window instead of directly in table. 25525 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro. 25526 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero. 25527 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only 25528 /// comes in effect if you pass in zero was row height argument. 25529 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change 25530 /// how layouting works. From now there will be an internal minimum 25531 /// row height derived from font height. If you need a row smaller than 25532 /// that you can directly set it by `nk_layout_set_min_row_height` and 25533 /// reset the value back by calling `nk_layout_reset_min_row_height. 25534 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix. 25535 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function. 25536 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer. 25537 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped. 25538 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries. 25539 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space. 25540 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size. 25541 /// - 2017/05/06 (1.38.0) - Added platform double-click support. 25542 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends. 25543 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support. 25544 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing. 25545 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error. 25546 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags. 25547 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption. 25548 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows. 25549 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior. 25550 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377. 25551 /// - 2017/03/18 (1.34.3) - Fixed long window header titles. 25552 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering. 25553 /// - 2017/03/04 (1.34.1) - Fixed group closable flag. 25554 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support. 25555 /// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus. 25556 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows. 25557 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows. 25558 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing. 25559 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner. 25560 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both 25561 /// dynamic and static widgets. 25562 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit. 25563 /// - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows. 25564 /// - 2016/12/03 (1.29.1) - Fixed wrapped text with no seperator and C89 error. 25565 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters. 25566 /// - 2016/11/22 (1.28.6) - Fixed window minimized closing bug. 25567 /// - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior. 25568 /// - 2016/11/19 (1.28.4) - Fixed tooltip flickering. 25569 /// - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing. 25570 /// - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation. 25571 /// - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error. 25572 /// - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly 25573 /// pass in a style struct to change buttons visual. 25574 /// - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state 25575 /// storage. Just like last the `nk_group` commit the main 25576 /// advantage is that you optionally can minimize nuklears runtime 25577 /// memory consumption or handle hash collisions. 25578 /// - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar 25579 /// offset storage. Main advantage is that you can externalize 25580 /// the memory management for the offset. It could also be helpful 25581 /// if you have a hash collision in `nk_group_begin` but really 25582 /// want the name. In addition I added `nk_list_view` which allows 25583 /// to draw big lists inside a group without actually having to 25584 /// commit the whole list to nuklear (issue #269). 25585 /// - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`. 25586 /// - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of 25587 /// the hands of the user. From now on users don't have to care 25588 /// about panels unless they care about some information. If you 25589 /// still need the panel just call `nk_window_get_panel`. 25590 /// - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled 25591 /// rectangle for less overdraw and widget background transparency. 25592 /// - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control. 25593 /// - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `<stdint.h>` compilation. 25594 /// - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug. 25595 /// - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing. 25596 /// - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text 25597 /// text in every edit widget if one of them is scrolled. 25598 /// - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong 25599 /// text length is passed. It should have been in bytes but 25600 /// was passed as glyphes. 25601 /// - 2016/09/20 (1.22.2) - Fixed color button size calculation. 25602 /// - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `<stdio.h>` 25603 /// again from `NK_INCLUDE_STANDARD_VARARGS`. 25604 /// - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well 25605 /// as C++11 and newer. In addition to use vsnprintf you have 25606 /// to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS` 25607 /// is not enough. That behavior is now fixed. By default if 25608 /// both varargs as well as stdio is selected I try to use 25609 /// vsnprintf if not possible I will revert to vsprintf. If 25610 /// varargs but not stdio was defined I will use my own function. 25611 /// - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels. 25612 /// - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`. 25613 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo, 25614 /// and contextual which prevented closing in y-direction if 25615 /// popup did not reach max height. 25616 /// In addition the height parameter was changed into vec2 25617 /// for width and height to have more control over the popup size. 25618 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection. 25619 /// - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time 25620 /// all calculation are correct so no more hackery. 25621 /// - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types. 25622 /// Suprisinly spend years in C and still happened to confuse types 25623 /// with flags. Probably something to take note. 25624 /// - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just 25625 /// take the produced buffers from `nk_convert` and unplug the 25626 /// iteration process from `nk_context`. So now you can 25627 /// just use the vertex,element and command buffer + two pointer 25628 /// inside the command buffer retrieved by calls `nk__draw_begin` 25629 /// and `nk__draw_end` and macro `nk_draw_foreach_bounded`. 25630 /// - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call 25631 /// for windows, popups, combobox, menu and contextual is guarded by 25632 /// `if` condition and does not produce false drawing output. 25633 /// - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` 25634 /// to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and 25635 /// `NK_SYMBOL_RECT_OUTLINE`. 25636 /// - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` 25637 /// to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and 25638 /// `NK_SYMBOL_CIRCLE_OUTLINE`. 25639 /// - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` 25640 /// is not defined by supporting the biggest compiler GCC, clang and MSVC. 25641 /// - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error. 25642 /// - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation. 25643 /// - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL. 25644 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and 25645 /// instead made it user provided. The range of types to convert 25646 /// to is quite limited at the moment, but I would be more than 25647 /// happy to accept PRs to add additional. 25648 /// - 2016/08/30 (1.14.2) - Removed unused variables. 25649 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors. 25650 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly. 25651 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables. 25652 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would 25653 /// refrain from using slider with a big number of steps. 25654 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the 25655 /// window was in Read Only Mode. 25656 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just 25657 /// a hack for combo box and menu. 25658 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since 25659 /// it is bugged and causes issues in window selection. 25660 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now 25661 /// determined by the scrollbar size. 25662 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0. 25663 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection. 25664 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code 25665 /// handling panel padding and panel border. 25666 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`. 25667 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups. 25668 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes. 25669 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for 25670 /// hash collisions. Currently limited to `NK_WINDOW_MAX_NAME` 25671 /// which in term can be redefined if not big enough. 25672 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code. 25673 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released' 25674 /// to account for key press and release happening in one frame. 25675 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate. 25676 /// - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`. 25677 /// - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents. 25678 /// - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag 25679 /// `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep 25680 /// typing after commiting. 25681 /// - 2016/08/15 (1.09.4) - Removed redundant code. 25682 /// - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable. 25683 /// - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background 25684 /// window only as selected by hovering and not by clicking. 25685 /// - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading 25686 /// of glyphes for font with multiple ranges. 25687 /// - 2016/08/12 (1.09.1) - Added additional function to check if window is currently 25688 /// hidden and therefore not visible. 25689 /// - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` 25690 /// instead of the old flag `NK_WINDOW_HIDDEN`. 25691 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed 25692 /// the underlying implementation to not cast to float and instead 25693 /// work directly on the given values. 25694 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 25695 /// floating pointer number to string conversion for additional 25696 /// precision. 25697 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 25698 /// string to floating point number conversion for additional 25699 /// precision. 25700 /// - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`. 25701 /// - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading 25702 /// to wrong wiget width calculation which results in widgets falsly 25703 /// becomming tagged as not inside window and cannot be accessed. 25704 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and 25705 /// closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown 25706 /// by using `nk_window_show` and closed by either clicking the close 25707 /// icon in a window or by calling `nk_window_close`. Only closed 25708 /// windows get removed at the end of the frame while hidden windows 25709 /// remain. 25710 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to 25711 /// `nk_edit_string` which takes, edits and outputs a '\0' terminated string. 25712 /// - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior. 25713 /// - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`. 25714 /// - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating 25715 /// wrong item spacing and panel width. 25716 /// - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug. 25717 /// - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own 25718 /// define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine 25719 /// grained controlled over library includes. 25720 /// - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`. 25721 /// - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior. 25722 /// - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you 25723 /// move/scale a window and another window is behind it. 25724 /// If you are fast enough then the window behind gets activated 25725 /// and the operation is blocked. I now require activating 25726 /// by hovering only if mouse is not pressed. 25727 /// - 2016/08/04 (1.04.2) - Fixed changing fonts. 25728 /// - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior. 25729 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`. 25730 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for 25731 /// sub windows (combo, menu, ...). 25732 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor. 25733 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window 25734 /// to be always in the background of the screen. 25735 /// - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker. 25736 /// - 2016/08/01 (1.03.1) - Added helper macros into header include guard. 25737 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to 25738 /// simplify memory management by removing the need to 25739 /// allocate the pool. 25740 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled 25741 /// will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT 25742 /// seconds without window interaction. To make it work 25743 /// you have to also set a delta time inside the `nk_context`. 25744 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs. 25745 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`. 25746 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument. 25747 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified 25748 /// font atlas memory management by converting pointer 25749 /// arrays for fonts and font configurations to lists. 25750 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button 25751 /// behavior instead of passing it for every function call. 25752 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25753 /// ## Gallery 25754 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png) 25755 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png) 25756 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png) 25757 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png) 25758 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png) 25759 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png) 25760 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif) 25761 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png) 25762 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png) 25763 /// 25764 /// ## Credits 25765 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br /> 25766 /// 25767 /// 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 /> 25768 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br /> 25769 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br /> 25770 /// 25771 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and 25772 /// giving me the inspiration for this library, Casey Muratori for handmade hero 25773 /// and his original immediate mode graphical user interface idea and Sean 25774 /// Barret for his amazing single header libraries which restored my faith 25775 /// in libraries and brought me to create some of my own. Finally Apoorva Joshi 25776 /// for his single header file packer. 25777 */ 25778 25779