ScrapExplorer - nuklear.h

Home / ext / glfw / deps Lines: 11 | Size: 990828 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2/// # Nuklear 3/// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif) 4/// 5/// ## Contents 6/// 1. About section 7/// 2. Highlights section 8/// 3. Features section 9/// 4. Usage section 10/// 1. Flags section 11/// 2. Constants section 12/// 3. Dependencies section 13/// 5. Example section 14/// 6. API section 15/// 1. Context section 16/// 2. Input section 17/// 3. Drawing section 18/// 4. Window section 19/// 5. Layouting section 20/// 6. Groups section 21/// 7. Tree section 22/// 8. Properties section 23/// 7. License section 24/// 8. Changelog section 25/// 9. Gallery section 26/// 10. Credits section 27/// 28/// ## About 29/// This is a minimal state immediate mode graphical user interface toolkit 30/// written in ANSI C and licensed under public domain. It was designed as a simple 31/// embeddable user interface for application and does not have any dependencies, 32/// a default renderbackend or OS window and input handling but instead provides a very modular 33/// library approach by using simple input state for input and draw 34/// commands describing primitive shapes as output. So instead of providing a 35/// layered library that tries to abstract over a number of platform and 36/// render backends it only focuses on the actual UI. 37/// 38/// ## Highlights 39/// - Graphical user interface toolkit 40/// - Single header library 41/// - Written in C89 (a.k.a. ANSI C or ISO C90) 42/// - Small codebase (~18kLOC) 43/// - Focus on portability, efficiency and simplicity 44/// - No dependencies (not even the standard library if not wanted) 45/// - Fully skinnable and customizable 46/// - Low memory footprint with total memory control if needed or wanted 47/// - UTF-8 support 48/// - No global or hidden state 49/// - Customizable library modules (you can compile and use only what you need) 50/// - Optional font baker and vertex buffer output 51/// 52/// ## Features 53/// - Absolutely no platform dependent code 54/// - Memory management control ranging from/to 55/// - Ease of use by allocating everything from standard library 56/// - Control every byte of memory inside the library 57/// - Font handling control ranging from/to 58/// - Use your own font implementation for everything 59/// - Use this libraries internal font baking and handling API 60/// - Drawing output control ranging from/to 61/// - Simple shapes for more high level APIs which already have drawing capabilities 62/// - Hardware accessible anti-aliased vertex buffer output 63/// - Customizable colors and properties ranging from/to 64/// - Simple changes to color by filling a simple color table 65/// - Complete control with ability to use skinning to decorate widgets 66/// - Bendable UI library with widget ranging from/to 67/// - Basic widgets like buttons, checkboxes, slider, ... 68/// - Advanced widget like abstract comboboxes, contextual menus,... 69/// - Compile time configuration to only compile what you need 70/// - Subset which can be used if you do not want to link or use the standard library 71/// - Can be easily modified to only update on user input instead of frame updates 72/// 73/// ## Usage 74/// This library is self contained in one single header file and can be used either 75/// in header only mode or in implementation mode. The header only mode is used 76/// by default when included and allows including this header in other headers 77/// and does not contain the actual implementation. <br /><br /> 78/// 79/// The implementation mode requires to define the preprocessor macro 80/// NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.: 81/// 82/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C 83/// #define NK_IMPLEMENTATION 84/// #include "nuklear.h" 85/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 86/// 87/// Also optionally define the symbols listed in the section "OPTIONAL DEFINES" 88/// below in header and implementation mode if you want to use additional functionality 89/// or need more control over the library. 90/// 91/// !!! WARNING 92/// Every time nuklear is included define the same compiler flags. This very important not doing so could lead to compiler errors or even worse stack corruptions. 93/// 94/// ### Flags 95/// Flag | Description 96/// --------------------------------|------------------------------------------ 97/// NK_PRIVATE | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation 98/// NK_INCLUDE_FIXED_TYPES | If defined it will include header `<stdint.h>` for fixed sized types otherwise nuklear tries to select the correct type. If that fails it will throw a compiler error and you have to select the correct types yourself. 99/// NK_INCLUDE_DEFAULT_ALLOCATOR | If defined it will include header `<stdlib.h>` and provide additional functions to use this library without caring for memory allocation control and therefore ease memory management. 100/// NK_INCLUDE_STANDARD_IO | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading. 101/// NK_INCLUDE_STANDARD_VARARGS | If defined it will include header <stdio.h> and provide additional functions depending on file loading. 102/// NK_INCLUDE_VERTEX_BUFFER_OUTPUT | Defining this adds a vertex draw command list backend to this library, which allows you to convert queue commands into vertex draw commands. This is mainly if you need a hardware accessible format for OpenGL, DirectX, Vulkan, Metal,... 103/// NK_INCLUDE_FONT_BAKING | Defining this adds `stb_truetype` and `stb_rect_pack` implementation to this library and provides font baking and rendering. If you already have font handling or do not want to use this font handler you don't have to define it. 104/// NK_INCLUDE_DEFAULT_FONT | Defining this adds the default font: ProggyClean.ttf into this library which can be loaded into a font atlas and allows using this library without having a truetype font 105/// NK_INCLUDE_COMMAND_USERDATA | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures. 106/// NK_BUTTON_TRIGGER_ON_RELEASE | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released. 107/// NK_ZERO_COMMAND_MEMORY | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame. 108/// 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/// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png) 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 224extern "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 399typedef NK_INT8 nk_char; 400typedef NK_UINT8 nk_uchar; 401typedef NK_UINT8 nk_byte; 402typedef NK_INT16 nk_short; 403typedef NK_UINT16 nk_ushort; 404typedef NK_INT32 nk_int; 405typedef NK_UINT32 nk_uint; 406typedef NK_SIZE_TYPE nk_size; 407typedef NK_POINTER_TYPE nk_ptr; 408 409typedef nk_uint nk_hash; 410typedef nk_uint nk_flags; 411typedef 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 */ 416NK_STATIC_ASSERT(sizeof(nk_short) == 2); 417NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 418NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 419NK_STATIC_ASSERT(sizeof(nk_int) == 4); 420NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 421NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 422NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 423NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 424NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); 425 426#if defined(_MSC_VER) 427/* disable `operands are different enum types` warning on MSVC */ 428#pragma warning( disable: 5287 ) 429#endif 430 431/* ============================================================================ 432 * 433 * API 434 * 435 * =========================================================================== */ 436struct nk_buffer; 437struct nk_allocator; 438struct nk_command_buffer; 439struct nk_draw_command; 440struct nk_convert_config; 441struct nk_style_item; 442struct nk_text_edit; 443struct nk_draw_list; 444struct nk_user_font; 445struct nk_panel; 446struct nk_context; 447struct nk_draw_vertex_layout_element; 448struct nk_style_button; 449struct nk_style_toggle; 450struct nk_style_selectable; 451struct nk_style_slide; 452struct nk_style_progress; 453struct nk_style_scrollbar; 454struct nk_style_edit; 455struct nk_style_property; 456struct nk_style_chart; 457struct nk_style_combo; 458struct nk_style_tab; 459struct nk_style_window_header; 460struct nk_style_window; 461 462enum {nk_false, nk_true}; 463struct nk_color {nk_byte r,g,b,a;}; 464struct nk_colorf {float r,g,b,a;}; 465struct nk_vec2 {float x,y;}; 466struct nk_vec2i {short x, y;}; 467struct nk_rect {float x,y,w,h;}; 468struct nk_recti {short x,y,w,h;}; 469typedef char nk_glyph[NK_UTF_SIZE]; 470typedef union {void *ptr; int id;} nk_handle; 471struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];}; 472struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;}; 473struct nk_scroll {nk_uint x, y;}; 474 475enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT}; 476enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER}; 477enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true}; 478enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL}; 479enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true}; 480enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true}; 481enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX}; 482enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02}; 483enum nk_color_format {NK_RGB, NK_RGBA}; 484enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC}; 485enum nk_layout_format {NK_DYNAMIC, NK_STATIC}; 486enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB}; 487 488typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size); 489typedef void (*nk_plugin_free)(nk_handle, void *old); 490typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode); 491typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*); 492typedef void(*nk_plugin_copy)(nk_handle, const char*, int len); 493 494struct nk_allocator { 495 nk_handle userdata; 496 nk_plugin_alloc alloc; 497 nk_plugin_free free; 498}; 499enum nk_symbol_type { 500 NK_SYMBOL_NONE, 501 NK_SYMBOL_X, 502 NK_SYMBOL_UNDERSCORE, 503 NK_SYMBOL_CIRCLE_SOLID, 504 NK_SYMBOL_CIRCLE_OUTLINE, 505 NK_SYMBOL_RECT_SOLID, 506 NK_SYMBOL_RECT_OUTLINE, 507 NK_SYMBOL_TRIANGLE_UP, 508 NK_SYMBOL_TRIANGLE_DOWN, 509 NK_SYMBOL_TRIANGLE_LEFT, 510 NK_SYMBOL_TRIANGLE_RIGHT, 511 NK_SYMBOL_PLUS, 512 NK_SYMBOL_MINUS, 513 NK_SYMBOL_MAX 514}; 515/* ============================================================================= 516 * 517 * CONTEXT 518 * 519 * =============================================================================*/ 520/*/// ### Context 521/// Contexts are the main entry point and the majestro of nuklear and contain all required state. 522/// They are used for window, memory, input, style, stack, commands and time management and need 523/// to be passed into all nuklear GUI specific functions. 524/// 525/// #### Usage 526/// To use a context it first has to be initialized which can be achieved by calling 527/// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`. 528/// Each takes in a font handle and a specific way of handling memory. Memory control 529/// hereby ranges from standard library to just specifying a fixed sized block of memory 530/// which nuklear has to manage itself from. 531/// 532/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 533/// struct nk_context ctx; 534/// nk_init_xxx(&ctx, ...); 535/// while (1) { 536/// // [...] 537/// nk_clear(&ctx); 538/// } 539/// nk_free(&ctx); 540/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 541/// 542/// #### Reference 543/// Function | Description 544/// --------------------|------------------------------------------------------- 545/// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free) 546/// __nk_init_fixed__ | Initializes context from single fixed size memory block 547/// __nk_init__ | Initializes context with memory allocator callbacks for alloc and free 548/// __nk_init_custom__ | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations 549/// __nk_clear__ | Called at the end of the frame to reset and prepare the context for the next frame 550/// __nk_free__ | Shutdown and free all memory allocated inside the context 551/// __nk_set_user_data__| Utility function to pass user data to draw command 552 */ 553#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 554/*/// #### nk_init_default 555/// Initializes a `nk_context` struct with a default standard library allocator. 556/// Should be used if you don't want to be bothered with memory management in nuklear. 557/// 558/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 559/// int nk_init_default(struct nk_context *ctx, const struct nk_user_font *font); 560/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 561/// 562/// Parameter | Description 563/// ------------|--------------------------------------------------------------- 564/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 565/// __font__ | Must point to a previously initialized font handle for more info look at font documentation 566/// 567/// Returns either `false(0)` on failure or `true(1)` on success. 568/// 569*/ 570NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*); 571#endif 572/*/// #### nk_init_fixed 573/// Initializes a `nk_context` struct from single fixed size memory block 574/// Should be used if you want complete control over nuklear's memory management. 575/// Especially recommended for system with little memory or systems with virtual memory. 576/// For the later case you can just allocate for example 16MB of virtual memory 577/// and only the required amount of memory will actually be committed. 578/// 579/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 580/// int nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font); 581/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 582/// 583/// !!! Warning 584/// make sure the passed memory block is aligned correctly for `nk_draw_commands`. 585/// 586/// Parameter | Description 587/// ------------|-------------------------------------------------------------- 588/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 589/// __memory__ | Must point to a previously allocated memory block 590/// __size__ | Must contain the total size of __memory__ 591/// __font__ | Must point to a previously initialized font handle for more info look at font documentation 592/// 593/// Returns either `false(0)` on failure or `true(1)` on success. 594*/ 595NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*); 596/*/// #### nk_init 597/// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate 598/// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation 599/// interface to nuklear. Can be useful for cases like monitoring memory consumption. 600/// 601/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 602/// int nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font); 603/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 604/// 605/// Parameter | Description 606/// ------------|--------------------------------------------------------------- 607/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 608/// __alloc__ | Must point to a previously allocated memory allocator 609/// __font__ | Must point to a previously initialized font handle for more info look at font documentation 610/// 611/// Returns either `false(0)` on failure or `true(1)` on success. 612*/ 613NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*); 614/*/// #### nk_init_custom 615/// Initializes a `nk_context` struct from two different either fixed or growing 616/// buffers. The first buffer is for allocating draw commands while the second buffer is 617/// used for allocating windows, panels and state tables. 618/// 619/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 620/// int nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font); 621/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 622/// 623/// Parameter | Description 624/// ------------|--------------------------------------------------------------- 625/// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 626/// __cmds__ | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into 627/// __pool__ | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables 628/// __font__ | Must point to a previously initialized font handle for more info look at font documentation 629/// 630/// Returns either `false(0)` on failure or `true(1)` on success. 631*/ 632NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*); 633/*/// #### nk_clear 634/// Resets the context state at the end of the frame. This includes mostly 635/// garbage collector tasks like removing windows or table not called and therefore 636/// used anymore. 637/// 638/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 639/// void nk_clear(struct nk_context *ctx); 640/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 641/// 642/// Parameter | Description 643/// ------------|----------------------------------------------------------- 644/// __ctx__ | Must point to a previously initialized `nk_context` struct 645*/ 646NK_API void nk_clear(struct nk_context*); 647/*/// #### nk_free 648/// Frees all memory allocated by nuklear. Not needed if context was 649/// initialized with `nk_init_fixed`. 650/// 651/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 652/// void nk_free(struct nk_context *ctx); 653/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 654/// 655/// Parameter | Description 656/// ------------|----------------------------------------------------------- 657/// __ctx__ | Must point to a previously initialized `nk_context` struct 658*/ 659NK_API void nk_free(struct nk_context*); 660#ifdef NK_INCLUDE_COMMAND_USERDATA 661/*/// #### nk_set_user_data 662/// Sets the currently passed userdata passed down into each draw command. 663/// 664/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 665/// void nk_set_user_data(struct nk_context *ctx, nk_handle data); 666/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 667/// 668/// Parameter | Description 669/// ------------|-------------------------------------------------------------- 670/// __ctx__ | Must point to a previously initialized `nk_context` struct 671/// __data__ | Handle with either pointer or index to be passed into every draw commands 672*/ 673NK_API void nk_set_user_data(struct nk_context*, nk_handle handle); 674#endif 675/* ============================================================================= 676 * 677 * INPUT 678 * 679 * =============================================================================*/ 680/*/// ### Input 681/// The input API is responsible for holding the current input state composed of 682/// mouse, key and text input states. 683/// It is worth noting that no direct OS or window handling is done in nuklear. 684/// Instead all input state has to be provided by platform specific code. This on one hand 685/// expects more work from the user and complicates usage but on the other hand 686/// provides simple abstraction over a big number of platforms, libraries and other 687/// already provided functionality. 688/// 689/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 690/// nk_input_begin(&ctx); 691/// while (GetEvent(&evt)) { 692/// if (evt.type == MOUSE_MOVE) 693/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 694/// else if (evt.type == [...]) { 695/// // [...] 696/// } 697/// } nk_input_end(&ctx); 698/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 699/// 700/// #### Usage 701/// Input state needs to be provided to nuklear by first calling `nk_input_begin` 702/// which resets internal state like delta mouse position and button transistions. 703/// After `nk_input_begin` all current input state needs to be provided. This includes 704/// mouse motion, button and key pressed and released, text input and scrolling. 705/// Both event- or state-based input handling are supported by this API 706/// and should work without problems. Finally after all input state has been 707/// mirrored `nk_input_end` needs to be called to finish input process. 708/// 709/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 710/// struct nk_context ctx; 711/// nk_init_xxx(&ctx, ...); 712/// while (1) { 713/// Event evt; 714/// nk_input_begin(&ctx); 715/// while (GetEvent(&evt)) { 716/// if (evt.type == MOUSE_MOVE) 717/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 718/// else if (evt.type == [...]) { 719/// // [...] 720/// } 721/// } 722/// nk_input_end(&ctx); 723/// // [...] 724/// nk_clear(&ctx); 725/// } nk_free(&ctx); 726/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 727/// 728/// #### Reference 729/// Function | Description 730/// --------------------|------------------------------------------------------- 731/// __nk_input_begin__ | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls 732/// __nk_input_motion__ | Mirrors mouse cursor position 733/// __nk_input_key__ | Mirrors key state with either pressed or released 734/// __nk_input_button__ | Mirrors mouse button state with either pressed or released 735/// __nk_input_scroll__ | Mirrors mouse scroll values 736/// __nk_input_char__ | Adds a single ASCII text character into an internal text buffer 737/// __nk_input_glyph__ | Adds a single multi-byte UTF-8 character into an internal text buffer 738/// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer 739/// __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 740*/ 741enum nk_keys { 742 NK_KEY_NONE, 743 NK_KEY_SHIFT, 744 NK_KEY_CTRL, 745 NK_KEY_DEL, 746 NK_KEY_ENTER, 747 NK_KEY_TAB, 748 NK_KEY_BACKSPACE, 749 NK_KEY_COPY, 750 NK_KEY_CUT, 751 NK_KEY_PASTE, 752 NK_KEY_UP, 753 NK_KEY_DOWN, 754 NK_KEY_LEFT, 755 NK_KEY_RIGHT, 756 /* Shortcuts: text field */ 757 NK_KEY_TEXT_INSERT_MODE, 758 NK_KEY_TEXT_REPLACE_MODE, 759 NK_KEY_TEXT_RESET_MODE, 760 NK_KEY_TEXT_LINE_START, 761 NK_KEY_TEXT_LINE_END, 762 NK_KEY_TEXT_START, 763 NK_KEY_TEXT_END, 764 NK_KEY_TEXT_UNDO, 765 NK_KEY_TEXT_REDO, 766 NK_KEY_TEXT_SELECT_ALL, 767 NK_KEY_TEXT_WORD_LEFT, 768 NK_KEY_TEXT_WORD_RIGHT, 769 /* Shortcuts: scrollbar */ 770 NK_KEY_SCROLL_START, 771 NK_KEY_SCROLL_END, 772 NK_KEY_SCROLL_DOWN, 773 NK_KEY_SCROLL_UP, 774 NK_KEY_MAX 775}; 776enum nk_buttons { 777 NK_BUTTON_LEFT, 778 NK_BUTTON_MIDDLE, 779 NK_BUTTON_RIGHT, 780 NK_BUTTON_DOUBLE, 781 NK_BUTTON_MAX 782}; 783/*/// #### nk_input_begin 784/// Begins the input mirroring process by resetting text, scroll 785/// mouse, previous mouse position and movement as well as key state transitions, 786/// 787/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 788/// void nk_input_begin(struct nk_context*); 789/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 790/// 791/// Parameter | Description 792/// ------------|----------------------------------------------------------- 793/// __ctx__ | Must point to a previously initialized `nk_context` struct 794*/ 795NK_API void nk_input_begin(struct nk_context*); 796/*/// #### nk_input_motion 797/// Mirrors current mouse position to nuklear 798/// 799/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 800/// void nk_input_motion(struct nk_context *ctx, int x, int y); 801/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 802/// 803/// Parameter | Description 804/// ------------|----------------------------------------------------------- 805/// __ctx__ | Must point to a previously initialized `nk_context` struct 806/// __x__ | Must hold an integer describing the current mouse cursor x-position 807/// __y__ | Must hold an integer describing the current mouse cursor y-position 808*/ 809NK_API void nk_input_motion(struct nk_context*, int x, int y); 810/*/// #### nk_input_key 811/// Mirrors the state of a specific key to nuklear 812/// 813/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 814/// void nk_input_key(struct nk_context*, enum nk_keys key, int down); 815/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 816/// 817/// Parameter | Description 818/// ------------|----------------------------------------------------------- 819/// __ctx__ | Must point to a previously initialized `nk_context` struct 820/// __key__ | Must be any value specified in enum `nk_keys` that needs to be mirrored 821/// __down__ | Must be 0 for key is up and 1 for key is down 822*/ 823NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down); 824/*/// #### nk_input_button 825/// Mirrors the state of a specific mouse button to nuklear 826/// 827/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 828/// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, int down); 829/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 830/// 831/// Parameter | Description 832/// ------------|----------------------------------------------------------- 833/// __ctx__ | Must point to a previously initialized `nk_context` struct 834/// __btn__ | Must be any value specified in enum `nk_buttons` that needs to be mirrored 835/// __x__ | Must contain an integer describing mouse cursor x-position on click up/down 836/// __y__ | Must contain an integer describing mouse cursor y-position on click up/down 837/// __down__ | Must be 0 for key is up and 1 for key is down 838*/ 839NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down); 840/*/// #### nk_input_scroll 841/// Copies the last mouse scroll value to nuklear. Is generally 842/// a scroll value. So does not have to come from mouse and could also originate 843/// TODO finish this sentence 844/// 845/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 846/// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val); 847/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 848/// 849/// Parameter | Description 850/// ------------|----------------------------------------------------------- 851/// __ctx__ | Must point to a previously initialized `nk_context` struct 852/// __val__ | vector with both X- as well as Y-scroll value 853*/ 854NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val); 855/*/// #### nk_input_char 856/// Copies a single ASCII character into an internal text buffer 857/// This is basically a helper function to quickly push ASCII characters into 858/// nuklear. 859/// 860/// !!! Note 861/// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 862/// 863/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 864/// void nk_input_char(struct nk_context *ctx, char c); 865/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 866/// 867/// Parameter | Description 868/// ------------|----------------------------------------------------------- 869/// __ctx__ | Must point to a previously initialized `nk_context` struct 870/// __c__ | Must be a single ASCII character preferable one that can be printed 871*/ 872NK_API void nk_input_char(struct nk_context*, char); 873/*/// #### nk_input_glyph 874/// Converts an encoded unicode rune into UTF-8 and copies the result into an 875/// internal text buffer. 876/// 877/// !!! Note 878/// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 879/// 880/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 881/// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g); 882/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 883/// 884/// Parameter | Description 885/// ------------|----------------------------------------------------------- 886/// __ctx__ | Must point to a previously initialized `nk_context` struct 887/// __g__ | UTF-32 unicode codepoint 888*/ 889NK_API void nk_input_glyph(struct nk_context*, const nk_glyph); 890/*/// #### nk_input_unicode 891/// Converts a unicode rune into UTF-8 and copies the result 892/// into an internal text buffer. 893/// !!! Note 894/// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 895/// 896/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 897/// void nk_input_unicode(struct nk_context*, nk_rune rune); 898/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 899/// 900/// Parameter | Description 901/// ------------|----------------------------------------------------------- 902/// __ctx__ | Must point to a previously initialized `nk_context` struct 903/// __rune__ | UTF-32 unicode codepoint 904*/ 905NK_API void nk_input_unicode(struct nk_context*, nk_rune); 906/*/// #### nk_input_end 907/// End the input mirroring process by resetting mouse grabbing 908/// state to ensure the mouse cursor is not grabbed indefinitely. 909/// 910/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 911/// void nk_input_end(struct nk_context *ctx); 912/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 913/// 914/// Parameter | Description 915/// ------------|----------------------------------------------------------- 916/// __ctx__ | Must point to a previously initialized `nk_context` struct 917*/ 918NK_API void nk_input_end(struct nk_context*); 919/* ============================================================================= 920 * 921 * DRAWING 922 * 923 * =============================================================================*/ 924/*/// ### Drawing 925/// This library was designed to be render backend agnostic so it does 926/// not draw anything to screen directly. Instead all drawn shapes, widgets 927/// are made of, are buffered into memory and make up a command queue. 928/// Each frame therefore fills the command buffer with draw commands 929/// that then need to be executed by the user and his own render backend. 930/// After that the command buffer needs to be cleared and a new frame can be 931/// started. It is probably important to note that the command buffer is the main 932/// drawing API and the optional vertex buffer API only takes this format and 933/// converts it into a hardware accessible format. 934/// 935/// #### Usage 936/// To draw all draw commands accumulated over a frame you need your own render 937/// backend able to draw a number of 2D primitives. This includes at least 938/// filled and stroked rectangles, circles, text, lines, triangles and scissors. 939/// As soon as this criterion is met you can iterate over each draw command 940/// and execute each draw command in a interpreter like fashion: 941/// 942/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 943/// const struct nk_command *cmd = 0; 944/// nk_foreach(cmd, &ctx) { 945/// switch (cmd->type) { 946/// case NK_COMMAND_LINE: 947/// your_draw_line_function(...) 948/// break; 949/// case NK_COMMAND_RECT 950/// your_draw_rect_function(...) 951/// break; 952/// case //...: 953/// //[...] 954/// } 955/// } 956/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 957/// 958/// In program flow context draw commands need to be executed after input has been 959/// gathered and the complete UI with windows and their contained widgets have 960/// been executed and before calling `nk_clear` which frees all previously 961/// allocated draw commands. 962/// 963/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 964/// struct nk_context ctx; 965/// nk_init_xxx(&ctx, ...); 966/// while (1) { 967/// Event evt; 968/// nk_input_begin(&ctx); 969/// while (GetEvent(&evt)) { 970/// if (evt.type == MOUSE_MOVE) 971/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 972/// else if (evt.type == [...]) { 973/// [...] 974/// } 975/// } 976/// nk_input_end(&ctx); 977/// // 978/// // [...] 979/// // 980/// const struct nk_command *cmd = 0; 981/// nk_foreach(cmd, &ctx) { 982/// switch (cmd->type) { 983/// case NK_COMMAND_LINE: 984/// your_draw_line_function(...) 985/// break; 986/// case NK_COMMAND_RECT 987/// your_draw_rect_function(...) 988/// break; 989/// case ...: 990/// // [...] 991/// } 992/// nk_clear(&ctx); 993/// } 994/// nk_free(&ctx); 995/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 996/// 997/// You probably noticed that you have to draw all of the UI each frame which is 998/// quite wasteful. While the actual UI updating loop is quite fast rendering 999/// without actually needing it is not. So there are multiple things you could do. 1000/// 1001/// First is only update on input. This of course is only an option if your 1002/// application only depends on the UI and does not require any outside calculations. 1003/// If you actually only update on input make sure to update the UI two times each 1004/// frame and call `nk_clear` directly after the first pass and only draw in 1005/// the second pass. In addition it is recommended to also add additional timers 1006/// to make sure the UI is not drawn more than a fixed number of frames per second. 1007/// 1008/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1009/// struct nk_context ctx; 1010/// nk_init_xxx(&ctx, ...); 1011/// while (1) { 1012/// // [...wait for input ] 1013/// // [...do two UI passes ...] 1014/// do_ui(...) 1015/// nk_clear(&ctx); 1016/// do_ui(...) 1017/// // 1018/// // draw 1019/// const struct nk_command *cmd = 0; 1020/// nk_foreach(cmd, &ctx) { 1021/// switch (cmd->type) { 1022/// case NK_COMMAND_LINE: 1023/// your_draw_line_function(...) 1024/// break; 1025/// case NK_COMMAND_RECT 1026/// your_draw_rect_function(...) 1027/// break; 1028/// case ...: 1029/// //[...] 1030/// } 1031/// nk_clear(&ctx); 1032/// } 1033/// nk_free(&ctx); 1034/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1035/// 1036/// The second probably more applicable trick is to only draw if anything changed. 1037/// It is not really useful for applications with continuous draw loop but 1038/// quite useful for desktop applications. To actually get nuklear to only 1039/// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and 1040/// allocate a memory buffer that will store each unique drawing output. 1041/// After each frame you compare the draw command memory inside the library 1042/// with your allocated buffer by memcmp. If memcmp detects differences 1043/// you have to copy the command buffer into the allocated buffer 1044/// and then draw like usual (this example uses fixed memory but you could 1045/// use dynamically allocated memory). 1046/// 1047/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1048/// //[... other defines ...] 1049/// #define NK_ZERO_COMMAND_MEMORY 1050/// #include "nuklear.h" 1051/// // 1052/// // setup context 1053/// struct nk_context ctx; 1054/// void *last = calloc(1,64*1024); 1055/// void *buf = calloc(1,64*1024); 1056/// nk_init_fixed(&ctx, buf, 64*1024); 1057/// // 1058/// // loop 1059/// while (1) { 1060/// // [...input...] 1061/// // [...ui...] 1062/// void *cmds = nk_buffer_memory(&ctx.memory); 1063/// if (memcmp(cmds, last, ctx.memory.allocated)) { 1064/// memcpy(last,cmds,ctx.memory.allocated); 1065/// const struct nk_command *cmd = 0; 1066/// nk_foreach(cmd, &ctx) { 1067/// switch (cmd->type) { 1068/// case NK_COMMAND_LINE: 1069/// your_draw_line_function(...) 1070/// break; 1071/// case NK_COMMAND_RECT 1072/// your_draw_rect_function(...) 1073/// break; 1074/// case ...: 1075/// // [...] 1076/// } 1077/// } 1078/// } 1079/// nk_clear(&ctx); 1080/// } 1081/// nk_free(&ctx); 1082/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1083/// 1084/// Finally while using draw commands makes sense for higher abstracted platforms like 1085/// X11 and Win32 or drawing libraries it is often desirable to use graphics 1086/// hardware directly. Therefore it is possible to just define 1087/// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output. 1088/// To access the vertex output you first have to convert all draw commands into 1089/// vertexes by calling `nk_convert` which takes in your preferred vertex format. 1090/// After successfully converting all draw commands just iterate over and execute all 1091/// vertex draw commands: 1092/// 1093/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1094/// // fill configuration 1095/// struct your_vertex 1096/// { 1097/// float pos[2]; // important to keep it to 2 floats 1098/// float uv[2]; 1099/// unsigned char col[4]; 1100/// }; 1101/// struct nk_convert_config cfg = {}; 1102/// static const struct nk_draw_vertex_layout_element vertex_layout[] = { 1103/// {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)}, 1104/// {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)}, 1105/// {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)}, 1106/// {NK_VERTEX_LAYOUT_END} 1107/// }; 1108/// cfg.shape_AA = NK_ANTI_ALIASING_ON; 1109/// cfg.line_AA = NK_ANTI_ALIASING_ON; 1110/// cfg.vertex_layout = vertex_layout; 1111/// cfg.vertex_size = sizeof(struct your_vertex); 1112/// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex); 1113/// cfg.circle_segment_count = 22; 1114/// cfg.curve_segment_count = 22; 1115/// cfg.arc_segment_count = 22; 1116/// cfg.global_alpha = 1.0f; 1117/// cfg.null = dev->null; 1118/// // 1119/// // setup buffers and convert 1120/// struct nk_buffer cmds, verts, idx; 1121/// nk_buffer_init_default(&cmds); 1122/// nk_buffer_init_default(&verts); 1123/// nk_buffer_init_default(&idx); 1124/// nk_convert(&ctx, &cmds, &verts, &idx, &cfg); 1125/// // 1126/// // draw 1127/// nk_draw_foreach(cmd, &ctx, &cmds) { 1128/// if (!cmd->elem_count) continue; 1129/// //[...] 1130/// } 1131/// nk_buffer_free(&cms); 1132/// nk_buffer_free(&verts); 1133/// nk_buffer_free(&idx); 1134/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1135/// 1136/// #### Reference 1137/// Function | Description 1138/// --------------------|------------------------------------------------------- 1139/// __nk__begin__ | Returns the first draw command in the context draw command list to be drawn 1140/// __nk__next__ | Increments the draw command iterator to the next command inside the context draw command list 1141/// __nk_foreach__ | Iterates over each draw command inside the context draw command list 1142/// __nk_convert__ | Converts from the abstract draw commands list into a hardware accessible vertex format 1143/// __nk_draw_begin__ | Returns the first vertex command in the context vertex draw list to be executed 1144/// __nk__draw_next__ | Increments the vertex command iterator to the next command inside the context vertex command list 1145/// __nk__draw_end__ | Returns the end of the vertex draw list 1146/// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list 1147*/ 1148enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON}; 1149enum nk_convert_result { 1150 NK_CONVERT_SUCCESS = 0, 1151 NK_CONVERT_INVALID_PARAM = 1, 1152 NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1), 1153 NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2), 1154 NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3) 1155}; 1156struct nk_draw_null_texture { 1157 nk_handle texture; /* texture handle to a texture with a white pixel */ 1158 struct nk_vec2 uv; /* coordinates to a white pixel in the texture */ 1159}; 1160struct nk_convert_config { 1161 float global_alpha; /* global alpha value */ 1162 enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */ 1163 enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */ 1164 unsigned circle_segment_count; /* number of segments used for circles: default to 22 */ 1165 unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */ 1166 unsigned curve_segment_count; /* number of segments used for curves: default to 22 */ 1167 struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */ 1168 const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ 1169 nk_size vertex_size; /* sizeof one vertex for vertex packing */ 1170 nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */ 1171}; 1172/*/// #### nk__begin 1173/// Returns a draw command list iterator to iterate all draw 1174/// commands accumulated over one frame. 1175/// 1176/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1177/// const struct nk_command* nk__begin(struct nk_context*); 1178/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1179/// 1180/// Parameter | Description 1181/// ------------|----------------------------------------------------------- 1182/// __ctx__ | must point to an previously initialized `nk_context` struct at the end of a frame 1183/// 1184/// Returns draw command pointer pointing to the first command inside the draw command list 1185*/ 1186NK_API const struct nk_command* nk__begin(struct nk_context*); 1187/*/// #### nk__next 1188/// Returns draw command pointer pointing to the next command inside the draw command list 1189/// 1190/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1191/// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1192/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1193/// 1194/// Parameter | Description 1195/// ------------|----------------------------------------------------------- 1196/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1197/// __cmd__ | Must point to an previously a draw command either returned by `nk__begin` or `nk__next` 1198/// 1199/// Returns draw command pointer pointing to the next command inside the draw command list 1200*/ 1201NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1202/*/// #### nk_foreach 1203/// Iterates over each draw command inside the context draw command list 1204/// 1205/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1206/// #define nk_foreach(c, ctx) 1207/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1208/// 1209/// Parameter | Description 1210/// ------------|----------------------------------------------------------- 1211/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1212/// __cmd__ | Command pointer initialized to NULL 1213/// 1214/// Iterates over each draw command inside the context draw command list 1215*/ 1216#define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c)) 1217#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 1218/*/// #### nk_convert 1219/// Converts all internal draw commands into vertex draw commands and fills 1220/// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format 1221/// as well as some other configuration values have to be configured by filling out a 1222/// `nk_convert_config` struct. 1223/// 1224/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1225/// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 1226/// struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); 1227/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1228/// 1229/// Parameter | Description 1230/// ------------|----------------------------------------------------------- 1231/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1232/// __cmds__ | Must point to a previously initialized buffer to hold converted vertex draw commands 1233/// __vertices__| Must point to a previously initialized buffer to hold all produced vertices 1234/// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices 1235/// __config__ | Must point to a filled out `nk_config` struct to configure the conversion process 1236/// 1237/// Returns one of enum nk_convert_result error codes 1238/// 1239/// Parameter | Description 1240/// --------------------------------|----------------------------------------------------------- 1241/// NK_CONVERT_SUCCESS | Signals a successful draw command to vertex buffer conversion 1242/// NK_CONVERT_INVALID_PARAM | An invalid argument was passed in the function call 1243/// NK_CONVERT_COMMAND_BUFFER_FULL | The provided buffer for storing draw commands is full or failed to allocate more memory 1244/// NK_CONVERT_VERTEX_BUFFER_FULL | The provided buffer for storing vertices is full or failed to allocate more memory 1245/// NK_CONVERT_ELEMENT_BUFFER_FULL | The provided buffer for storing indicies is full or failed to allocate more memory 1246*/ 1247NK_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*); 1248/*/// #### nk__draw_begin 1249/// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer 1250/// 1251/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1252/// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1253/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1254/// 1255/// Parameter | Description 1256/// ------------|----------------------------------------------------------- 1257/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1258/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1259/// 1260/// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer 1261*/ 1262NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1263/*/// #### nk__draw_end 1264/// Returns the vertex draw command at the end of the vertex draw command buffer 1265/// 1266/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1267/// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf); 1268/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1269/// 1270/// Parameter | Description 1271/// ------------|----------------------------------------------------------- 1272/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1273/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1274/// 1275/// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1276*/ 1277NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*); 1278/*/// #### nk__draw_next 1279/// Increments the vertex draw command buffer iterator 1280/// 1281/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1282/// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1283/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1284/// 1285/// Parameter | Description 1286/// ------------|----------------------------------------------------------- 1287/// __cmd__ | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command 1288/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1289/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1290/// 1291/// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1292*/ 1293NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1294/*/// #### nk_draw_foreach 1295/// Iterates over each vertex draw command inside a vertex draw command buffer 1296/// 1297/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1298/// #define nk_draw_foreach(cmd,ctx, b) 1299/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1300/// 1301/// Parameter | Description 1302/// ------------|----------------------------------------------------------- 1303/// __cmd__ | `nk_draw_command`iterator set to NULL 1304/// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1305/// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1306*/ 1307#define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) 1308#endif 1309/* ============================================================================= 1310 * 1311 * WINDOW 1312 * 1313 * ============================================================================= 1314/// ### Window 1315/// Windows are the main persistent state used inside nuklear and are life time 1316/// controlled by simply "retouching" (i.e. calling) each window each frame. 1317/// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx` 1318/// and `nk_end`. Calling any widgets outside these two functions will result in an 1319/// assert in debug or no state change in release mode.<br /><br /> 1320/// 1321/// Each window holds frame persistent state like position, size, flags, state tables, 1322/// and some garbage collected internal persistent widget state. Each window 1323/// is linked into a window stack list which determines the drawing and overlapping 1324/// order. The topmost window thereby is the currently active window.<br /><br /> 1325/// 1326/// To change window position inside the stack occurs either automatically by 1327/// user input by being clicked on or programmatically by calling `nk_window_focus`. 1328/// Windows by default are visible unless explicitly being defined with flag 1329/// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag 1330/// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling 1331/// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br /> 1332/// 1333/// #### Usage 1334/// To create and keep a window you have to call one of the two `nk_begin_xxx` 1335/// functions to start window declarations and `nk_end` at the end. Furthermore it 1336/// is recommended to check the return value of `nk_begin_xxx` and only process 1337/// widgets inside the window if the value is not 0. Either way you have to call 1338/// `nk_end` at the end of window declarations. Furthermore, do not attempt to 1339/// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not 1340/// in a segmentation fault. 1341/// 1342/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1343/// if (nk_begin_xxx(...) { 1344/// // [... widgets ...] 1345/// } 1346/// nk_end(ctx); 1347/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1348/// 1349/// In the grand concept window and widget declarations need to occur after input 1350/// handling and before drawing to screen. Not doing so can result in higher 1351/// latency or at worst invalid behavior. Furthermore make sure that `nk_clear` 1352/// is called at the end of the frame. While nuklear's default platform backends 1353/// already call `nk_clear` for you if you write your own backend not calling 1354/// `nk_clear` can cause asserts or even worse undefined behavior. 1355/// 1356/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1357/// struct nk_context ctx; 1358/// nk_init_xxx(&ctx, ...); 1359/// while (1) { 1360/// Event evt; 1361/// nk_input_begin(&ctx); 1362/// while (GetEvent(&evt)) { 1363/// if (evt.type == MOUSE_MOVE) 1364/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 1365/// else if (evt.type == [...]) { 1366/// nk_input_xxx(...); 1367/// } 1368/// } 1369/// nk_input_end(&ctx); 1370/// 1371/// if (nk_begin_xxx(...) { 1372/// //[...] 1373/// } 1374/// nk_end(ctx); 1375/// 1376/// const struct nk_command *cmd = 0; 1377/// nk_foreach(cmd, &ctx) { 1378/// case NK_COMMAND_LINE: 1379/// your_draw_line_function(...) 1380/// break; 1381/// case NK_COMMAND_RECT 1382/// your_draw_rect_function(...) 1383/// break; 1384/// case //...: 1385/// //[...] 1386/// } 1387/// nk_clear(&ctx); 1388/// } 1389/// nk_free(&ctx); 1390/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1391/// 1392/// #### Reference 1393/// Function | Description 1394/// ------------------------------------|---------------------------------------- 1395/// nk_begin | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed 1396/// nk_begin_titled | Extended window start with separated title and identifier to allow multiple windows with same name but not title 1397/// nk_end | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup 1398// 1399/// nk_window_find | Finds and returns the window with give name 1400/// nk_window_get_bounds | Returns a rectangle with screen position and size of the currently processed window. 1401/// nk_window_get_position | Returns the position of the currently processed window 1402/// nk_window_get_size | Returns the size with width and height of the currently processed window 1403/// nk_window_get_width | Returns the width of the currently processed window 1404/// nk_window_get_height | Returns the height of the currently processed window 1405/// nk_window_get_panel | Returns the underlying panel which contains all processing state of the current window 1406/// nk_window_get_content_region | Returns the position and size of the currently visible and non-clipped space inside the currently processed window 1407/// nk_window_get_content_region_min | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1408/// nk_window_get_content_region_max | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1409/// nk_window_get_content_region_size | Returns the size of the currently visible and non-clipped space inside the currently processed window 1410/// nk_window_get_canvas | Returns the draw command buffer. Can be used to draw custom widgets 1411/// nk_window_get_scroll | Gets the scroll offset of the current window 1412/// nk_window_has_focus | Returns if the currently processed window is currently active 1413/// nk_window_is_collapsed | Returns if the window with given name is currently minimized/collapsed 1414/// nk_window_is_closed | Returns if the currently processed window was closed 1415/// nk_window_is_hidden | Returns if the currently processed window was hidden 1416/// nk_window_is_active | Same as nk_window_has_focus for some reason 1417/// nk_window_is_hovered | Returns if the currently processed window is currently being hovered by mouse 1418/// nk_window_is_any_hovered | Return if any window currently hovered 1419/// nk_item_is_any_active | Returns if any window or widgets is currently hovered or active 1420// 1421/// nk_window_set_bounds | Updates position and size of the currently processed window 1422/// nk_window_set_position | Updates position of the currently process window 1423/// nk_window_set_size | Updates the size of the currently processed window 1424/// nk_window_set_focus | Set the currently processed window as active window 1425/// nk_window_set_scroll | Sets the scroll offset of the current window 1426// 1427/// nk_window_close | Closes the window with given window name which deletes the window at the end of the frame 1428/// nk_window_collapse | Collapses the window with given window name 1429/// nk_window_collapse_if | Collapses the window with given window name if the given condition was met 1430/// nk_window_show | Hides a visible or reshows a hidden window 1431/// nk_window_show_if | Hides/shows a window depending on condition 1432*/ 1433/* 1434/// #### nk_panel_flags 1435/// Flag | Description 1436/// ----------------------------|---------------------------------------- 1437/// NK_WINDOW_BORDER | Draws a border around the window to visually separate window from the background 1438/// NK_WINDOW_MOVABLE | The movable flag indicates that a window can be moved by user input or by dragging the window header 1439/// 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 1440/// NK_WINDOW_CLOSABLE | Adds a closable icon into the header 1441/// NK_WINDOW_MINIMIZABLE | Adds a minimize icon into the header 1442/// NK_WINDOW_NO_SCROLLBAR | Removes the scrollbar from the window 1443/// NK_WINDOW_TITLE | Forces a header at the top at the window showing the title 1444/// 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 1445/// NK_WINDOW_BACKGROUND | Always keep window in the background 1446/// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-bottom corner instead right-bottom 1447/// NK_WINDOW_NO_INPUT | Prevents window of scaling, moving or getting focus 1448/// 1449/// #### nk_collapse_states 1450/// State | Description 1451/// ----------------|----------------------------------------------------------- 1452/// __NK_MINIMIZED__| UI section is collased and not visibile until maximized 1453/// __NK_MAXIMIZED__| UI section is extended and visibile until minimized 1454/// <br /><br /> 1455*/ 1456enum nk_panel_flags { 1457 NK_WINDOW_BORDER = NK_FLAG(0), 1458 NK_WINDOW_MOVABLE = NK_FLAG(1), 1459 NK_WINDOW_SCALABLE = NK_FLAG(2), 1460 NK_WINDOW_CLOSABLE = NK_FLAG(3), 1461 NK_WINDOW_MINIMIZABLE = NK_FLAG(4), 1462 NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), 1463 NK_WINDOW_TITLE = NK_FLAG(6), 1464 NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), 1465 NK_WINDOW_BACKGROUND = NK_FLAG(8), 1466 NK_WINDOW_SCALE_LEFT = NK_FLAG(9), 1467 NK_WINDOW_NO_INPUT = NK_FLAG(10) 1468}; 1469/*/// #### nk_begin 1470/// Starts a new window; needs to be called every frame for every 1471/// window (unless hidden) or otherwise the window gets removed 1472/// 1473/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1474/// int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1475/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1476/// 1477/// Parameter | Description 1478/// ------------|----------------------------------------------------------- 1479/// __ctx__ | Must point to an previously initialized `nk_context` struct 1480/// __title__ | Window title and identifier. Needs to be persistent over frames to identify the window 1481/// __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 1482/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1483/// 1484/// Returns `true(1)` if the window can be filled up with widgets from this point 1485/// until `nk_end` or `false(0)` otherwise for example if minimized 1486*/ 1487NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1488/*/// #### nk_begin_titled 1489/// Extended window start with separated title and identifier to allow multiple 1490/// windows with same title but not name 1491/// 1492/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1493/// int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1494/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1495/// 1496/// Parameter | Description 1497/// ------------|----------------------------------------------------------- 1498/// __ctx__ | Must point to an previously initialized `nk_context` struct 1499/// __name__ | Window identifier. Needs to be persistent over frames to identify the window 1500/// __title__ | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set 1501/// __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 1502/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1503/// 1504/// Returns `true(1)` if the window can be filled up with widgets from this point 1505/// until `nk_end` or `false(0)` otherwise for example if minimized 1506*/ 1507NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1508/*/// #### nk_end 1509/// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup. 1510/// All widget calls after this functions will result in asserts or no state changes 1511/// 1512/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1513/// void nk_end(struct nk_context *ctx); 1514/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1515/// 1516/// Parameter | Description 1517/// ------------|----------------------------------------------------------- 1518/// __ctx__ | Must point to an previously initialized `nk_context` struct 1519*/ 1520NK_API void nk_end(struct nk_context *ctx); 1521/*/// #### nk_window_find 1522/// Finds and returns a window from passed name 1523/// 1524/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1525/// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1526/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1527/// 1528/// Parameter | Description 1529/// ------------|----------------------------------------------------------- 1530/// __ctx__ | Must point to an previously initialized `nk_context` struct 1531/// __name__ | Window identifier 1532/// 1533/// Returns a `nk_window` struct pointing to the identified window or NULL if 1534/// no window with the given name was found 1535*/ 1536NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1537/*/// #### nk_window_get_bounds 1538/// Returns a rectangle with screen position and size of the currently processed window 1539/// 1540/// !!! WARNING 1541/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1542/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1543/// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1544/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1545/// 1546/// Parameter | Description 1547/// ------------|----------------------------------------------------------- 1548/// __ctx__ | Must point to an previously initialized `nk_context` struct 1549/// 1550/// Returns a `nk_rect` struct with window upper left window position and size 1551*/ 1552NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1553/*/// #### nk_window_get_position 1554/// Returns the position of the currently processed window. 1555/// 1556/// !!! WARNING 1557/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1558/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1559/// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1560/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1561/// 1562/// Parameter | Description 1563/// ------------|----------------------------------------------------------- 1564/// __ctx__ | Must point to an previously initialized `nk_context` struct 1565/// 1566/// Returns a `nk_vec2` struct with window upper left position 1567*/ 1568NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1569/*/// #### nk_window_get_size 1570/// Returns the size with width and height of the currently processed window. 1571/// 1572/// !!! WARNING 1573/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1574/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1575/// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx); 1576/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1577/// 1578/// Parameter | Description 1579/// ------------|----------------------------------------------------------- 1580/// __ctx__ | Must point to an previously initialized `nk_context` struct 1581/// 1582/// Returns a `nk_vec2` struct with window width and height 1583*/ 1584NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*); 1585/*/// #### nk_window_get_width 1586/// Returns the width of the currently processed window. 1587/// 1588/// !!! WARNING 1589/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1590/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1591/// float nk_window_get_width(const struct nk_context *ctx); 1592/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1593/// 1594/// Parameter | Description 1595/// ------------|----------------------------------------------------------- 1596/// __ctx__ | Must point to an previously initialized `nk_context` struct 1597/// 1598/// Returns the current window width 1599*/ 1600NK_API float nk_window_get_width(const struct nk_context*); 1601/*/// #### nk_window_get_height 1602/// Returns the height of the currently processed window. 1603/// 1604/// !!! WARNING 1605/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1606/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1607/// float nk_window_get_height(const struct nk_context *ctx); 1608/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1609/// 1610/// Parameter | Description 1611/// ------------|----------------------------------------------------------- 1612/// __ctx__ | Must point to an previously initialized `nk_context` struct 1613/// 1614/// Returns the current window height 1615*/ 1616NK_API float nk_window_get_height(const struct nk_context*); 1617/*/// #### nk_window_get_panel 1618/// Returns the underlying panel which contains all processing state of the current window. 1619/// 1620/// !!! WARNING 1621/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1622/// !!! WARNING 1623/// Do not keep the returned panel pointer around, it is only valid until `nk_end` 1624/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1625/// struct nk_panel* nk_window_get_panel(struct nk_context *ctx); 1626/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1627/// 1628/// Parameter | Description 1629/// ------------|----------------------------------------------------------- 1630/// __ctx__ | Must point to an previously initialized `nk_context` struct 1631/// 1632/// Returns a pointer to window internal `nk_panel` state. 1633*/ 1634NK_API struct nk_panel* nk_window_get_panel(struct nk_context*); 1635/*/// #### nk_window_get_content_region 1636/// Returns the position and size of the currently visible and non-clipped space 1637/// inside the currently processed window. 1638/// 1639/// !!! WARNING 1640/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1641/// 1642/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1643/// struct nk_rect nk_window_get_content_region(struct nk_context *ctx); 1644/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1645/// 1646/// Parameter | Description 1647/// ------------|----------------------------------------------------------- 1648/// __ctx__ | Must point to an previously initialized `nk_context` struct 1649/// 1650/// Returns `nk_rect` struct with screen position and size (no scrollbar offset) 1651/// of the visible space inside the current window 1652*/ 1653NK_API struct nk_rect nk_window_get_content_region(struct nk_context*); 1654/*/// #### nk_window_get_content_region_min 1655/// Returns the upper left position of the currently visible and non-clipped 1656/// space inside the currently processed window. 1657/// 1658/// !!! WARNING 1659/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1660/// 1661/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1662/// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx); 1663/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1664/// 1665/// Parameter | Description 1666/// ------------|----------------------------------------------------------- 1667/// __ctx__ | Must point to an previously initialized `nk_context` struct 1668/// 1669/// returns `nk_vec2` struct with upper left screen position (no scrollbar offset) 1670/// of the visible space inside the current window 1671*/ 1672NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*); 1673/*/// #### nk_window_get_content_region_max 1674/// Returns the lower right screen position of the currently visible and 1675/// non-clipped space inside the currently processed window. 1676/// 1677/// !!! WARNING 1678/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1679/// 1680/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1681/// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx); 1682/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1683/// 1684/// Parameter | Description 1685/// ------------|----------------------------------------------------------- 1686/// __ctx__ | Must point to an previously initialized `nk_context` struct 1687/// 1688/// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset) 1689/// of the visible space inside the current window 1690*/ 1691NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*); 1692/*/// #### nk_window_get_content_region_size 1693/// Returns the size of the currently visible and non-clipped space inside the 1694/// currently processed window 1695/// 1696/// !!! WARNING 1697/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1698/// 1699/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1700/// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx); 1701/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1702/// 1703/// Parameter | Description 1704/// ------------|----------------------------------------------------------- 1705/// __ctx__ | Must point to an previously initialized `nk_context` struct 1706/// 1707/// Returns `nk_vec2` struct with size the visible space inside the current window 1708*/ 1709NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); 1710/*/// #### nk_window_get_canvas 1711/// Returns the draw command buffer. Can be used to draw custom widgets 1712/// !!! WARNING 1713/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1714/// !!! WARNING 1715/// Do not keep the returned command buffer pointer around it is only valid until `nk_end` 1716/// 1717/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1718/// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx); 1719/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1720/// 1721/// Parameter | Description 1722/// ------------|----------------------------------------------------------- 1723/// __ctx__ | Must point to an previously initialized `nk_context` struct 1724/// 1725/// Returns a pointer to window internal `nk_command_buffer` struct used as 1726/// drawing canvas. Can be used to do custom drawing. 1727*/ 1728NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); 1729/*/// #### nk_window_get_scroll 1730/// Gets the scroll offset for the current window 1731/// !!! WARNING 1732/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1733/// 1734/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1735/// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y); 1736/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1737/// 1738/// Parameter | Description 1739/// -------------|----------------------------------------------------------- 1740/// __ctx__ | Must point to an previously initialized `nk_context` struct 1741/// __offset_x__ | A pointer to the x offset output (or NULL to ignore) 1742/// __offset_y__ | A pointer to the y offset output (or NULL to ignore) 1743*/ 1744NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); 1745/*/// #### nk_window_has_focus 1746/// Returns if the currently processed window is currently active 1747/// !!! WARNING 1748/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1749/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1750/// int nk_window_has_focus(const struct nk_context *ctx); 1751/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1752/// 1753/// Parameter | Description 1754/// ------------|----------------------------------------------------------- 1755/// __ctx__ | Must point to an previously initialized `nk_context` struct 1756/// 1757/// Returns `false(0)` if current window is not active or `true(1)` if it is 1758*/ 1759NK_API int nk_window_has_focus(const struct nk_context*); 1760/*/// #### nk_window_is_hovered 1761/// Return if the current window is being hovered 1762/// !!! WARNING 1763/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1764/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1765/// int nk_window_is_hovered(struct nk_context *ctx); 1766/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1767/// 1768/// Parameter | Description 1769/// ------------|----------------------------------------------------------- 1770/// __ctx__ | Must point to an previously initialized `nk_context` struct 1771/// 1772/// Returns `true(1)` if current window is hovered or `false(0)` otherwise 1773*/ 1774NK_API int nk_window_is_hovered(struct nk_context*); 1775/*/// #### nk_window_is_collapsed 1776/// Returns if the window with given name is currently minimized/collapsed 1777/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1778/// int nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1779/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1780/// 1781/// Parameter | Description 1782/// ------------|----------------------------------------------------------- 1783/// __ctx__ | Must point to an previously initialized `nk_context` struct 1784/// __name__ | Identifier of window you want to check if it is collapsed 1785/// 1786/// Returns `true(1)` if current window is minimized and `false(0)` if window not 1787/// found or is not minimized 1788*/ 1789NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1790/*/// #### nk_window_is_closed 1791/// Returns if the window with given name was closed by calling `nk_close` 1792/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1793/// int nk_window_is_closed(struct nk_context *ctx, const char *name); 1794/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1795/// 1796/// Parameter | Description 1797/// ------------|----------------------------------------------------------- 1798/// __ctx__ | Must point to an previously initialized `nk_context` struct 1799/// __name__ | Identifier of window you want to check if it is closed 1800/// 1801/// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed 1802*/ 1803NK_API int nk_window_is_closed(struct nk_context*, const char*); 1804/*/// #### nk_window_is_hidden 1805/// Returns if the window with given name is hidden 1806/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1807/// int nk_window_is_hidden(struct nk_context *ctx, const char *name); 1808/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1809/// 1810/// Parameter | Description 1811/// ------------|----------------------------------------------------------- 1812/// __ctx__ | Must point to an previously initialized `nk_context` struct 1813/// __name__ | Identifier of window you want to check if it is hidden 1814/// 1815/// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible 1816*/ 1817NK_API int nk_window_is_hidden(struct nk_context*, const char*); 1818/*/// #### nk_window_is_active 1819/// Same as nk_window_has_focus for some reason 1820/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1821/// int nk_window_is_active(struct nk_context *ctx, const char *name); 1822/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1823/// 1824/// Parameter | Description 1825/// ------------|----------------------------------------------------------- 1826/// __ctx__ | Must point to an previously initialized `nk_context` struct 1827/// __name__ | Identifier of window you want to check if it is active 1828/// 1829/// Returns `true(1)` if current window is active or `false(0)` window not found or not active 1830*/ 1831NK_API int nk_window_is_active(struct nk_context*, const char*); 1832/*/// #### nk_window_is_any_hovered 1833/// Returns if the any window is being hovered 1834/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1835/// int nk_window_is_any_hovered(struct nk_context*); 1836/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1837/// 1838/// Parameter | Description 1839/// ------------|----------------------------------------------------------- 1840/// __ctx__ | Must point to an previously initialized `nk_context` struct 1841/// 1842/// Returns `true(1)` if any window is hovered or `false(0)` otherwise 1843*/ 1844NK_API int nk_window_is_any_hovered(struct nk_context*); 1845/*/// #### nk_item_is_any_active 1846/// Returns if the any window is being hovered or any widget is currently active. 1847/// Can be used to decide if input should be processed by UI or your specific input handling. 1848/// Example could be UI and 3D camera to move inside a 3D space. 1849/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1850/// int nk_item_is_any_active(struct nk_context*); 1851/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1852/// 1853/// Parameter | Description 1854/// ------------|----------------------------------------------------------- 1855/// __ctx__ | Must point to an previously initialized `nk_context` struct 1856/// 1857/// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise 1858*/ 1859NK_API int nk_item_is_any_active(struct nk_context*); 1860/*/// #### nk_window_set_bounds 1861/// Updates position and size of window with passed in name 1862/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1863/// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1864/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1865/// 1866/// Parameter | Description 1867/// ------------|----------------------------------------------------------- 1868/// __ctx__ | Must point to an previously initialized `nk_context` struct 1869/// __name__ | Identifier of the window to modify both position and size 1870/// __bounds__ | Must point to a `nk_rect` struct with the new position and size 1871*/ 1872NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1873/*/// #### nk_window_set_position 1874/// Updates position of window with passed name 1875/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1876/// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1877/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1878/// 1879/// Parameter | Description 1880/// ------------|----------------------------------------------------------- 1881/// __ctx__ | Must point to an previously initialized `nk_context` struct 1882/// __name__ | Identifier of the window to modify both position 1883/// __pos__ | Must point to a `nk_vec2` struct with the new position 1884*/ 1885NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1886/*/// #### nk_window_set_size 1887/// Updates size of window with passed in name 1888/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1889/// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1890/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1891/// 1892/// Parameter | Description 1893/// ------------|----------------------------------------------------------- 1894/// __ctx__ | Must point to an previously initialized `nk_context` struct 1895/// __name__ | Identifier of the window to modify both window size 1896/// __size__ | Must point to a `nk_vec2` struct with new window size 1897*/ 1898NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1899/*/// #### nk_window_set_focus 1900/// Sets the window with given name as active 1901/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1902/// void nk_window_set_focus(struct nk_context*, const char *name); 1903/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1904/// 1905/// Parameter | Description 1906/// ------------|----------------------------------------------------------- 1907/// __ctx__ | Must point to an previously initialized `nk_context` struct 1908/// __name__ | Identifier of the window to set focus on 1909*/ 1910NK_API void nk_window_set_focus(struct nk_context*, const char *name); 1911/*/// #### nk_window_set_scroll 1912/// Sets the scroll offset for the current window 1913/// !!! WARNING 1914/// Only call this function between calls `nk_begin_xxx` and `nk_end` 1915/// 1916/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1917/// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y); 1918/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1919/// 1920/// Parameter | Description 1921/// -------------|----------------------------------------------------------- 1922/// __ctx__ | Must point to an previously initialized `nk_context` struct 1923/// __offset_x__ | The x offset to scroll to 1924/// __offset_y__ | The y offset to scroll to 1925*/ 1926NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); 1927/*/// #### nk_window_close 1928/// Closes a window and marks it for being freed at the end of the frame 1929/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1930/// void nk_window_close(struct nk_context *ctx, const char *name); 1931/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1932/// 1933/// Parameter | Description 1934/// ------------|----------------------------------------------------------- 1935/// __ctx__ | Must point to an previously initialized `nk_context` struct 1936/// __name__ | Identifier of the window to close 1937*/ 1938NK_API void nk_window_close(struct nk_context *ctx, const char *name); 1939/*/// #### nk_window_collapse 1940/// Updates collapse state of a window with given name 1941/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1942/// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1943/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1944/// 1945/// Parameter | Description 1946/// ------------|----------------------------------------------------------- 1947/// __ctx__ | Must point to an previously initialized `nk_context` struct 1948/// __name__ | Identifier of the window to close 1949/// __state__ | value out of nk_collapse_states section 1950*/ 1951NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1952/*/// #### nk_window_collapse_if 1953/// Updates collapse state of a window with given name if given condition is met 1954/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1955/// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1956/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1957/// 1958/// Parameter | Description 1959/// ------------|----------------------------------------------------------- 1960/// __ctx__ | Must point to an previously initialized `nk_context` struct 1961/// __name__ | Identifier of the window to either collapse or maximize 1962/// __state__ | value out of nk_collapse_states section the window should be put into 1963/// __cond__ | condition that has to be met to actually commit the collapse state change 1964*/ 1965NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1966/*/// #### nk_window_show 1967/// updates visibility state of a window with given name 1968/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1969/// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1970/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1971/// 1972/// Parameter | Description 1973/// ------------|----------------------------------------------------------- 1974/// __ctx__ | Must point to an previously initialized `nk_context` struct 1975/// __name__ | Identifier of the window to either collapse or maximize 1976/// __state__ | state with either visible or hidden to modify the window with 1977*/ 1978NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1979/*/// #### nk_window_show_if 1980/// Updates visibility state of a window with given name if a given condition is met 1981/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1982/// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1983/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1984/// 1985/// Parameter | Description 1986/// ------------|----------------------------------------------------------- 1987/// __ctx__ | Must point to an previously initialized `nk_context` struct 1988/// __name__ | Identifier of the window to either hide or show 1989/// __state__ | state with either visible or hidden to modify the window with 1990/// __cond__ | condition that has to be met to actually commit the visbility state change 1991*/ 1992NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1993/* ============================================================================= 1994 * 1995 * LAYOUT 1996 * 1997 * ============================================================================= 1998/// ### Layouting 1999/// Layouting in general describes placing widget inside a window with position and size. 2000/// While in this particular implementation there are five different APIs for layouting 2001/// each with different trade offs between control and ease of use. <br /><br /> 2002/// 2003/// All layouting methods in this library are based around the concept of a row. 2004/// A row has a height the window content grows by and a number of columns and each 2005/// layouting method specifies how each widget is placed inside the row. 2006/// After a row has been allocated by calling a layouting functions and then 2007/// filled with widgets will advance an internal pointer over the allocated row. <br /><br /> 2008/// 2009/// To actually define a layout you just call the appropriate layouting function 2010/// and each subsequent widget call will place the widget as specified. Important 2011/// here is that if you define more widgets then columns defined inside the layout 2012/// functions it will allocate the next row without you having to make another layouting <br /><br /> 2013/// call. 2014/// 2015/// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API 2016/// is that you have to define the row height for each. However the row height 2017/// often depends on the height of the font. <br /><br /> 2018/// 2019/// To fix that internally nuklear uses a minimum row height that is set to the 2020/// height plus padding of currently active font and overwrites the row height 2021/// value if zero. <br /><br /> 2022/// 2023/// If you manually want to change the minimum row height then 2024/// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to 2025/// reset it back to be derived from font height. <br /><br /> 2026/// 2027/// Also if you change the font in nuklear it will automatically change the minimum 2028/// row height for you and. This means if you change the font but still want 2029/// a minimum row height smaller than the font you have to repush your value. <br /><br /> 2030/// 2031/// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx` 2032/// layouting method in combination with a cassowary constraint solver (there are 2033/// some versions on github with permissive license model) to take over all control over widget 2034/// layouting yourself. However for quick and dirty layouting using all the other layouting 2035/// functions should be fine. 2036/// 2037/// #### Usage 2038/// 1. __nk_layout_row_dynamic__<br /><br /> 2039/// The easiest layouting function is `nk_layout_row_dynamic`. It provides each 2040/// widgets with same horizontal space inside the row and dynamically grows 2041/// if the owning window grows in width. So the number of columns dictates 2042/// the size of each widget dynamically by formula: 2043/// 2044/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2045/// widget_width = (window_width - padding - spacing) * (1/colum_count) 2046/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2047/// 2048/// Just like all other layouting APIs if you define more widget than columns this 2049/// library will allocate a new row and keep all layouting parameters previously 2050/// defined. 2051/// 2052/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2053/// if (nk_begin_xxx(...) { 2054/// // first row with height: 30 composed of two widgets 2055/// nk_layout_row_dynamic(&ctx, 30, 2); 2056/// nk_widget(...); 2057/// nk_widget(...); 2058/// // 2059/// // second row with same parameter as defined above 2060/// nk_widget(...); 2061/// nk_widget(...); 2062/// // 2063/// // third row uses 0 for height which will use auto layouting 2064/// nk_layout_row_dynamic(&ctx, 0, 2); 2065/// nk_widget(...); 2066/// nk_widget(...); 2067/// } 2068/// nk_end(...); 2069/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2070/// 2071/// 2. __nk_layout_row_static__<br /><br /> 2072/// Another easy layouting function is `nk_layout_row_static`. It provides each 2073/// widget with same horizontal pixel width inside the row and does not grow 2074/// if the owning window scales smaller or bigger. 2075/// 2076/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2077/// if (nk_begin_xxx(...) { 2078/// // first row with height: 30 composed of two widgets with width: 80 2079/// nk_layout_row_static(&ctx, 30, 80, 2); 2080/// nk_widget(...); 2081/// nk_widget(...); 2082/// // 2083/// // second row with same parameter as defined above 2084/// nk_widget(...); 2085/// nk_widget(...); 2086/// // 2087/// // third row uses 0 for height which will use auto layouting 2088/// nk_layout_row_static(&ctx, 0, 80, 2); 2089/// nk_widget(...); 2090/// nk_widget(...); 2091/// } 2092/// nk_end(...); 2093/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2094/// 2095/// 3. __nk_layout_row_xxx__<br /><br /> 2096/// A little bit more advanced layouting API are functions `nk_layout_row_begin`, 2097/// `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly 2098/// specify each column pixel or window ratio in a row. It supports either 2099/// directly setting per column pixel width or widget window ratio but not 2100/// both. Furthermore it is a immediate mode API so each value is directly 2101/// pushed before calling a widget. Therefore the layout is not automatically 2102/// repeating like the last two layouting functions. 2103/// 2104/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2105/// if (nk_begin_xxx(...) { 2106/// // first row with height: 25 composed of two widgets with width 60 and 40 2107/// nk_layout_row_begin(ctx, NK_STATIC, 25, 2); 2108/// nk_layout_row_push(ctx, 60); 2109/// nk_widget(...); 2110/// nk_layout_row_push(ctx, 40); 2111/// nk_widget(...); 2112/// nk_layout_row_end(ctx); 2113/// // 2114/// // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75 2115/// nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2); 2116/// nk_layout_row_push(ctx, 0.25f); 2117/// nk_widget(...); 2118/// nk_layout_row_push(ctx, 0.75f); 2119/// nk_widget(...); 2120/// nk_layout_row_end(ctx); 2121/// // 2122/// // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75 2123/// nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2); 2124/// nk_layout_row_push(ctx, 0.25f); 2125/// nk_widget(...); 2126/// nk_layout_row_push(ctx, 0.75f); 2127/// nk_widget(...); 2128/// nk_layout_row_end(ctx); 2129/// } 2130/// nk_end(...); 2131/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2132/// 2133/// 4. __nk_layout_row__<br /><br /> 2134/// The array counterpart to API nk_layout_row_xxx is the single nk_layout_row 2135/// functions. Instead of pushing either pixel or window ratio for every widget 2136/// it allows to define it by array. The trade of for less control is that 2137/// `nk_layout_row` is automatically repeating. Otherwise the behavior is the 2138/// same. 2139/// 2140/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2141/// if (nk_begin_xxx(...) { 2142/// // two rows with height: 30 composed of two widgets with width 60 and 40 2143/// const float size[] = {60,40}; 2144/// nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); 2145/// nk_widget(...); 2146/// nk_widget(...); 2147/// nk_widget(...); 2148/// nk_widget(...); 2149/// // 2150/// // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75 2151/// const float ratio[] = {0.25, 0.75}; 2152/// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2153/// nk_widget(...); 2154/// nk_widget(...); 2155/// nk_widget(...); 2156/// nk_widget(...); 2157/// // 2158/// // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75 2159/// const float ratio[] = {0.25, 0.75}; 2160/// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2161/// nk_widget(...); 2162/// nk_widget(...); 2163/// nk_widget(...); 2164/// nk_widget(...); 2165/// } 2166/// nk_end(...); 2167/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2168/// 2169/// 5. __nk_layout_row_template_xxx__<br /><br /> 2170/// The most complex and second most flexible API is a simplified flexbox version without 2171/// line wrapping and weights for dynamic widgets. It is an immediate mode API but 2172/// unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called 2173/// before calling the templated widgets. 2174/// The row template layout has three different per widget size specifier. The first 2175/// one is the `nk_layout_row_template_push_static` with fixed widget pixel width. 2176/// They do not grow if the row grows and will always stay the same. 2177/// The second size specifier is `nk_layout_row_template_push_variable` 2178/// which defines a minimum widget size but it also can grow if more space is available 2179/// not taken by other widgets. 2180/// Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic` 2181/// which are completely flexible and unlike variable widgets can even shrink 2182/// to zero if not enough space is provided. 2183/// 2184/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2185/// if (nk_begin_xxx(...) { 2186/// // two rows with height: 30 composed of three widgets 2187/// nk_layout_row_template_begin(ctx, 30); 2188/// nk_layout_row_template_push_dynamic(ctx); 2189/// nk_layout_row_template_push_variable(ctx, 80); 2190/// nk_layout_row_template_push_static(ctx, 80); 2191/// nk_layout_row_template_end(ctx); 2192/// // 2193/// // first row 2194/// nk_widget(...); // dynamic widget can go to zero if not enough space 2195/// nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space 2196/// nk_widget(...); // static widget with fixed 80 pixel width 2197/// // 2198/// // second row same layout 2199/// nk_widget(...); 2200/// nk_widget(...); 2201/// nk_widget(...); 2202/// } 2203/// nk_end(...); 2204/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2205/// 2206/// 6. __nk_layout_space_xxx__<br /><br /> 2207/// Finally the most flexible API directly allows you to place widgets inside the 2208/// window. The space layout API is an immediate mode API which does not support 2209/// row auto repeat and directly sets position and size of a widget. Position 2210/// and size hereby can be either specified as ratio of allocated space or 2211/// allocated space local position and pixel size. Since this API is quite 2212/// powerful there are a number of utility functions to get the available space 2213/// and convert between local allocated space and screen space. 2214/// 2215/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2216/// if (nk_begin_xxx(...) { 2217/// // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2218/// nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX); 2219/// nk_layout_space_push(ctx, nk_rect(0,0,150,200)); 2220/// nk_widget(...); 2221/// nk_layout_space_push(ctx, nk_rect(200,200,100,200)); 2222/// nk_widget(...); 2223/// nk_layout_space_end(ctx); 2224/// // 2225/// // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2226/// nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX); 2227/// nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1)); 2228/// nk_widget(...); 2229/// nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1)); 2230/// nk_widget(...); 2231/// } 2232/// nk_end(...); 2233/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2234/// 2235/// #### Reference 2236/// Function | Description 2237/// ----------------------------------------|------------------------------------ 2238/// nk_layout_set_min_row_height | Set the currently used minimum row height to a specified value 2239/// nk_layout_reset_min_row_height | Resets the currently used minimum row height to font height 2240/// nk_layout_widget_bounds | Calculates current width a static layout row can fit inside a window 2241/// nk_layout_ratio_from_pixel | Utility functions to calculate window ratio from pixel size 2242// 2243/// nk_layout_row_dynamic | Current layout is divided into n same sized growing columns 2244/// nk_layout_row_static | Current layout is divided into n same fixed sized columns 2245/// nk_layout_row_begin | Starts a new row with given height and number of columns 2246/// nk_layout_row_push | Pushes another column with given size or window ratio 2247/// nk_layout_row_end | Finished previously started row 2248/// nk_layout_row | Specifies row columns in array as either window ratio or size 2249// 2250/// nk_layout_row_template_begin | Begins the row template declaration 2251/// nk_layout_row_template_push_dynamic | Adds a dynamic column that dynamically grows and can go to zero if not enough space 2252/// nk_layout_row_template_push_variable | Adds a variable column that dynamically grows but does not shrink below specified pixel width 2253/// nk_layout_row_template_push_static | Adds a static column that does not grow and will always have the same size 2254/// nk_layout_row_template_end | Marks the end of the row template 2255// 2256/// nk_layout_space_begin | Begins a new layouting space that allows to specify each widgets position and size 2257/// nk_layout_space_push | Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2258/// nk_layout_space_end | Marks the end of the layouting space 2259// 2260/// nk_layout_space_bounds | Callable after nk_layout_space_begin and returns total space allocated 2261/// nk_layout_space_to_screen | Converts vector from nk_layout_space coordinate space into screen space 2262/// nk_layout_space_to_local | Converts vector from screen space into nk_layout_space coordinates 2263/// nk_layout_space_rect_to_screen | Converts rectangle from nk_layout_space coordinate space into screen space 2264/// nk_layout_space_rect_to_local | Converts rectangle from screen space into nk_layout_space coordinates 2265*/ 2266/*/// #### nk_layout_set_min_row_height 2267/// Sets the currently used minimum row height. 2268/// !!! WARNING 2269/// The passed height needs to include both your preferred row height 2270/// as well as padding. No internal padding is added. 2271/// 2272/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2273/// void nk_layout_set_min_row_height(struct nk_context*, float height); 2274/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2275/// 2276/// Parameter | Description 2277/// ------------|----------------------------------------------------------- 2278/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2279/// __height__ | New minimum row height to be used for auto generating the row height 2280*/ 2281NK_API void nk_layout_set_min_row_height(struct nk_context*, float height); 2282/*/// #### nk_layout_reset_min_row_height 2283/// Reset the currently used minimum row height back to `font_height + text_padding + padding` 2284/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2285/// void nk_layout_reset_min_row_height(struct nk_context*); 2286/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2287/// 2288/// Parameter | Description 2289/// ------------|----------------------------------------------------------- 2290/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2291*/ 2292NK_API void nk_layout_reset_min_row_height(struct nk_context*); 2293/*/// #### nk_layout_widget_bounds 2294/// Returns the width of the next row allocate by one of the layouting functions 2295/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2296/// struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2297/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2298/// 2299/// Parameter | Description 2300/// ------------|----------------------------------------------------------- 2301/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2302/// 2303/// Return `nk_rect` with both position and size of the next row 2304*/ 2305NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2306/*/// #### nk_layout_ratio_from_pixel 2307/// Utility functions to calculate window ratio from pixel size 2308/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2309/// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2310/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2311/// 2312/// Parameter | Description 2313/// ------------|----------------------------------------------------------- 2314/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2315/// __pixel__ | Pixel_width to convert to window ratio 2316/// 2317/// Returns `nk_rect` with both position and size of the next row 2318*/ 2319NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2320/*/// #### nk_layout_row_dynamic 2321/// Sets current row layout to share horizontal space 2322/// between @cols number of widgets evenly. Once called all subsequent widget 2323/// calls greater than @cols will allocate a new row with same layout. 2324/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2325/// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2326/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2327/// 2328/// Parameter | Description 2329/// ------------|----------------------------------------------------------- 2330/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2331/// __height__ | Holds height of each widget in row or zero for auto layouting 2332/// __columns__ | Number of widget inside row 2333*/ 2334NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2335/*/// #### nk_layout_row_static 2336/// Sets current row layout to fill @cols number of widgets 2337/// in row with same @item_width horizontal size. Once called all subsequent widget 2338/// calls greater than @cols will allocate a new row with same layout. 2339/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2340/// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2341/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2342/// 2343/// Parameter | Description 2344/// ------------|----------------------------------------------------------- 2345/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2346/// __height__ | Holds height of each widget in row or zero for auto layouting 2347/// __width__ | Holds pixel width of each widget in the row 2348/// __columns__ | Number of widget inside row 2349*/ 2350NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2351/*/// #### nk_layout_row_begin 2352/// Starts a new dynamic or fixed row with given height and columns. 2353/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2354/// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2355/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2356/// 2357/// Parameter | Description 2358/// ------------|----------------------------------------------------------- 2359/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2360/// __fmt__ | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2361/// __height__ | holds height of each widget in row or zero for auto layouting 2362/// __columns__ | Number of widget inside row 2363*/ 2364NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2365/*/// #### nk_layout_row_push 2366/// Specifies either window ratio or width of a single column 2367/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2368/// void nk_layout_row_push(struct nk_context*, float value); 2369/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2370/// 2371/// Parameter | Description 2372/// ------------|----------------------------------------------------------- 2373/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2374/// __value__ | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call 2375*/ 2376NK_API void nk_layout_row_push(struct nk_context*, float value); 2377/*/// #### nk_layout_row_end 2378/// Finished previously started row 2379/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2380/// void nk_layout_row_end(struct nk_context*); 2381/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2382/// 2383/// Parameter | Description 2384/// ------------|----------------------------------------------------------- 2385/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2386*/ 2387NK_API void nk_layout_row_end(struct nk_context*); 2388/*/// #### nk_layout_row 2389/// Specifies row columns in array as either window ratio or size 2390/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2391/// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2392/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2393/// 2394/// Parameter | Description 2395/// ------------|----------------------------------------------------------- 2396/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2397/// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2398/// __height__ | Holds height of each widget in row or zero for auto layouting 2399/// __columns__ | Number of widget inside row 2400*/ 2401NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2402/*/// #### nk_layout_row_template_begin 2403/// Begins the row template declaration 2404/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2405/// void nk_layout_row_template_begin(struct nk_context*, float row_height); 2406/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2407/// 2408/// Parameter | Description 2409/// ------------|----------------------------------------------------------- 2410/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2411/// __height__ | Holds height of each widget in row or zero for auto layouting 2412*/ 2413NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height); 2414/*/// #### nk_layout_row_template_push_dynamic 2415/// Adds a dynamic column that dynamically grows and can go to zero if not enough space 2416/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2417/// void nk_layout_row_template_push_dynamic(struct nk_context*); 2418/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2419/// 2420/// Parameter | Description 2421/// ------------|----------------------------------------------------------- 2422/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2423/// __height__ | Holds height of each widget in row or zero for auto layouting 2424*/ 2425NK_API void nk_layout_row_template_push_dynamic(struct nk_context*); 2426/*/// #### nk_layout_row_template_push_variable 2427/// Adds a variable column that dynamically grows but does not shrink below specified pixel width 2428/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2429/// void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2430/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2431/// 2432/// Parameter | Description 2433/// ------------|----------------------------------------------------------- 2434/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2435/// __width__ | Holds the minimum pixel width the next column must always be 2436*/ 2437NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2438/*/// #### nk_layout_row_template_push_static 2439/// Adds a static column that does not grow and will always have the same size 2440/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2441/// void nk_layout_row_template_push_static(struct nk_context*, float width); 2442/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2443/// 2444/// Parameter | Description 2445/// ------------|----------------------------------------------------------- 2446/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2447/// __width__ | Holds the absolute pixel width value the next column must be 2448*/ 2449NK_API void nk_layout_row_template_push_static(struct nk_context*, float width); 2450/*/// #### nk_layout_row_template_end 2451/// Marks the end of the row template 2452/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2453/// void nk_layout_row_template_end(struct nk_context*); 2454/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2455/// 2456/// Parameter | Description 2457/// ------------|----------------------------------------------------------- 2458/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2459*/ 2460NK_API void nk_layout_row_template_end(struct nk_context*); 2461/*/// #### nk_layout_space_begin 2462/// Begins a new layouting space that allows to specify each widgets position and size. 2463/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2464/// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2465/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2466/// 2467/// Parameter | Description 2468/// ------------|----------------------------------------------------------- 2469/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2470/// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2471/// __height__ | Holds height of each widget in row or zero for auto layouting 2472/// __columns__ | Number of widgets inside row 2473*/ 2474NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2475/*/// #### nk_layout_space_push 2476/// Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2477/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2478/// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds); 2479/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2480/// 2481/// Parameter | Description 2482/// ------------|----------------------------------------------------------- 2483/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2484/// __bounds__ | Position and size in laoyut space local coordinates 2485*/ 2486NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds); 2487/*/// #### nk_layout_space_end 2488/// Marks the end of the layout space 2489/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2490/// void nk_layout_space_end(struct nk_context*); 2491/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2492/// 2493/// Parameter | Description 2494/// ------------|----------------------------------------------------------- 2495/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2496*/ 2497NK_API void nk_layout_space_end(struct nk_context*); 2498/*/// #### nk_layout_space_bounds 2499/// Utility function to calculate total space allocated for `nk_layout_space` 2500/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2501/// struct nk_rect nk_layout_space_bounds(struct nk_context*); 2502/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2503/// 2504/// Parameter | Description 2505/// ------------|----------------------------------------------------------- 2506/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2507/// 2508/// Returns `nk_rect` holding the total space allocated 2509*/ 2510NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*); 2511/*/// #### nk_layout_space_to_screen 2512/// Converts vector from nk_layout_space coordinate space into screen space 2513/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2514/// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2515/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2516/// 2517/// Parameter | Description 2518/// ------------|----------------------------------------------------------- 2519/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2520/// __vec__ | Position to convert from layout space into screen coordinate space 2521/// 2522/// Returns transformed `nk_vec2` in screen space coordinates 2523*/ 2524NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2525/*/// #### nk_layout_space_to_local 2526/// Converts vector from layout space into screen space 2527/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2528/// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2529/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2530/// 2531/// Parameter | Description 2532/// ------------|----------------------------------------------------------- 2533/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2534/// __vec__ | Position to convert from screen space into layout coordinate space 2535/// 2536/// Returns transformed `nk_vec2` in layout space coordinates 2537*/ 2538NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2539/*/// #### nk_layout_space_rect_to_screen 2540/// Converts rectangle from screen space into layout space 2541/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2542/// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2543/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2544/// 2545/// Parameter | Description 2546/// ------------|----------------------------------------------------------- 2547/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2548/// __bounds__ | Rectangle to convert from layout space into screen space 2549/// 2550/// Returns transformed `nk_rect` in screen space coordinates 2551*/ 2552NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2553/*/// #### nk_layout_space_rect_to_local 2554/// Converts rectangle from layout space into screen space 2555/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2556/// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2557/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2558/// 2559/// Parameter | Description 2560/// ------------|----------------------------------------------------------- 2561/// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2562/// __bounds__ | Rectangle to convert from layout space into screen space 2563/// 2564/// Returns transformed `nk_rect` in layout space coordinates 2565*/ 2566NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2567/* ============================================================================= 2568 * 2569 * GROUP 2570 * 2571 * ============================================================================= 2572/// ### Groups 2573/// Groups are basically windows inside windows. They allow to subdivide space 2574/// in a window to layout widgets as a group. Almost all more complex widget 2575/// layouting requirements can be solved using groups and basic layouting 2576/// fuctionality. Groups just like windows are identified by an unique name and 2577/// internally keep track of scrollbar offsets by default. However additional 2578/// versions are provided to directly manage the scrollbar. 2579/// 2580/// #### Usage 2581/// To create a group you have to call one of the three `nk_group_begin_xxx` 2582/// functions to start group declarations and `nk_group_end` at the end. Furthermore it 2583/// is required to check the return value of `nk_group_begin_xxx` and only process 2584/// widgets inside the window if the value is not 0. 2585/// Nesting groups is possible and even encouraged since many layouting schemes 2586/// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end` 2587/// to be only called if the corosponding `nk_group_begin_xxx` call does not return 0: 2588/// 2589/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2590/// if (nk_group_begin_xxx(ctx, ...) { 2591/// // [... widgets ...] 2592/// nk_group_end(ctx); 2593/// } 2594/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2595/// 2596/// In the grand concept groups can be called after starting a window 2597/// with `nk_begin_xxx` and before calling `nk_end`: 2598/// 2599/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2600/// struct nk_context ctx; 2601/// nk_init_xxx(&ctx, ...); 2602/// while (1) { 2603/// // Input 2604/// Event evt; 2605/// nk_input_begin(&ctx); 2606/// while (GetEvent(&evt)) { 2607/// if (evt.type == MOUSE_MOVE) 2608/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 2609/// else if (evt.type == [...]) { 2610/// nk_input_xxx(...); 2611/// } 2612/// } 2613/// nk_input_end(&ctx); 2614/// // 2615/// // Window 2616/// if (nk_begin_xxx(...) { 2617/// // [...widgets...] 2618/// nk_layout_row_dynamic(...); 2619/// if (nk_group_begin_xxx(ctx, ...) { 2620/// //[... widgets ...] 2621/// nk_group_end(ctx); 2622/// } 2623/// } 2624/// nk_end(ctx); 2625/// // 2626/// // Draw 2627/// const struct nk_command *cmd = 0; 2628/// nk_foreach(cmd, &ctx) { 2629/// switch (cmd->type) { 2630/// case NK_COMMAND_LINE: 2631/// your_draw_line_function(...) 2632/// break; 2633/// case NK_COMMAND_RECT 2634/// your_draw_rect_function(...) 2635/// break; 2636/// case ...: 2637/// // [...] 2638/// } 2639/// nk_clear(&ctx); 2640/// } 2641/// nk_free(&ctx); 2642/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2643/// #### Reference 2644/// Function | Description 2645/// --------------------------------|------------------------------------------- 2646/// nk_group_begin | Start a new group with internal scrollbar handling 2647/// nk_group_begin_titled | Start a new group with separeted name and title and internal scrollbar handling 2648/// nk_group_end | Ends a group. Should only be called if nk_group_begin returned non-zero 2649/// nk_group_scrolled_offset_begin | Start a new group with manual separated handling of scrollbar x- and y-offset 2650/// nk_group_scrolled_begin | Start a new group with manual scrollbar handling 2651/// nk_group_scrolled_end | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero 2652/// nk_group_get_scroll | Gets the scroll offset for the given group 2653/// nk_group_set_scroll | Sets the scroll offset for the given group 2654*/ 2655/*/// #### nk_group_begin 2656/// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2657/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2658/// int nk_group_begin(struct nk_context*, const char *title, nk_flags); 2659/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2660/// 2661/// Parameter | Description 2662/// ------------|----------------------------------------------------------- 2663/// __ctx__ | Must point to an previously initialized `nk_context` struct 2664/// __title__ | Must be an unique identifier for this group that is also used for the group header 2665/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2666/// 2667/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2668*/ 2669NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags); 2670/*/// #### nk_group_begin_titled 2671/// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2672/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2673/// int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2674/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2675/// 2676/// Parameter | Description 2677/// ------------|----------------------------------------------------------- 2678/// __ctx__ | Must point to an previously initialized `nk_context` struct 2679/// __id__ | Must be an unique identifier for this group 2680/// __title__ | Group header title 2681/// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2682/// 2683/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2684*/ 2685NK_API int nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2686/*/// #### nk_group_end 2687/// Ends a widget group 2688/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2689/// void nk_group_end(struct nk_context*); 2690/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2691/// 2692/// Parameter | Description 2693/// ------------|----------------------------------------------------------- 2694/// __ctx__ | Must point to an previously initialized `nk_context` struct 2695*/ 2696NK_API void nk_group_end(struct nk_context*); 2697/*/// #### nk_group_scrolled_offset_begin 2698/// starts a new widget group. requires a previous layouting function to specify 2699/// a size. Does not keep track of scrollbar. 2700/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2701/// int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2702/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2703/// 2704/// Parameter | Description 2705/// ------------|----------------------------------------------------------- 2706/// __ctx__ | Must point to an previously initialized `nk_context` struct 2707/// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally. 2708/// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically 2709/// __title__ | Window unique group title used to both identify and display in the group header 2710/// __flags__ | Window flags from the nk_panel_flags section 2711/// 2712/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2713*/ 2714NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2715/*/// #### nk_group_scrolled_begin 2716/// Starts a new widget group. requires a previous 2717/// layouting function to specify a size. Does not keep track of scrollbar. 2718/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2719/// int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2720/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2721/// 2722/// Parameter | Description 2723/// ------------|----------------------------------------------------------- 2724/// __ctx__ | Must point to an previously initialized `nk_context` struct 2725/// __off__ | Both x- and y- scroll offset. Allows for manual scrollbar control 2726/// __title__ | Window unique group title used to both identify and display in the group header 2727/// __flags__ | Window flags from nk_panel_flags section 2728/// 2729/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2730*/ 2731NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2732/*/// #### nk_group_scrolled_end 2733/// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin. 2734/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2735/// void nk_group_scrolled_end(struct nk_context*); 2736/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2737/// 2738/// Parameter | Description 2739/// ------------|----------------------------------------------------------- 2740/// __ctx__ | Must point to an previously initialized `nk_context` struct 2741*/ 2742NK_API void nk_group_scrolled_end(struct nk_context*); 2743/*/// #### nk_group_get_scroll 2744/// Gets the scroll position of the given group. 2745/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2746/// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); 2747/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2748/// 2749/// Parameter | Description 2750/// -------------|----------------------------------------------------------- 2751/// __ctx__ | Must point to an previously initialized `nk_context` struct 2752/// __id__ | The id of the group to get the scroll position of 2753/// __x_offset__ | A pointer to the x offset output (or NULL to ignore) 2754/// __y_offset__ | A pointer to the y offset output (or NULL to ignore) 2755*/ 2756NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); 2757/*/// #### nk_group_set_scroll 2758/// Sets the scroll position of the given group. 2759/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2760/// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); 2761/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2762/// 2763/// Parameter | Description 2764/// -------------|----------------------------------------------------------- 2765/// __ctx__ | Must point to an previously initialized `nk_context` struct 2766/// __id__ | The id of the group to scroll 2767/// __x_offset__ | The x offset to scroll to 2768/// __y_offset__ | The y offset to scroll to 2769*/ 2770NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); 2771/* ============================================================================= 2772 * 2773 * TREE 2774 * 2775 * ============================================================================= 2776/// ### Tree 2777/// Trees represent two different concept. First the concept of a collapsable 2778/// UI section that can be either in a hidden or visibile state. They allow the UI 2779/// user to selectively minimize the current set of visible UI to comprehend. 2780/// The second concept are tree widgets for visual UI representation of trees.<br /><br /> 2781/// 2782/// Trees thereby can be nested for tree representations and multiple nested 2783/// collapsable UI sections. All trees are started by calling of the 2784/// `nk_tree_xxx_push_tree` functions and ended by calling one of the 2785/// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label 2786/// and optionally an image to be displayed and the initial collapse state from 2787/// the nk_collapse_states section.<br /><br /> 2788/// 2789/// The runtime state of the tree is either stored outside the library by the caller 2790/// or inside which requires a unique ID. The unique ID can either be generated 2791/// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`, 2792/// by `__FILE__` and a user provided ID generated for example by loop index with 2793/// function `nk_tree_push_id` or completely provided from outside by user with 2794/// function `nk_tree_push_hashed`. 2795/// 2796/// #### Usage 2797/// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx` 2798/// functions to start a collapsable UI section and `nk_tree_xxx_pop` to mark the 2799/// end. 2800/// Each starting function will either return `false(0)` if the tree is collapsed 2801/// or hidden and therefore does not need to be filled with content or `true(1)` 2802/// if visible and required to be filled. 2803/// 2804/// !!! Note 2805/// The tree header does not require and layouting function and instead 2806/// calculates a auto height based on the currently used font size 2807/// 2808/// The tree ending functions only need to be called if the tree content is 2809/// actually visible. So make sure the tree push function is guarded by `if` 2810/// and the pop call is only taken if the tree is visible. 2811/// 2812/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2813/// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) { 2814/// nk_layout_row_dynamic(...); 2815/// nk_widget(...); 2816/// nk_tree_pop(ctx); 2817/// } 2818/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2819/// 2820/// #### Reference 2821/// Function | Description 2822/// ----------------------------|------------------------------------------- 2823/// nk_tree_push | Start a collapsable UI section with internal state management 2824/// nk_tree_push_id | Start a collapsable UI section with internal state management callable in a look 2825/// nk_tree_push_hashed | Start a collapsable UI section with internal state management with full control over internal unique ID use to store state 2826/// nk_tree_image_push | Start a collapsable UI section with image and label header 2827/// nk_tree_image_push_id | Start a collapsable UI section with image and label header and internal state management callable in a look 2828/// 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 2829/// nk_tree_pop | Ends a collapsable UI section 2830// 2831/// nk_tree_state_push | Start a collapsable UI section with external state management 2832/// nk_tree_state_image_push | Start a collapsable UI section with image and label header and external state management 2833/// nk_tree_state_pop | Ends a collapsabale UI section 2834/// 2835/// #### nk_tree_type 2836/// Flag | Description 2837/// ----------------|---------------------------------------- 2838/// NK_TREE_NODE | Highlighted tree header to mark a collapsable UI section 2839/// NK_TREE_TAB | Non-highighted tree header closer to tree representations 2840*/ 2841/*/// #### nk_tree_push 2842/// Starts a collapsable UI section with internal state management 2843/// !!! WARNING 2844/// To keep track of the runtime tree collapsable state this function uses 2845/// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2846/// to call this function in a loop please use `nk_tree_push_id` or 2847/// `nk_tree_push_hashed` instead. 2848/// 2849/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2850/// #define nk_tree_push(ctx, type, title, state) 2851/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2852/// 2853/// Parameter | Description 2854/// ------------|----------------------------------------------------------- 2855/// __ctx__ | Must point to an previously initialized `nk_context` struct 2856/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2857/// __title__ | Label printed in the tree header 2858/// __state__ | Initial tree state value out of nk_collapse_states 2859/// 2860/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2861*/ 2862#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__) 2863/*/// #### nk_tree_push_id 2864/// Starts a collapsable UI section with internal state management callable in a look 2865/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2866/// #define nk_tree_push_id(ctx, type, title, state, id) 2867/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2868/// 2869/// Parameter | Description 2870/// ------------|----------------------------------------------------------- 2871/// __ctx__ | Must point to an previously initialized `nk_context` struct 2872/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2873/// __title__ | Label printed in the tree header 2874/// __state__ | Initial tree state value out of nk_collapse_states 2875/// __id__ | Loop counter index if this function is called in a loop 2876/// 2877/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2878*/ 2879#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) 2880/*/// #### nk_tree_push_hashed 2881/// Start a collapsable UI section with internal state management with full 2882/// control over internal unique ID used to store state 2883/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2884/// 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); 2885/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2886/// 2887/// Parameter | Description 2888/// ------------|----------------------------------------------------------- 2889/// __ctx__ | Must point to an previously initialized `nk_context` struct 2890/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2891/// __title__ | Label printed in the tree header 2892/// __state__ | Initial tree state value out of nk_collapse_states 2893/// __hash__ | Memory block or string to generate the ID from 2894/// __len__ | Size of passed memory block or string in __hash__ 2895/// __seed__ | Seeding value if this function is called in a loop or default to `0` 2896/// 2897/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2898*/ 2899NK_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); 2900/*/// #### nk_tree_image_push 2901/// Start a collapsable UI section with image and label header 2902/// !!! WARNING 2903/// To keep track of the runtime tree collapsable state this function uses 2904/// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2905/// to call this function in a loop please use `nk_tree_image_push_id` or 2906/// `nk_tree_image_push_hashed` instead. 2907/// 2908/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2909/// #define nk_tree_image_push(ctx, type, img, title, state) 2910/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2911// 2912/// Parameter | Description 2913/// ------------|----------------------------------------------------------- 2914/// __ctx__ | Must point to an previously initialized `nk_context` struct 2915/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2916/// __img__ | Image to display inside the header on the left of the label 2917/// __title__ | Label printed in the tree header 2918/// __state__ | Initial tree state value out of nk_collapse_states 2919/// 2920/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2921*/ 2922#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__) 2923/*/// #### nk_tree_image_push_id 2924/// Start a collapsable UI section with image and label header and internal state 2925/// management callable in a look 2926/// 2927/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2928/// #define nk_tree_image_push_id(ctx, type, img, title, state, id) 2929/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2930/// 2931/// Parameter | Description 2932/// ------------|----------------------------------------------------------- 2933/// __ctx__ | Must point to an previously initialized `nk_context` struct 2934/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2935/// __img__ | Image to display inside the header on the left of the label 2936/// __title__ | Label printed in the tree header 2937/// __state__ | Initial tree state value out of nk_collapse_states 2938/// __id__ | Loop counter index if this function is called in a loop 2939/// 2940/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2941*/ 2942#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) 2943/*/// #### nk_tree_image_push_hashed 2944/// Start a collapsable UI section with internal state management with full 2945/// control over internal unique ID used to store state 2946/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2947/// 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); 2948/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2949/// 2950/// Parameter | Description 2951/// ------------|----------------------------------------------------------- 2952/// __ctx__ | Must point to an previously initialized `nk_context` struct 2953/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2954/// __img__ | Image to display inside the header on the left of the label 2955/// __title__ | Label printed in the tree header 2956/// __state__ | Initial tree state value out of nk_collapse_states 2957/// __hash__ | Memory block or string to generate the ID from 2958/// __len__ | Size of passed memory block or string in __hash__ 2959/// __seed__ | Seeding value if this function is called in a loop or default to `0` 2960/// 2961/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2962*/ 2963NK_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); 2964/*/// #### nk_tree_pop 2965/// Ends a collapsabale UI section 2966/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2967/// void nk_tree_pop(struct nk_context*); 2968/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2969/// 2970/// Parameter | Description 2971/// ------------|----------------------------------------------------------- 2972/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2973*/ 2974NK_API void nk_tree_pop(struct nk_context*); 2975/*/// #### nk_tree_state_push 2976/// Start a collapsable UI section with external state management 2977/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2978/// int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 2979/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2980/// 2981/// Parameter | Description 2982/// ------------|----------------------------------------------------------- 2983/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 2984/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2985/// __title__ | Label printed in the tree header 2986/// __state__ | Persistent state to update 2987/// 2988/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2989*/ 2990NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 2991/*/// #### nk_tree_state_image_push 2992/// Start a collapsable UI section with image and label header and external state management 2993/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2994/// int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); 2995/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2996/// 2997/// Parameter | Description 2998/// ------------|----------------------------------------------------------- 2999/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3000/// __img__ | Image to display inside the header on the left of the label 3001/// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 3002/// __title__ | Label printed in the tree header 3003/// __state__ | Persistent state to update 3004/// 3005/// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 3006*/ 3007NK_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); 3008/*/// #### nk_tree_state_pop 3009/// Ends a collapsabale UI section 3010/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3011/// void nk_tree_state_pop(struct nk_context*); 3012/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3013/// 3014/// Parameter | Description 3015/// ------------|----------------------------------------------------------- 3016/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3017*/ 3018NK_API void nk_tree_state_pop(struct nk_context*); 3019 3020#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__) 3021#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) 3022NK_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); 3023NK_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); 3024NK_API void nk_tree_element_pop(struct nk_context*); 3025 3026/* ============================================================================= 3027 * 3028 * LIST VIEW 3029 * 3030 * ============================================================================= */ 3031struct nk_list_view { 3032/* public: */ 3033 int begin, end, count; 3034/* private: */ 3035 int total_height; 3036 struct nk_context *ctx; 3037 nk_uint *scroll_pointer; 3038 nk_uint scroll_value; 3039}; 3040NK_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); 3041NK_API void nk_list_view_end(struct nk_list_view*); 3042/* ============================================================================= 3043 * 3044 * WIDGET 3045 * 3046 * ============================================================================= */ 3047enum nk_widget_layout_states { 3048 NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */ 3049 NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */ 3050 NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */ 3051}; 3052enum nk_widget_states { 3053 NK_WIDGET_STATE_MODIFIED = NK_FLAG(1), 3054 NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */ 3055 NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */ 3056 NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */ 3057 NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */ 3058 NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */ 3059 NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */ 3060 NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */ 3061}; 3062NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*); 3063NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2); 3064NK_API struct nk_rect nk_widget_bounds(struct nk_context*); 3065NK_API struct nk_vec2 nk_widget_position(struct nk_context*); 3066NK_API struct nk_vec2 nk_widget_size(struct nk_context*); 3067NK_API float nk_widget_width(struct nk_context*); 3068NK_API float nk_widget_height(struct nk_context*); 3069NK_API int nk_widget_is_hovered(struct nk_context*); 3070NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons); 3071NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down); 3072NK_API void nk_spacing(struct nk_context*, int cols); 3073/* ============================================================================= 3074 * 3075 * TEXT 3076 * 3077 * ============================================================================= */ 3078enum nk_text_align { 3079 NK_TEXT_ALIGN_LEFT = 0x01, 3080 NK_TEXT_ALIGN_CENTERED = 0x02, 3081 NK_TEXT_ALIGN_RIGHT = 0x04, 3082 NK_TEXT_ALIGN_TOP = 0x08, 3083 NK_TEXT_ALIGN_MIDDLE = 0x10, 3084 NK_TEXT_ALIGN_BOTTOM = 0x20 3085}; 3086enum nk_text_alignment { 3087 NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT, 3088 NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED, 3089 NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT 3090}; 3091NK_API void nk_text(struct nk_context*, const char*, int, nk_flags); 3092NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color); 3093NK_API void nk_text_wrap(struct nk_context*, const char*, int); 3094NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color); 3095NK_API void nk_label(struct nk_context*, const char*, nk_flags align); 3096NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color); 3097NK_API void nk_label_wrap(struct nk_context*, const char*); 3098NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color); 3099NK_API void nk_image(struct nk_context*, struct nk_image); 3100NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color); 3101#ifdef NK_INCLUDE_STANDARD_VARARGS 3102NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3); 3103NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4); 3104NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2); 3105NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3); 3106NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3); 3107NK_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); 3108NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3109NK_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); 3110NK_API void nk_value_bool(struct nk_context*, const char *prefix, int); 3111NK_API void nk_value_int(struct nk_context*, const char *prefix, int); 3112NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int); 3113NK_API void nk_value_float(struct nk_context*, const char *prefix, float); 3114NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color); 3115NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color); 3116NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color); 3117#endif 3118/* ============================================================================= 3119 * 3120 * BUTTON 3121 * 3122 * ============================================================================= */ 3123NK_API int nk_button_text(struct nk_context*, const char *title, int len); 3124NK_API int nk_button_label(struct nk_context*, const char *title); 3125NK_API int nk_button_color(struct nk_context*, struct nk_color); 3126NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type); 3127NK_API int nk_button_image(struct nk_context*, struct nk_image img); 3128NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment); 3129NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3130NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment); 3131NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment); 3132NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len); 3133NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title); 3134NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type); 3135NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img); 3136NK_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); 3137NK_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); 3138NK_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); 3139NK_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); 3140NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior); 3141NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior); 3142NK_API int nk_button_pop_behavior(struct nk_context*); 3143/* ============================================================================= 3144 * 3145 * CHECKBOX 3146 * 3147 * ============================================================================= */ 3148NK_API int nk_check_label(struct nk_context*, const char*, int active); 3149NK_API int nk_check_text(struct nk_context*, const char*, int,int active); 3150NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value); 3151NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value); 3152NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active); 3153NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active); 3154NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value); 3155NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value); 3156/* ============================================================================= 3157 * 3158 * RADIO BUTTON 3159 * 3160 * ============================================================================= */ 3161NK_API int nk_radio_label(struct nk_context*, const char*, int *active); 3162NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active); 3163NK_API int nk_option_label(struct nk_context*, const char*, int active); 3164NK_API int nk_option_text(struct nk_context*, const char*, int, int active); 3165/* ============================================================================= 3166 * 3167 * SELECTABLE 3168 * 3169 * ============================================================================= */ 3170NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value); 3171NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value); 3172NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value); 3173NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value); 3174NK_API int nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int *value); 3175NK_API int nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int *value); 3176 3177NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value); 3178NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value); 3179NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value); 3180NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value); 3181NK_API int nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, int value); 3182NK_API int nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, int value); 3183 3184/* ============================================================================= 3185 * 3186 * SLIDER 3187 * 3188 * ============================================================================= */ 3189NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step); 3190NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); 3191NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step); 3192NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step); 3193/* ============================================================================= 3194 * 3195 * PROGRESSBAR 3196 * 3197 * ============================================================================= */ 3198NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable); 3199NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable); 3200 3201/* ============================================================================= 3202 * 3203 * COLOR PICKER 3204 * 3205 * ============================================================================= */ 3206NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format); 3207NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format); 3208/* ============================================================================= 3209 * 3210 * PROPERTIES 3211 * 3212 * ============================================================================= 3213/// ### Properties 3214/// Properties are the main value modification widgets in Nuklear. Changing a value 3215/// can be achieved by dragging, adding/removing incremental steps on button click 3216/// or by directly typing a number. 3217/// 3218/// #### Usage 3219/// Each property requires a unique name for identifaction that is also used for 3220/// displaying a label. If you want to use the same name multiple times make sure 3221/// add a '#' before your name. The '#' will not be shown but will generate a 3222/// unique ID. Each propery also takes in a minimum and maximum value. If you want 3223/// to make use of the complete number range of a type just use the provided 3224/// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for 3225/// `nk_property_int` and `nk_propertyi`. In additional each property takes in 3226/// a increment value that will be added or subtracted if either the increment 3227/// decrement button is clicked. Finally there is a value for increment per pixel 3228/// dragged that is added or subtracted from the value. 3229/// 3230/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3231/// int value = 0; 3232/// struct nk_context ctx; 3233/// nk_init_xxx(&ctx, ...); 3234/// while (1) { 3235/// // Input 3236/// Event evt; 3237/// nk_input_begin(&ctx); 3238/// while (GetEvent(&evt)) { 3239/// if (evt.type == MOUSE_MOVE) 3240/// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 3241/// else if (evt.type == [...]) { 3242/// nk_input_xxx(...); 3243/// } 3244/// } 3245/// nk_input_end(&ctx); 3246/// // 3247/// // Window 3248/// if (nk_begin_xxx(...) { 3249/// // Property 3250/// nk_layout_row_dynamic(...); 3251/// nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1); 3252/// } 3253/// nk_end(ctx); 3254/// // 3255/// // Draw 3256/// const struct nk_command *cmd = 0; 3257/// nk_foreach(cmd, &ctx) { 3258/// switch (cmd->type) { 3259/// case NK_COMMAND_LINE: 3260/// your_draw_line_function(...) 3261/// break; 3262/// case NK_COMMAND_RECT 3263/// your_draw_rect_function(...) 3264/// break; 3265/// case ...: 3266/// // [...] 3267/// } 3268/// nk_clear(&ctx); 3269/// } 3270/// nk_free(&ctx); 3271/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3272/// 3273/// #### Reference 3274/// Function | Description 3275/// --------------------|------------------------------------------- 3276/// nk_property_int | Integer property directly modifing a passed in value 3277/// nk_property_float | Float property directly modifing a passed in value 3278/// nk_property_double | Double property directly modifing a passed in value 3279/// nk_propertyi | Integer property returning the modified int value 3280/// nk_propertyf | Float property returning the modified float value 3281/// nk_propertyd | Double property returning the modified double value 3282/// 3283*/ 3284/*/// #### nk_property_int 3285/// Integer property directly modifing a passed in value 3286/// !!! WARNING 3287/// To generate a unique property ID using the same label make sure to insert 3288/// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3289/// 3290/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3291/// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3292/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3293/// 3294/// Parameter | Description 3295/// --------------------|----------------------------------------------------------- 3296/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3297/// __name__ | String used both as a label as well as a unique identifier 3298/// __min__ | Minimum value not allowed to be underflown 3299/// __val__ | Integer pointer to be modified 3300/// __max__ | Maximum value not allowed to be overflown 3301/// __step__ | Increment added and subtracted on increment and decrement button 3302/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3303*/ 3304NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3305/*/// #### nk_property_float 3306/// Float property directly modifing a passed in value 3307/// !!! WARNING 3308/// To generate a unique property ID using the same label make sure to insert 3309/// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3310/// 3311/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3312/// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3313/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3314/// 3315/// Parameter | Description 3316/// --------------------|----------------------------------------------------------- 3317/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3318/// __name__ | String used both as a label as well as a unique identifier 3319/// __min__ | Minimum value not allowed to be underflown 3320/// __val__ | Float pointer to be modified 3321/// __max__ | Maximum value not allowed to be overflown 3322/// __step__ | Increment added and subtracted on increment and decrement button 3323/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3324*/ 3325NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3326/*/// #### nk_property_double 3327/// Double property directly modifing a passed in value 3328/// !!! WARNING 3329/// To generate a unique property ID using the same label make sure to insert 3330/// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3331/// 3332/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3333/// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel); 3334/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3335/// 3336/// Parameter | Description 3337/// --------------------|----------------------------------------------------------- 3338/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3339/// __name__ | String used both as a label as well as a unique identifier 3340/// __min__ | Minimum value not allowed to be underflown 3341/// __val__ | Double pointer to be modified 3342/// __max__ | Maximum value not allowed to be overflown 3343/// __step__ | Increment added and subtracted on increment and decrement button 3344/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3345*/ 3346NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel); 3347/*/// #### nk_propertyi 3348/// Integer property modifing a passed in value and returning the new value 3349/// !!! WARNING 3350/// To generate a unique property ID using the same label make sure to insert 3351/// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3352/// 3353/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3354/// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3355/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3356/// 3357/// Parameter | Description 3358/// --------------------|----------------------------------------------------------- 3359/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3360/// __name__ | String used both as a label as well as a unique identifier 3361/// __min__ | Minimum value not allowed to be underflown 3362/// __val__ | Current integer value to be modified and returned 3363/// __max__ | Maximum value not allowed to be overflown 3364/// __step__ | Increment added and subtracted on increment and decrement button 3365/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3366/// 3367/// Returns the new modified integer value 3368*/ 3369NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3370/*/// #### nk_propertyf 3371/// Float property modifing a passed in value and returning the new value 3372/// !!! WARNING 3373/// To generate a unique property ID using the same label make sure to insert 3374/// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3375/// 3376/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3377/// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3378/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3379/// 3380/// Parameter | Description 3381/// --------------------|----------------------------------------------------------- 3382/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3383/// __name__ | String used both as a label as well as a unique identifier 3384/// __min__ | Minimum value not allowed to be underflown 3385/// __val__ | Current float value to be modified and returned 3386/// __max__ | Maximum value not allowed to be overflown 3387/// __step__ | Increment added and subtracted on increment and decrement button 3388/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3389/// 3390/// Returns the new modified float value 3391*/ 3392NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3393/*/// #### nk_propertyd 3394/// Float property modifing a passed in value and returning the new value 3395/// !!! WARNING 3396/// To generate a unique property ID using the same label make sure to insert 3397/// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3398/// 3399/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3400/// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel); 3401/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3402/// 3403/// Parameter | Description 3404/// --------------------|----------------------------------------------------------- 3405/// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3406/// __name__ | String used both as a label as well as a unique identifier 3407/// __min__ | Minimum value not allowed to be underflown 3408/// __val__ | Current double value to be modified and returned 3409/// __max__ | Maximum value not allowed to be overflown 3410/// __step__ | Increment added and subtracted on increment and decrement button 3411/// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3412/// 3413/// Returns the new modified double value 3414*/ 3415NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel); 3416/* ============================================================================= 3417 * 3418 * TEXT EDIT 3419 * 3420 * ============================================================================= */ 3421enum nk_edit_flags { 3422 NK_EDIT_DEFAULT = 0, 3423 NK_EDIT_READ_ONLY = NK_FLAG(0), 3424 NK_EDIT_AUTO_SELECT = NK_FLAG(1), 3425 NK_EDIT_SIG_ENTER = NK_FLAG(2), 3426 NK_EDIT_ALLOW_TAB = NK_FLAG(3), 3427 NK_EDIT_NO_CURSOR = NK_FLAG(4), 3428 NK_EDIT_SELECTABLE = NK_FLAG(5), 3429 NK_EDIT_CLIPBOARD = NK_FLAG(6), 3430 NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7), 3431 NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8), 3432 NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9), 3433 NK_EDIT_MULTILINE = NK_FLAG(10), 3434 NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(11) 3435}; 3436enum nk_edit_types { 3437 NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE, 3438 NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD, 3439 NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD, 3440 NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD 3441}; 3442enum nk_edit_events { 3443 NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */ 3444 NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */ 3445 NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */ 3446 NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */ 3447 NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */ 3448}; 3449NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter); 3450NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter); 3451NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter); 3452NK_API void nk_edit_focus(struct nk_context*, nk_flags flags); 3453NK_API void nk_edit_unfocus(struct nk_context*); 3454/* ============================================================================= 3455 * 3456 * CHART 3457 * 3458 * ============================================================================= */ 3459NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max); 3460NK_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); 3461NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value); 3462NK_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); 3463NK_API nk_flags nk_chart_push(struct nk_context*, float); 3464NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int); 3465NK_API void nk_chart_end(struct nk_context*); 3466NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset); 3467NK_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); 3468/* ============================================================================= 3469 * 3470 * POPUP 3471 * 3472 * ============================================================================= */ 3473NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); 3474NK_API void nk_popup_close(struct nk_context*); 3475NK_API void nk_popup_end(struct nk_context*); 3476NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); 3477NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); 3478/* ============================================================================= 3479 * 3480 * COMBOBOX 3481 * 3482 * ============================================================================= */ 3483NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size); 3484NK_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); 3485NK_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); 3486NK_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); 3487NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); 3488NK_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); 3489NK_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); 3490NK_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); 3491/* ============================================================================= 3492 * 3493 * ABSTRACT COMBOBOX 3494 * 3495 * ============================================================================= */ 3496NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size); 3497NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size); 3498NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size); 3499NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size); 3500NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size); 3501NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size); 3502NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size); 3503NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size); 3504NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size); 3505NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment); 3506NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment); 3507NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3508NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment); 3509NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3510NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3511NK_API void nk_combo_close(struct nk_context*); 3512NK_API void nk_combo_end(struct nk_context*); 3513/* ============================================================================= 3514 * 3515 * CONTEXTUAL 3516 * 3517 * ============================================================================= */ 3518NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds); 3519NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align); 3520NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align); 3521NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3522NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3523NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3524NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3525NK_API void nk_contextual_close(struct nk_context*); 3526NK_API void nk_contextual_end(struct nk_context*); 3527/* ============================================================================= 3528 * 3529 * TOOLTIP 3530 * 3531 * ============================================================================= */ 3532NK_API void nk_tooltip(struct nk_context*, const char*); 3533#ifdef NK_INCLUDE_STANDARD_VARARGS 3534NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2); 3535NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3536#endif 3537NK_API int nk_tooltip_begin(struct nk_context*, float width); 3538NK_API void nk_tooltip_end(struct nk_context*); 3539/* ============================================================================= 3540 * 3541 * MENU 3542 * 3543 * ============================================================================= */ 3544NK_API void nk_menubar_begin(struct nk_context*); 3545NK_API void nk_menubar_end(struct nk_context*); 3546NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size); 3547NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size); 3548NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size); 3549NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size); 3550NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size); 3551NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size); 3552NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3553NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3554NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align); 3555NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment); 3556NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3557NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3558NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3559NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3560NK_API void nk_menu_close(struct nk_context*); 3561NK_API void nk_menu_end(struct nk_context*); 3562/* ============================================================================= 3563 * 3564 * STYLE 3565 * 3566 * ============================================================================= */ 3567enum nk_style_colors { 3568 NK_COLOR_TEXT, 3569 NK_COLOR_WINDOW, 3570 NK_COLOR_HEADER, 3571 NK_COLOR_BORDER, 3572 NK_COLOR_BUTTON, 3573 NK_COLOR_BUTTON_HOVER, 3574 NK_COLOR_BUTTON_ACTIVE, 3575 NK_COLOR_TOGGLE, 3576 NK_COLOR_TOGGLE_HOVER, 3577 NK_COLOR_TOGGLE_CURSOR, 3578 NK_COLOR_SELECT, 3579 NK_COLOR_SELECT_ACTIVE, 3580 NK_COLOR_SLIDER, 3581 NK_COLOR_SLIDER_CURSOR, 3582 NK_COLOR_SLIDER_CURSOR_HOVER, 3583 NK_COLOR_SLIDER_CURSOR_ACTIVE, 3584 NK_COLOR_PROPERTY, 3585 NK_COLOR_EDIT, 3586 NK_COLOR_EDIT_CURSOR, 3587 NK_COLOR_COMBO, 3588 NK_COLOR_CHART, 3589 NK_COLOR_CHART_COLOR, 3590 NK_COLOR_CHART_COLOR_HIGHLIGHT, 3591 NK_COLOR_SCROLLBAR, 3592 NK_COLOR_SCROLLBAR_CURSOR, 3593 NK_COLOR_SCROLLBAR_CURSOR_HOVER, 3594 NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 3595 NK_COLOR_TAB_HEADER, 3596 NK_COLOR_COUNT 3597}; 3598enum nk_style_cursor { 3599 NK_CURSOR_ARROW, 3600 NK_CURSOR_TEXT, 3601 NK_CURSOR_MOVE, 3602 NK_CURSOR_RESIZE_VERTICAL, 3603 NK_CURSOR_RESIZE_HORIZONTAL, 3604 NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT, 3605 NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT, 3606 NK_CURSOR_COUNT 3607}; 3608NK_API void nk_style_default(struct nk_context*); 3609NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*); 3610NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*); 3611NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*); 3612NK_API const char* nk_style_get_color_by_name(enum nk_style_colors); 3613NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*); 3614NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor); 3615NK_API void nk_style_show_cursor(struct nk_context*); 3616NK_API void nk_style_hide_cursor(struct nk_context*); 3617 3618NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*); 3619NK_API int nk_style_push_float(struct nk_context*, float*, float); 3620NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2); 3621NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item); 3622NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags); 3623NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color); 3624 3625NK_API int nk_style_pop_font(struct nk_context*); 3626NK_API int nk_style_pop_float(struct nk_context*); 3627NK_API int nk_style_pop_vec2(struct nk_context*); 3628NK_API int nk_style_pop_style_item(struct nk_context*); 3629NK_API int nk_style_pop_flags(struct nk_context*); 3630NK_API int nk_style_pop_color(struct nk_context*); 3631/* ============================================================================= 3632 * 3633 * COLOR 3634 * 3635 * ============================================================================= */ 3636NK_API struct nk_color nk_rgb(int r, int g, int b); 3637NK_API struct nk_color nk_rgb_iv(const int *rgb); 3638NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb); 3639NK_API struct nk_color nk_rgb_f(float r, float g, float b); 3640NK_API struct nk_color nk_rgb_fv(const float *rgb); 3641NK_API struct nk_color nk_rgb_cf(struct nk_colorf c); 3642NK_API struct nk_color nk_rgb_hex(const char *rgb); 3643 3644NK_API struct nk_color nk_rgba(int r, int g, int b, int a); 3645NK_API struct nk_color nk_rgba_u32(nk_uint); 3646NK_API struct nk_color nk_rgba_iv(const int *rgba); 3647NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba); 3648NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a); 3649NK_API struct nk_color nk_rgba_fv(const float *rgba); 3650NK_API struct nk_color nk_rgba_cf(struct nk_colorf c); 3651NK_API struct nk_color nk_rgba_hex(const char *rgb); 3652 3653NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a); 3654NK_API struct nk_colorf nk_hsva_colorfv(float *c); 3655NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in); 3656NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in); 3657 3658NK_API struct nk_color nk_hsv(int h, int s, int v); 3659NK_API struct nk_color nk_hsv_iv(const int *hsv); 3660NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv); 3661NK_API struct nk_color nk_hsv_f(float h, float s, float v); 3662NK_API struct nk_color nk_hsv_fv(const float *hsv); 3663 3664NK_API struct nk_color nk_hsva(int h, int s, int v, int a); 3665NK_API struct nk_color nk_hsva_iv(const int *hsva); 3666NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva); 3667NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a); 3668NK_API struct nk_color nk_hsva_fv(const float *hsva); 3669 3670/* color (conversion nuklear --> user) */ 3671NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color); 3672NK_API void nk_color_fv(float *rgba_out, struct nk_color); 3673NK_API struct nk_colorf nk_color_cf(struct nk_color); 3674NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color); 3675NK_API void nk_color_dv(double *rgba_out, struct nk_color); 3676 3677NK_API nk_uint nk_color_u32(struct nk_color); 3678NK_API void nk_color_hex_rgba(char *output, struct nk_color); 3679NK_API void nk_color_hex_rgb(char *output, struct nk_color); 3680 3681NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color); 3682NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color); 3683NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color); 3684NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color); 3685NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color); 3686NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color); 3687 3688NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color); 3689NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color); 3690NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color); 3691NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color); 3692NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color); 3693NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color); 3694/* ============================================================================= 3695 * 3696 * IMAGE 3697 * 3698 * ============================================================================= */ 3699NK_API nk_handle nk_handle_ptr(void*); 3700NK_API nk_handle nk_handle_id(int); 3701NK_API struct nk_image nk_image_handle(nk_handle); 3702NK_API struct nk_image nk_image_ptr(void*); 3703NK_API struct nk_image nk_image_id(int); 3704NK_API int nk_image_is_subimage(const struct nk_image* img); 3705NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region); 3706NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region); 3707NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region); 3708/* ============================================================================= 3709 * 3710 * MATH 3711 * 3712 * ============================================================================= */ 3713NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed); 3714NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading); 3715 3716NK_API struct nk_vec2 nk_vec2(float x, float y); 3717NK_API struct nk_vec2 nk_vec2i(int x, int y); 3718NK_API struct nk_vec2 nk_vec2v(const float *xy); 3719NK_API struct nk_vec2 nk_vec2iv(const int *xy); 3720 3721NK_API struct nk_rect nk_get_null_rect(void); 3722NK_API struct nk_rect nk_rect(float x, float y, float w, float h); 3723NK_API struct nk_rect nk_recti(int x, int y, int w, int h); 3724NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size); 3725NK_API struct nk_rect nk_rectv(const float *xywh); 3726NK_API struct nk_rect nk_rectiv(const int *xywh); 3727NK_API struct nk_vec2 nk_rect_pos(struct nk_rect); 3728NK_API struct nk_vec2 nk_rect_size(struct nk_rect); 3729/* ============================================================================= 3730 * 3731 * STRING 3732 * 3733 * ============================================================================= */ 3734NK_API int nk_strlen(const char *str); 3735NK_API int nk_stricmp(const char *s1, const char *s2); 3736NK_API int nk_stricmpn(const char *s1, const char *s2, int n); 3737NK_API int nk_strtoi(const char *str, const char **endptr); 3738NK_API float nk_strtof(const char *str, const char **endptr); 3739NK_API double nk_strtod(const char *str, const char **endptr); 3740NK_API int nk_strfilter(const char *text, const char *regexp); 3741NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score); 3742NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score); 3743/* ============================================================================= 3744 * 3745 * UTF-8 3746 * 3747 * ============================================================================= */ 3748NK_API int nk_utf_decode(const char*, nk_rune*, int); 3749NK_API int nk_utf_encode(nk_rune, char*, int); 3750NK_API int nk_utf_len(const char*, int byte_len); 3751NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len); 3752/* =============================================================== 3753 * 3754 * FONT 3755 * 3756 * ===============================================================*/ 3757/* Font handling in this library was designed to be quite customizable and lets 3758 you decide what you want to use and what you want to provide. There are three 3759 different ways to use the font atlas. The first two will use your font 3760 handling scheme and only requires essential data to run nuklear. The next 3761 slightly more advanced features is font handling with vertex buffer output. 3762 Finally the most complex API wise is using nuklear's font baking API. 3763 3764 1.) Using your own implementation without vertex buffer output 3765 -------------------------------------------------------------- 3766 So first up the easiest way to do font handling is by just providing a 3767 `nk_user_font` struct which only requires the height in pixel of the used 3768 font and a callback to calculate the width of a string. This way of handling 3769 fonts is best fitted for using the normal draw shape command API where you 3770 do all the text drawing yourself and the library does not require any kind 3771 of deeper knowledge about which font handling mechanism you use. 3772 IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist 3773 over the complete life time! I know this sucks but it is currently the only 3774 way to switch between fonts. 3775 3776 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3777 { 3778 your_font_type *type = handle.ptr; 3779 float text_width = ...; 3780 return text_width; 3781 } 3782 3783 struct nk_user_font font; 3784 font.userdata.ptr = &your_font_class_or_struct; 3785 font.height = your_font_height; 3786 font.width = your_text_width_calculation; 3787 3788 struct nk_context ctx; 3789 nk_init_default(&ctx, &font); 3790 3791 2.) Using your own implementation with vertex buffer output 3792 -------------------------------------------------------------- 3793 While the first approach works fine if you don't want to use the optional 3794 vertex buffer output it is not enough if you do. To get font handling working 3795 for these cases you have to provide two additional parameters inside the 3796 `nk_user_font`. First a texture atlas handle used to draw text as subimages 3797 of a bigger font atlas texture and a callback to query a character's glyph 3798 information (offset, size, ...). So it is still possible to provide your own 3799 font and use the vertex buffer output. 3800 3801 float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3802 { 3803 your_font_type *type = handle.ptr; 3804 float text_width = ...; 3805 return text_width; 3806 } 3807 void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 3808 { 3809 your_font_type *type = handle.ptr; 3810 glyph.width = ...; 3811 glyph.height = ...; 3812 glyph.xadvance = ...; 3813 glyph.uv[0].x = ...; 3814 glyph.uv[0].y = ...; 3815 glyph.uv[1].x = ...; 3816 glyph.uv[1].y = ...; 3817 glyph.offset.x = ...; 3818 glyph.offset.y = ...; 3819 } 3820 3821 struct nk_user_font font; 3822 font.userdata.ptr = &your_font_class_or_struct; 3823 font.height = your_font_height; 3824 font.width = your_text_width_calculation; 3825 font.query = query_your_font_glyph; 3826 font.texture.id = your_font_texture; 3827 3828 struct nk_context ctx; 3829 nk_init_default(&ctx, &font); 3830 3831 3.) Nuklear font baker 3832 ------------------------------------ 3833 The final approach if you do not have a font handling functionality or don't 3834 want to use it in this library is by using the optional font baker. 3835 The font baker APIs can be used to create a font plus font atlas texture 3836 and can be used with or without the vertex buffer output. 3837 3838 It still uses the `nk_user_font` struct and the two different approaches 3839 previously stated still work. The font baker is not located inside 3840 `nk_context` like all other systems since it can be understood as more of 3841 an extension to nuklear and does not really depend on any `nk_context` state. 3842 3843 Font baker need to be initialized first by one of the nk_font_atlas_init_xxx 3844 functions. If you don't care about memory just call the default version 3845 `nk_font_atlas_init_default` which will allocate all memory from the standard library. 3846 If you want to control memory allocation but you don't care if the allocated 3847 memory is temporary and therefore can be freed directly after the baking process 3848 is over or permanent you can call `nk_font_atlas_init`. 3849 3850 After successfully initializing the font baker you can add Truetype(.ttf) fonts from 3851 different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`. 3852 functions. Adding font will permanently store each font, font config and ttf memory block(!) 3853 inside the font atlas and allows to reuse the font atlas. If you don't want to reuse 3854 the font baker by for example adding additional fonts you can call 3855 `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end). 3856 3857 As soon as you added all fonts you wanted you can now start the baking process 3858 for every selected glyph to image by calling `nk_font_atlas_bake`. 3859 The baking process returns image memory, width and height which can be used to 3860 either create your own image object or upload it to any graphics library. 3861 No matter which case you finally have to call `nk_font_atlas_end` which 3862 will free all temporary memory including the font atlas image so make sure 3863 you created our texture beforehand. `nk_font_atlas_end` requires a handle 3864 to your font texture or object and optionally fills a `struct nk_draw_null_texture` 3865 which can be used for the optional vertex output. If you don't want it just 3866 set the argument to `NULL`. 3867 3868 At this point you are done and if you don't want to reuse the font atlas you 3869 can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration 3870 memory. Finally if you don't use the font atlas and any of it's fonts anymore 3871 you need to call `nk_font_atlas_clear` to free all memory still being used. 3872 3873 struct nk_font_atlas atlas; 3874 nk_font_atlas_init_default(&atlas); 3875 nk_font_atlas_begin(&atlas); 3876 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0); 3877 nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0); 3878 const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32); 3879 nk_font_atlas_end(&atlas, nk_handle_id(texture), 0); 3880 3881 struct nk_context ctx; 3882 nk_init_default(&ctx, &font->handle); 3883 while (1) { 3884 3885 } 3886 nk_font_atlas_clear(&atlas); 3887 3888 The font baker API is probably the most complex API inside this library and 3889 I would suggest reading some of my examples `example/` to get a grip on how 3890 to use the font atlas. There are a number of details I left out. For example 3891 how to merge fonts, configure a font with `nk_font_config` to use other languages, 3892 use another texture coordinate format and a lot more: 3893 3894 struct nk_font_config cfg = nk_font_config(font_pixel_height); 3895 cfg.merge_mode = nk_false or nk_true; 3896 cfg.range = nk_font_korean_glyph_ranges(); 3897 cfg.coord_type = NK_COORD_PIXEL; 3898 nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg); 3899 3900*/ 3901struct nk_user_font_glyph; 3902typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len); 3903typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height, 3904 struct nk_user_font_glyph *glyph, 3905 nk_rune codepoint, nk_rune next_codepoint); 3906 3907#if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT) 3908struct nk_user_font_glyph { 3909 struct nk_vec2 uv[2]; 3910 /* texture coordinates */ 3911 struct nk_vec2 offset; 3912 /* offset between top left and glyph */ 3913 float width, height; 3914 /* size of the glyph */ 3915 float xadvance; 3916 /* offset to the next glyph */ 3917}; 3918#endif 3919 3920struct nk_user_font { 3921 nk_handle userdata; 3922 /* user provided font handle */ 3923 float height; 3924 /* max height of the font */ 3925 nk_text_width_f width; 3926 /* font string width in pixel callback */ 3927#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 3928 nk_query_font_glyph_f query; 3929 /* font glyph callback to query drawing info */ 3930 nk_handle texture; 3931 /* texture handle to the used font atlas or texture */ 3932#endif 3933}; 3934 3935#ifdef NK_INCLUDE_FONT_BAKING 3936enum nk_font_coord_type { 3937 NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */ 3938 NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */ 3939}; 3940 3941struct nk_font; 3942struct nk_baked_font { 3943 float height; 3944 /* height of the font */ 3945 float ascent, descent; 3946 /* font glyphs ascent and descent */ 3947 nk_rune glyph_offset; 3948 /* glyph array offset inside the font glyph baking output array */ 3949 nk_rune glyph_count; 3950 /* number of glyphs of this font inside the glyph baking array output */ 3951 const nk_rune *ranges; 3952 /* font codepoint ranges as pairs of (from/to) and 0 as last element */ 3953}; 3954 3955struct nk_font_config { 3956 struct nk_font_config *next; 3957 /* NOTE: only used internally */ 3958 void *ttf_blob; 3959 /* pointer to loaded TTF file memory block. 3960 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 3961 nk_size ttf_size; 3962 /* size of the loaded TTF file memory block 3963 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 3964 3965 unsigned char ttf_data_owned_by_atlas; 3966 /* used inside font atlas: default to: 0*/ 3967 unsigned char merge_mode; 3968 /* merges this font into the last font */ 3969 unsigned char pixel_snap; 3970 /* align every character to pixel boundary (if true set oversample (1,1)) */ 3971 unsigned char oversample_v, oversample_h; 3972 /* rasterize at hight quality for sub-pixel position */ 3973 unsigned char padding[3]; 3974 3975 float size; 3976 /* baked pixel height of the font */ 3977 enum nk_font_coord_type coord_type; 3978 /* texture coordinate format with either pixel or UV coordinates */ 3979 struct nk_vec2 spacing; 3980 /* extra pixel spacing between glyphs */ 3981 const nk_rune *range; 3982 /* list of unicode ranges (2 values per range, zero terminated) */ 3983 struct nk_baked_font *font; 3984 /* font to setup in the baking process: NOTE: not needed for font atlas */ 3985 nk_rune fallback_glyph; 3986 /* fallback glyph to use if a given rune is not found */ 3987 struct nk_font_config *n; 3988 struct nk_font_config *p; 3989}; 3990 3991struct nk_font_glyph { 3992 nk_rune codepoint; 3993 float xadvance; 3994 float x0, y0, x1, y1, w, h; 3995 float u0, v0, u1, v1; 3996}; 3997 3998struct nk_font { 3999 struct nk_font *next; 4000 struct nk_user_font handle; 4001 struct nk_baked_font info; 4002 float scale; 4003 struct nk_font_glyph *glyphs; 4004 const struct nk_font_glyph *fallback; 4005 nk_rune fallback_codepoint; 4006 nk_handle texture; 4007 struct nk_font_config *config; 4008}; 4009 4010enum nk_font_atlas_format { 4011 NK_FONT_ATLAS_ALPHA8, 4012 NK_FONT_ATLAS_RGBA32 4013}; 4014 4015struct nk_font_atlas { 4016 void *pixel; 4017 int tex_width; 4018 int tex_height; 4019 4020 struct nk_allocator permanent; 4021 struct nk_allocator temporary; 4022 4023 struct nk_recti custom; 4024 struct nk_cursor cursors[NK_CURSOR_COUNT]; 4025 4026 int glyph_count; 4027 struct nk_font_glyph *glyphs; 4028 struct nk_font *default_font; 4029 struct nk_font *fonts; 4030 struct nk_font_config *config; 4031 int font_num; 4032}; 4033 4034/* some language glyph codepoint ranges */ 4035NK_API const nk_rune *nk_font_default_glyph_ranges(void); 4036NK_API const nk_rune *nk_font_chinese_glyph_ranges(void); 4037NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void); 4038NK_API const nk_rune *nk_font_korean_glyph_ranges(void); 4039 4040#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4041NK_API void nk_font_atlas_init_default(struct nk_font_atlas*); 4042#endif 4043NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*); 4044NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient); 4045NK_API void nk_font_atlas_begin(struct nk_font_atlas*); 4046NK_API struct nk_font_config nk_font_config(float pixel_height); 4047NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*); 4048#ifdef NK_INCLUDE_DEFAULT_FONT 4049NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*); 4050#endif 4051NK_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); 4052#ifdef NK_INCLUDE_STANDARD_IO 4053NK_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*); 4054#endif 4055NK_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*); 4056NK_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); 4057NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format); 4058NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*); 4059NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode); 4060NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas); 4061NK_API void nk_font_atlas_clear(struct nk_font_atlas*); 4062 4063#endif 4064 4065/* ============================================================== 4066 * 4067 * MEMORY BUFFER 4068 * 4069 * ===============================================================*/ 4070/* A basic (double)-buffer with linear allocation and resetting as only 4071 freeing policy. The buffer's main purpose is to control all memory management 4072 inside the GUI toolkit and still leave memory control as much as possible in 4073 the hand of the user while also making sure the library is easy to use if 4074 not as much control is needed. 4075 In general all memory inside this library can be provided from the user in 4076 three different ways. 4077 4078 The first way and the one providing most control is by just passing a fixed 4079 size memory block. In this case all control lies in the hand of the user 4080 since he can exactly control where the memory comes from and how much memory 4081 the library should consume. Of course using the fixed size API removes the 4082 ability to automatically resize a buffer if not enough memory is provided so 4083 you have to take over the resizing. While being a fixed sized buffer sounds 4084 quite limiting, it is very effective in this library since the actual memory 4085 consumption is quite stable and has a fixed upper bound for a lot of cases. 4086 4087 If you don't want to think about how much memory the library should allocate 4088 at all time or have a very dynamic UI with unpredictable memory consumption 4089 habits but still want control over memory allocation you can use the dynamic 4090 allocator based API. The allocator consists of two callbacks for allocating 4091 and freeing memory and optional userdata so you can plugin your own allocator. 4092 4093 The final and easiest way can be used by defining 4094 NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory 4095 allocation functions malloc and free and takes over complete control over 4096 memory in this library. 4097*/ 4098struct nk_memory_status { 4099 void *memory; 4100 unsigned int type; 4101 nk_size size; 4102 nk_size allocated; 4103 nk_size needed; 4104 nk_size calls; 4105}; 4106 4107enum nk_allocation_type { 4108 NK_BUFFER_FIXED, 4109 NK_BUFFER_DYNAMIC 4110}; 4111 4112enum nk_buffer_allocation_type { 4113 NK_BUFFER_FRONT, 4114 NK_BUFFER_BACK, 4115 NK_BUFFER_MAX 4116}; 4117 4118struct nk_buffer_marker { 4119 int active; 4120 nk_size offset; 4121}; 4122 4123struct nk_memory {void *ptr;nk_size size;}; 4124struct nk_buffer { 4125 struct nk_buffer_marker marker[NK_BUFFER_MAX]; 4126 /* buffer marker to free a buffer to a certain offset */ 4127 struct nk_allocator pool; 4128 /* allocator callback for dynamic buffers */ 4129 enum nk_allocation_type type; 4130 /* memory management type */ 4131 struct nk_memory memory; 4132 /* memory and size of the current memory block */ 4133 float grow_factor; 4134 /* growing factor for dynamic memory management */ 4135 nk_size allocated; 4136 /* total amount of memory allocated */ 4137 nk_size needed; 4138 /* totally consumed memory given that enough memory is present */ 4139 nk_size calls; 4140 /* number of allocation calls */ 4141 nk_size size; 4142 /* current size of the buffer */ 4143}; 4144 4145#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4146NK_API void nk_buffer_init_default(struct nk_buffer*); 4147#endif 4148NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size); 4149NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size); 4150NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*); 4151NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align); 4152NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type); 4153NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type); 4154NK_API void nk_buffer_clear(struct nk_buffer*); 4155NK_API void nk_buffer_free(struct nk_buffer*); 4156NK_API void *nk_buffer_memory(struct nk_buffer*); 4157NK_API const void *nk_buffer_memory_const(const struct nk_buffer*); 4158NK_API nk_size nk_buffer_total(struct nk_buffer*); 4159 4160/* ============================================================== 4161 * 4162 * STRING 4163 * 4164 * ===============================================================*/ 4165/* Basic string buffer which is only used in context with the text editor 4166 * to manage and manipulate dynamic or fixed size string content. This is _NOT_ 4167 * the default string handling method. The only instance you should have any contact 4168 * with this API is if you interact with an `nk_text_edit` object inside one of the 4169 * copy and paste functions and even there only for more advanced cases. */ 4170struct nk_str { 4171 struct nk_buffer buffer; 4172 int len; /* in codepoints/runes/glyphs */ 4173}; 4174 4175#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4176NK_API void nk_str_init_default(struct nk_str*); 4177#endif 4178NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size); 4179NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size); 4180NK_API void nk_str_clear(struct nk_str*); 4181NK_API void nk_str_free(struct nk_str*); 4182 4183NK_API int nk_str_append_text_char(struct nk_str*, const char*, int); 4184NK_API int nk_str_append_str_char(struct nk_str*, const char*); 4185NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int); 4186NK_API int nk_str_append_str_utf8(struct nk_str*, const char*); 4187NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int); 4188NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*); 4189 4190NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int); 4191NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int); 4192 4193NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int); 4194NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*); 4195NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int); 4196NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*); 4197NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int); 4198NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*); 4199 4200NK_API void nk_str_remove_chars(struct nk_str*, int len); 4201NK_API void nk_str_remove_runes(struct nk_str *str, int len); 4202NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len); 4203NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len); 4204 4205NK_API char *nk_str_at_char(struct nk_str*, int pos); 4206NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len); 4207NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos); 4208NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos); 4209NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len); 4210 4211NK_API char *nk_str_get(struct nk_str*); 4212NK_API const char *nk_str_get_const(const struct nk_str*); 4213NK_API int nk_str_len(struct nk_str*); 4214NK_API int nk_str_len_char(struct nk_str*); 4215 4216/*=============================================================== 4217 * 4218 * TEXT EDITOR 4219 * 4220 * ===============================================================*/ 4221/* Editing text in this library is handled by either `nk_edit_string` or 4222 * `nk_edit_buffer`. But like almost everything in this library there are multiple 4223 * ways of doing it and a balance between control and ease of use with memory 4224 * as well as functionality controlled by flags. 4225 * 4226 * This library generally allows three different levels of memory control: 4227 * First of is the most basic way of just providing a simple char array with 4228 * string length. This method is probably the easiest way of handling simple 4229 * user text input. Main upside is complete control over memory while the biggest 4230 * downside in comparison with the other two approaches is missing undo/redo. 4231 * 4232 * For UIs that require undo/redo the second way was created. It is based on 4233 * a fixed size nk_text_edit struct, which has an internal undo/redo stack. 4234 * This is mainly useful if you want something more like a text editor but don't want 4235 * to have a dynamically growing buffer. 4236 * 4237 * The final way is using a dynamically growing nk_text_edit struct, which 4238 * has both a default version if you don't care where memory comes from and an 4239 * allocator version if you do. While the text editor is quite powerful for its 4240 * complexity I would not recommend editing gigabytes of data with it. 4241 * It is rather designed for uses cases which make sense for a GUI library not for 4242 * an full blown text editor. 4243 */ 4244#ifndef NK_TEXTEDIT_UNDOSTATECOUNT 4245#define NK_TEXTEDIT_UNDOSTATECOUNT 99 4246#endif 4247 4248#ifndef NK_TEXTEDIT_UNDOCHARCOUNT 4249#define NK_TEXTEDIT_UNDOCHARCOUNT 999 4250#endif 4251 4252struct nk_text_edit; 4253struct nk_clipboard { 4254 nk_handle userdata; 4255 nk_plugin_paste paste; 4256 nk_plugin_copy copy; 4257}; 4258 4259struct nk_text_undo_record { 4260 int where; 4261 short insert_length; 4262 short delete_length; 4263 short char_storage; 4264}; 4265 4266struct nk_text_undo_state { 4267 struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]; 4268 nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]; 4269 short undo_point; 4270 short redo_point; 4271 short undo_char_point; 4272 short redo_char_point; 4273}; 4274 4275enum nk_text_edit_type { 4276 NK_TEXT_EDIT_SINGLE_LINE, 4277 NK_TEXT_EDIT_MULTI_LINE 4278}; 4279 4280enum nk_text_edit_mode { 4281 NK_TEXT_EDIT_MODE_VIEW, 4282 NK_TEXT_EDIT_MODE_INSERT, 4283 NK_TEXT_EDIT_MODE_REPLACE 4284}; 4285 4286struct nk_text_edit { 4287 struct nk_clipboard clip; 4288 struct nk_str string; 4289 nk_plugin_filter filter; 4290 struct nk_vec2 scrollbar; 4291 4292 int cursor; 4293 int select_start; 4294 int select_end; 4295 unsigned char mode; 4296 unsigned char cursor_at_end_of_line; 4297 unsigned char initialized; 4298 unsigned char has_preferred_x; 4299 unsigned char single_line; 4300 unsigned char active; 4301 unsigned char padding1; 4302 float preferred_x; 4303 struct nk_text_undo_state undo; 4304}; 4305 4306/* filter function */ 4307NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode); 4308NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode); 4309NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode); 4310NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode); 4311NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode); 4312NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode); 4313NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode); 4314 4315/* text editor */ 4316#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4317NK_API void nk_textedit_init_default(struct nk_text_edit*); 4318#endif 4319NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size); 4320NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size); 4321NK_API void nk_textedit_free(struct nk_text_edit*); 4322NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len); 4323NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len); 4324NK_API void nk_textedit_delete_selection(struct nk_text_edit*); 4325NK_API void nk_textedit_select_all(struct nk_text_edit*); 4326NK_API int nk_textedit_cut(struct nk_text_edit*); 4327NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len); 4328NK_API void nk_textedit_undo(struct nk_text_edit*); 4329NK_API void nk_textedit_redo(struct nk_text_edit*); 4330 4331/* =============================================================== 4332 * 4333 * DRAWING 4334 * 4335 * ===============================================================*/ 4336/* This library was designed to be render backend agnostic so it does 4337 not draw anything to screen. Instead all drawn shapes, widgets 4338 are made of, are buffered into memory and make up a command queue. 4339 Each frame therefore fills the command buffer with draw commands 4340 that then need to be executed by the user and his own render backend. 4341 After that the command buffer needs to be cleared and a new frame can be 4342 started. It is probably important to note that the command buffer is the main 4343 drawing API and the optional vertex buffer API only takes this format and 4344 converts it into a hardware accessible format. 4345 4346 To use the command queue to draw your own widgets you can access the 4347 command buffer of each window by calling `nk_window_get_canvas` after 4348 previously having called `nk_begin`: 4349 4350 void draw_red_rectangle_widget(struct nk_context *ctx) 4351 { 4352 struct nk_command_buffer *canvas; 4353 struct nk_input *input = &ctx->input; 4354 canvas = nk_window_get_canvas(ctx); 4355 4356 struct nk_rect space; 4357 enum nk_widget_layout_states state; 4358 state = nk_widget(&space, ctx); 4359 if (!state) return; 4360 4361 if (state != NK_WIDGET_ROM) 4362 update_your_widget_by_user_input(...); 4363 nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0)); 4364 } 4365 4366 if (nk_begin(...)) { 4367 nk_layout_row_dynamic(ctx, 25, 1); 4368 draw_red_rectangle_widget(ctx); 4369 } 4370 nk_end(..) 4371 4372 Important to know if you want to create your own widgets is the `nk_widget` 4373 call. It allocates space on the panel reserved for this widget to be used, 4374 but also returns the state of the widget space. If your widget is not seen and does 4375 not have to be updated it is '0' and you can just return. If it only has 4376 to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both 4377 update and draw your widget. The reason for separating is to only draw and 4378 update what is actually necessary which is crucial for performance. 4379*/ 4380enum nk_command_type { 4381 NK_COMMAND_NOP, 4382 NK_COMMAND_SCISSOR, 4383 NK_COMMAND_LINE, 4384 NK_COMMAND_CURVE, 4385 NK_COMMAND_RECT, 4386 NK_COMMAND_RECT_FILLED, 4387 NK_COMMAND_RECT_MULTI_COLOR, 4388 NK_COMMAND_CIRCLE, 4389 NK_COMMAND_CIRCLE_FILLED, 4390 NK_COMMAND_ARC, 4391 NK_COMMAND_ARC_FILLED, 4392 NK_COMMAND_TRIANGLE, 4393 NK_COMMAND_TRIANGLE_FILLED, 4394 NK_COMMAND_POLYGON, 4395 NK_COMMAND_POLYGON_FILLED, 4396 NK_COMMAND_POLYLINE, 4397 NK_COMMAND_TEXT, 4398 NK_COMMAND_IMAGE, 4399 NK_COMMAND_CUSTOM 4400}; 4401 4402/* command base and header of every command inside the buffer */ 4403struct nk_command { 4404 enum nk_command_type type; 4405 nk_size next; 4406#ifdef NK_INCLUDE_COMMAND_USERDATA 4407 nk_handle userdata; 4408#endif 4409}; 4410 4411struct nk_command_scissor { 4412 struct nk_command header; 4413 short x, y; 4414 unsigned short w, h; 4415}; 4416 4417struct nk_command_line { 4418 struct nk_command header; 4419 unsigned short line_thickness; 4420 struct nk_vec2i begin; 4421 struct nk_vec2i end; 4422 struct nk_color color; 4423}; 4424 4425struct nk_command_curve { 4426 struct nk_command header; 4427 unsigned short line_thickness; 4428 struct nk_vec2i begin; 4429 struct nk_vec2i end; 4430 struct nk_vec2i ctrl[2]; 4431 struct nk_color color; 4432}; 4433 4434struct nk_command_rect { 4435 struct nk_command header; 4436 unsigned short rounding; 4437 unsigned short line_thickness; 4438 short x, y; 4439 unsigned short w, h; 4440 struct nk_color color; 4441}; 4442 4443struct nk_command_rect_filled { 4444 struct nk_command header; 4445 unsigned short rounding; 4446 short x, y; 4447 unsigned short w, h; 4448 struct nk_color color; 4449}; 4450 4451struct nk_command_rect_multi_color { 4452 struct nk_command header; 4453 short x, y; 4454 unsigned short w, h; 4455 struct nk_color left; 4456 struct nk_color top; 4457 struct nk_color bottom; 4458 struct nk_color right; 4459}; 4460 4461struct nk_command_triangle { 4462 struct nk_command header; 4463 unsigned short line_thickness; 4464 struct nk_vec2i a; 4465 struct nk_vec2i b; 4466 struct nk_vec2i c; 4467 struct nk_color color; 4468}; 4469 4470struct nk_command_triangle_filled { 4471 struct nk_command header; 4472 struct nk_vec2i a; 4473 struct nk_vec2i b; 4474 struct nk_vec2i c; 4475 struct nk_color color; 4476}; 4477 4478struct nk_command_circle { 4479 struct nk_command header; 4480 short x, y; 4481 unsigned short line_thickness; 4482 unsigned short w, h; 4483 struct nk_color color; 4484}; 4485 4486struct nk_command_circle_filled { 4487 struct nk_command header; 4488 short x, y; 4489 unsigned short w, h; 4490 struct nk_color color; 4491}; 4492 4493struct nk_command_arc { 4494 struct nk_command header; 4495 short cx, cy; 4496 unsigned short r; 4497 unsigned short line_thickness; 4498 float a[2]; 4499 struct nk_color color; 4500}; 4501 4502struct nk_command_arc_filled { 4503 struct nk_command header; 4504 short cx, cy; 4505 unsigned short r; 4506 float a[2]; 4507 struct nk_color color; 4508}; 4509 4510struct nk_command_polygon { 4511 struct nk_command header; 4512 struct nk_color color; 4513 unsigned short line_thickness; 4514 unsigned short point_count; 4515 struct nk_vec2i points[1]; 4516}; 4517 4518struct nk_command_polygon_filled { 4519 struct nk_command header; 4520 struct nk_color color; 4521 unsigned short point_count; 4522 struct nk_vec2i points[1]; 4523}; 4524 4525struct nk_command_polyline { 4526 struct nk_command header; 4527 struct nk_color color; 4528 unsigned short line_thickness; 4529 unsigned short point_count; 4530 struct nk_vec2i points[1]; 4531}; 4532 4533struct nk_command_image { 4534 struct nk_command header; 4535 short x, y; 4536 unsigned short w, h; 4537 struct nk_image img; 4538 struct nk_color col; 4539}; 4540 4541typedef void (*nk_command_custom_callback)(void *canvas, short x,short y, 4542 unsigned short w, unsigned short h, nk_handle callback_data); 4543struct nk_command_custom { 4544 struct nk_command header; 4545 short x, y; 4546 unsigned short w, h; 4547 nk_handle callback_data; 4548 nk_command_custom_callback callback; 4549}; 4550 4551struct nk_command_text { 4552 struct nk_command header; 4553 const struct nk_user_font *font; 4554 struct nk_color background; 4555 struct nk_color foreground; 4556 short x, y; 4557 unsigned short w, h; 4558 float height; 4559 int length; 4560 char string[1]; 4561}; 4562 4563enum nk_command_clipping { 4564 NK_CLIPPING_OFF = nk_false, 4565 NK_CLIPPING_ON = nk_true 4566}; 4567 4568struct nk_command_buffer { 4569 struct nk_buffer *base; 4570 struct nk_rect clip; 4571 int use_clipping; 4572 nk_handle userdata; 4573 nk_size begin, end, last; 4574}; 4575 4576/* shape outlines */ 4577NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color); 4578NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color); 4579NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color); 4580NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color); 4581NK_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); 4582NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color); 4583NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col); 4584NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color); 4585 4586/* filled shades */ 4587NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color); 4588NK_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); 4589NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color); 4590NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color); 4591NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color); 4592NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color); 4593 4594/* misc */ 4595NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color); 4596NK_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); 4597NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect); 4598NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr); 4599 4600/* =============================================================== 4601 * 4602 * INPUT 4603 * 4604 * ===============================================================*/ 4605struct nk_mouse_button { 4606 int down; 4607 unsigned int clicked; 4608 struct nk_vec2 clicked_pos; 4609}; 4610struct nk_mouse { 4611 struct nk_mouse_button buttons[NK_BUTTON_MAX]; 4612 struct nk_vec2 pos; 4613 struct nk_vec2 prev; 4614 struct nk_vec2 delta; 4615 struct nk_vec2 scroll_delta; 4616 unsigned char grab; 4617 unsigned char grabbed; 4618 unsigned char ungrab; 4619}; 4620 4621struct nk_key { 4622 int down; 4623 unsigned int clicked; 4624}; 4625struct nk_keyboard { 4626 struct nk_key keys[NK_KEY_MAX]; 4627 char text[NK_INPUT_MAX]; 4628 int text_len; 4629}; 4630 4631struct nk_input { 4632 struct nk_keyboard keyboard; 4633 struct nk_mouse mouse; 4634}; 4635 4636NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons); 4637NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4638NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down); 4639NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4640NK_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); 4641NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect); 4642NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect); 4643NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect); 4644NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect); 4645NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons); 4646NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons); 4647NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons); 4648NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys); 4649NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys); 4650NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys); 4651 4652/* =============================================================== 4653 * 4654 * DRAW LIST 4655 * 4656 * ===============================================================*/ 4657#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 4658/* The optional vertex buffer draw list provides a 2D drawing context 4659 with antialiasing functionality which takes basic filled or outlined shapes 4660 or a path and outputs vertexes, elements and draw commands. 4661 The actual draw list API is not required to be used directly while using this 4662 library since converting the default library draw command output is done by 4663 just calling `nk_convert` but I decided to still make this library accessible 4664 since it can be useful. 4665 4666 The draw list is based on a path buffering and polygon and polyline 4667 rendering API which allows a lot of ways to draw 2D content to screen. 4668 In fact it is probably more powerful than needed but allows even more crazy 4669 things than this library provides by default. 4670*/ 4671#ifdef NK_UINT_DRAW_INDEX 4672typedef nk_uint nk_draw_index; 4673#else 4674typedef nk_ushort nk_draw_index; 4675#endif 4676enum nk_draw_list_stroke { 4677 NK_STROKE_OPEN = nk_false, 4678 /* build up path has no connection back to the beginning */ 4679 NK_STROKE_CLOSED = nk_true 4680 /* build up path has a connection back to the beginning */ 4681}; 4682 4683enum nk_draw_vertex_layout_attribute { 4684 NK_VERTEX_POSITION, 4685 NK_VERTEX_COLOR, 4686 NK_VERTEX_TEXCOORD, 4687 NK_VERTEX_ATTRIBUTE_COUNT 4688}; 4689 4690enum nk_draw_vertex_layout_format { 4691 NK_FORMAT_SCHAR, 4692 NK_FORMAT_SSHORT, 4693 NK_FORMAT_SINT, 4694 NK_FORMAT_UCHAR, 4695 NK_FORMAT_USHORT, 4696 NK_FORMAT_UINT, 4697 NK_FORMAT_FLOAT, 4698 NK_FORMAT_DOUBLE, 4699 4700NK_FORMAT_COLOR_BEGIN, 4701 NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN, 4702 NK_FORMAT_R16G15B16, 4703 NK_FORMAT_R32G32B32, 4704 4705 NK_FORMAT_R8G8B8A8, 4706 NK_FORMAT_B8G8R8A8, 4707 NK_FORMAT_R16G15B16A16, 4708 NK_FORMAT_R32G32B32A32, 4709 NK_FORMAT_R32G32B32A32_FLOAT, 4710 NK_FORMAT_R32G32B32A32_DOUBLE, 4711 4712 NK_FORMAT_RGB32, 4713 NK_FORMAT_RGBA32, 4714NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32, 4715 NK_FORMAT_COUNT 4716}; 4717 4718#define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0 4719struct nk_draw_vertex_layout_element { 4720 enum nk_draw_vertex_layout_attribute attribute; 4721 enum nk_draw_vertex_layout_format format; 4722 nk_size offset; 4723}; 4724 4725struct nk_draw_command { 4726 unsigned int elem_count; 4727 /* number of elements in the current draw batch */ 4728 struct nk_rect clip_rect; 4729 /* current screen clipping rectangle */ 4730 nk_handle texture; 4731 /* current texture to set */ 4732#ifdef NK_INCLUDE_COMMAND_USERDATA 4733 nk_handle userdata; 4734#endif 4735}; 4736 4737struct nk_draw_list { 4738 struct nk_rect clip_rect; 4739 struct nk_vec2 circle_vtx[12]; 4740 struct nk_convert_config config; 4741 4742 struct nk_buffer *buffer; 4743 struct nk_buffer *vertices; 4744 struct nk_buffer *elements; 4745 4746 unsigned int element_count; 4747 unsigned int vertex_count; 4748 unsigned int cmd_count; 4749 nk_size cmd_offset; 4750 4751 unsigned int path_count; 4752 unsigned int path_offset; 4753 4754 enum nk_anti_aliasing line_AA; 4755 enum nk_anti_aliasing shape_AA; 4756 4757#ifdef NK_INCLUDE_COMMAND_USERDATA 4758 nk_handle userdata; 4759#endif 4760}; 4761 4762/* draw list */ 4763NK_API void nk_draw_list_init(struct nk_draw_list*); 4764NK_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); 4765 4766/* drawing */ 4767#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)) 4768NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*); 4769NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*); 4770NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*); 4771 4772/* path */ 4773NK_API void nk_draw_list_path_clear(struct nk_draw_list*); 4774NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos); 4775NK_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); 4776NK_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); 4777NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding); 4778NK_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); 4779NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color); 4780NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness); 4781 4782/* stroke */ 4783NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness); 4784NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness); 4785NK_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); 4786NK_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); 4787NK_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); 4788NK_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); 4789 4790/* fill */ 4791NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding); 4792NK_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); 4793NK_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); 4794NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs); 4795NK_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); 4796 4797/* misc */ 4798NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color); 4799NK_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); 4800#ifdef NK_INCLUDE_COMMAND_USERDATA 4801NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata); 4802#endif 4803 4804#endif 4805 4806/* =============================================================== 4807 * 4808 * GUI 4809 * 4810 * ===============================================================*/ 4811enum nk_style_item_type { 4812 NK_STYLE_ITEM_COLOR, 4813 NK_STYLE_ITEM_IMAGE 4814}; 4815 4816union nk_style_item_data { 4817 struct nk_image image; 4818 struct nk_color color; 4819}; 4820 4821struct nk_style_item { 4822 enum nk_style_item_type type; 4823 union nk_style_item_data data; 4824}; 4825 4826struct nk_style_text { 4827 struct nk_color color; 4828 struct nk_vec2 padding; 4829}; 4830 4831struct nk_style_button { 4832 /* background */ 4833 struct nk_style_item normal; 4834 struct nk_style_item hover; 4835 struct nk_style_item active; 4836 struct nk_color border_color; 4837 4838 /* text */ 4839 struct nk_color text_background; 4840 struct nk_color text_normal; 4841 struct nk_color text_hover; 4842 struct nk_color text_active; 4843 nk_flags text_alignment; 4844 4845 /* properties */ 4846 float border; 4847 float rounding; 4848 struct nk_vec2 padding; 4849 struct nk_vec2 image_padding; 4850 struct nk_vec2 touch_padding; 4851 4852 /* optional user callbacks */ 4853 nk_handle userdata; 4854 void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata); 4855 void(*draw_end)(struct nk_command_buffer*, nk_handle userdata); 4856}; 4857 4858struct nk_style_toggle { 4859 /* background */ 4860 struct nk_style_item normal; 4861 struct nk_style_item hover; 4862 struct nk_style_item active; 4863 struct nk_color border_color; 4864 4865 /* cursor */ 4866 struct nk_style_item cursor_normal; 4867 struct nk_style_item cursor_hover; 4868 4869 /* text */ 4870 struct nk_color text_normal; 4871 struct nk_color text_hover; 4872 struct nk_color text_active; 4873 struct nk_color text_background; 4874 nk_flags text_alignment; 4875 4876 /* properties */ 4877 struct nk_vec2 padding; 4878 struct nk_vec2 touch_padding; 4879 float spacing; 4880 float border; 4881 4882 /* optional user callbacks */ 4883 nk_handle userdata; 4884 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4885 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4886}; 4887 4888struct nk_style_selectable { 4889 /* background (inactive) */ 4890 struct nk_style_item normal; 4891 struct nk_style_item hover; 4892 struct nk_style_item pressed; 4893 4894 /* background (active) */ 4895 struct nk_style_item normal_active; 4896 struct nk_style_item hover_active; 4897 struct nk_style_item pressed_active; 4898 4899 /* text color (inactive) */ 4900 struct nk_color text_normal; 4901 struct nk_color text_hover; 4902 struct nk_color text_pressed; 4903 4904 /* text color (active) */ 4905 struct nk_color text_normal_active; 4906 struct nk_color text_hover_active; 4907 struct nk_color text_pressed_active; 4908 struct nk_color text_background; 4909 nk_flags text_alignment; 4910 4911 /* properties */ 4912 float rounding; 4913 struct nk_vec2 padding; 4914 struct nk_vec2 touch_padding; 4915 struct nk_vec2 image_padding; 4916 4917 /* optional user callbacks */ 4918 nk_handle userdata; 4919 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4920 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4921}; 4922 4923struct nk_style_slider { 4924 /* background */ 4925 struct nk_style_item normal; 4926 struct nk_style_item hover; 4927 struct nk_style_item active; 4928 struct nk_color border_color; 4929 4930 /* background bar */ 4931 struct nk_color bar_normal; 4932 struct nk_color bar_hover; 4933 struct nk_color bar_active; 4934 struct nk_color bar_filled; 4935 4936 /* cursor */ 4937 struct nk_style_item cursor_normal; 4938 struct nk_style_item cursor_hover; 4939 struct nk_style_item cursor_active; 4940 4941 /* properties */ 4942 float border; 4943 float rounding; 4944 float bar_height; 4945 struct nk_vec2 padding; 4946 struct nk_vec2 spacing; 4947 struct nk_vec2 cursor_size; 4948 4949 /* optional buttons */ 4950 int show_buttons; 4951 struct nk_style_button inc_button; 4952 struct nk_style_button dec_button; 4953 enum nk_symbol_type inc_symbol; 4954 enum nk_symbol_type dec_symbol; 4955 4956 /* optional user callbacks */ 4957 nk_handle userdata; 4958 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4959 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4960}; 4961 4962struct nk_style_progress { 4963 /* background */ 4964 struct nk_style_item normal; 4965 struct nk_style_item hover; 4966 struct nk_style_item active; 4967 struct nk_color border_color; 4968 4969 /* cursor */ 4970 struct nk_style_item cursor_normal; 4971 struct nk_style_item cursor_hover; 4972 struct nk_style_item cursor_active; 4973 struct nk_color cursor_border_color; 4974 4975 /* properties */ 4976 float rounding; 4977 float border; 4978 float cursor_border; 4979 float cursor_rounding; 4980 struct nk_vec2 padding; 4981 4982 /* optional user callbacks */ 4983 nk_handle userdata; 4984 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4985 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4986}; 4987 4988struct nk_style_scrollbar { 4989 /* background */ 4990 struct nk_style_item normal; 4991 struct nk_style_item hover; 4992 struct nk_style_item active; 4993 struct nk_color border_color; 4994 4995 /* cursor */ 4996 struct nk_style_item cursor_normal; 4997 struct nk_style_item cursor_hover; 4998 struct nk_style_item cursor_active; 4999 struct nk_color cursor_border_color; 5000 5001 /* properties */ 5002 float border; 5003 float rounding; 5004 float border_cursor; 5005 float rounding_cursor; 5006 struct nk_vec2 padding; 5007 5008 /* optional buttons */ 5009 int show_buttons; 5010 struct nk_style_button inc_button; 5011 struct nk_style_button dec_button; 5012 enum nk_symbol_type inc_symbol; 5013 enum nk_symbol_type dec_symbol; 5014 5015 /* optional user callbacks */ 5016 nk_handle userdata; 5017 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5018 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5019}; 5020 5021struct nk_style_edit { 5022 /* background */ 5023 struct nk_style_item normal; 5024 struct nk_style_item hover; 5025 struct nk_style_item active; 5026 struct nk_color border_color; 5027 struct nk_style_scrollbar scrollbar; 5028 5029 /* cursor */ 5030 struct nk_color cursor_normal; 5031 struct nk_color cursor_hover; 5032 struct nk_color cursor_text_normal; 5033 struct nk_color cursor_text_hover; 5034 5035 /* text (unselected) */ 5036 struct nk_color text_normal; 5037 struct nk_color text_hover; 5038 struct nk_color text_active; 5039 5040 /* text (selected) */ 5041 struct nk_color selected_normal; 5042 struct nk_color selected_hover; 5043 struct nk_color selected_text_normal; 5044 struct nk_color selected_text_hover; 5045 5046 /* properties */ 5047 float border; 5048 float rounding; 5049 float cursor_size; 5050 struct nk_vec2 scrollbar_size; 5051 struct nk_vec2 padding; 5052 float row_padding; 5053}; 5054 5055struct nk_style_property { 5056 /* background */ 5057 struct nk_style_item normal; 5058 struct nk_style_item hover; 5059 struct nk_style_item active; 5060 struct nk_color border_color; 5061 5062 /* text */ 5063 struct nk_color label_normal; 5064 struct nk_color label_hover; 5065 struct nk_color label_active; 5066 5067 /* symbols */ 5068 enum nk_symbol_type sym_left; 5069 enum nk_symbol_type sym_right; 5070 5071 /* properties */ 5072 float border; 5073 float rounding; 5074 struct nk_vec2 padding; 5075 5076 struct nk_style_edit edit; 5077 struct nk_style_button inc_button; 5078 struct nk_style_button dec_button; 5079 5080 /* optional user callbacks */ 5081 nk_handle userdata; 5082 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5083 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5084}; 5085 5086struct nk_style_chart { 5087 /* colors */ 5088 struct nk_style_item background; 5089 struct nk_color border_color; 5090 struct nk_color selected_color; 5091 struct nk_color color; 5092 5093 /* properties */ 5094 float border; 5095 float rounding; 5096 struct nk_vec2 padding; 5097}; 5098 5099struct nk_style_combo { 5100 /* background */ 5101 struct nk_style_item normal; 5102 struct nk_style_item hover; 5103 struct nk_style_item active; 5104 struct nk_color border_color; 5105 5106 /* label */ 5107 struct nk_color label_normal; 5108 struct nk_color label_hover; 5109 struct nk_color label_active; 5110 5111 /* symbol */ 5112 struct nk_color symbol_normal; 5113 struct nk_color symbol_hover; 5114 struct nk_color symbol_active; 5115 5116 /* button */ 5117 struct nk_style_button button; 5118 enum nk_symbol_type sym_normal; 5119 enum nk_symbol_type sym_hover; 5120 enum nk_symbol_type sym_active; 5121 5122 /* properties */ 5123 float border; 5124 float rounding; 5125 struct nk_vec2 content_padding; 5126 struct nk_vec2 button_padding; 5127 struct nk_vec2 spacing; 5128}; 5129 5130struct nk_style_tab { 5131 /* background */ 5132 struct nk_style_item background; 5133 struct nk_color border_color; 5134 struct nk_color text; 5135 5136 /* button */ 5137 struct nk_style_button tab_maximize_button; 5138 struct nk_style_button tab_minimize_button; 5139 struct nk_style_button node_maximize_button; 5140 struct nk_style_button node_minimize_button; 5141 enum nk_symbol_type sym_minimize; 5142 enum nk_symbol_type sym_maximize; 5143 5144 /* properties */ 5145 float border; 5146 float rounding; 5147 float indent; 5148 struct nk_vec2 padding; 5149 struct nk_vec2 spacing; 5150}; 5151 5152enum nk_style_header_align { 5153 NK_HEADER_LEFT, 5154 NK_HEADER_RIGHT 5155}; 5156struct nk_style_window_header { 5157 /* background */ 5158 struct nk_style_item normal; 5159 struct nk_style_item hover; 5160 struct nk_style_item active; 5161 5162 /* button */ 5163 struct nk_style_button close_button; 5164 struct nk_style_button minimize_button; 5165 enum nk_symbol_type close_symbol; 5166 enum nk_symbol_type minimize_symbol; 5167 enum nk_symbol_type maximize_symbol; 5168 5169 /* title */ 5170 struct nk_color label_normal; 5171 struct nk_color label_hover; 5172 struct nk_color label_active; 5173 5174 /* properties */ 5175 enum nk_style_header_align align; 5176 struct nk_vec2 padding; 5177 struct nk_vec2 label_padding; 5178 struct nk_vec2 spacing; 5179}; 5180 5181struct nk_style_window { 5182 struct nk_style_window_header header; 5183 struct nk_style_item fixed_background; 5184 struct nk_color background; 5185 5186 struct nk_color border_color; 5187 struct nk_color popup_border_color; 5188 struct nk_color combo_border_color; 5189 struct nk_color contextual_border_color; 5190 struct nk_color menu_border_color; 5191 struct nk_color group_border_color; 5192 struct nk_color tooltip_border_color; 5193 struct nk_style_item scaler; 5194 5195 float border; 5196 float combo_border; 5197 float contextual_border; 5198 float menu_border; 5199 float group_border; 5200 float tooltip_border; 5201 float popup_border; 5202 float min_row_height_padding; 5203 5204 float rounding; 5205 struct nk_vec2 spacing; 5206 struct nk_vec2 scrollbar_size; 5207 struct nk_vec2 min_size; 5208 5209 struct nk_vec2 padding; 5210 struct nk_vec2 group_padding; 5211 struct nk_vec2 popup_padding; 5212 struct nk_vec2 combo_padding; 5213 struct nk_vec2 contextual_padding; 5214 struct nk_vec2 menu_padding; 5215 struct nk_vec2 tooltip_padding; 5216}; 5217 5218struct nk_style { 5219 const struct nk_user_font *font; 5220 const struct nk_cursor *cursors[NK_CURSOR_COUNT]; 5221 const struct nk_cursor *cursor_active; 5222 struct nk_cursor *cursor_last; 5223 int cursor_visible; 5224 5225 struct nk_style_text text; 5226 struct nk_style_button button; 5227 struct nk_style_button contextual_button; 5228 struct nk_style_button menu_button; 5229 struct nk_style_toggle option; 5230 struct nk_style_toggle checkbox; 5231 struct nk_style_selectable selectable; 5232 struct nk_style_slider slider; 5233 struct nk_style_progress progress; 5234 struct nk_style_property property; 5235 struct nk_style_edit edit; 5236 struct nk_style_chart chart; 5237 struct nk_style_scrollbar scrollh; 5238 struct nk_style_scrollbar scrollv; 5239 struct nk_style_tab tab; 5240 struct nk_style_combo combo; 5241 struct nk_style_window window; 5242}; 5243 5244NK_API struct nk_style_item nk_style_item_image(struct nk_image img); 5245NK_API struct nk_style_item nk_style_item_color(struct nk_color); 5246NK_API struct nk_style_item nk_style_item_hide(void); 5247 5248/*============================================================== 5249 * PANEL 5250 * =============================================================*/ 5251#ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 5252#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16 5253#endif 5254#ifndef NK_CHART_MAX_SLOT 5255#define NK_CHART_MAX_SLOT 4 5256#endif 5257 5258enum nk_panel_type { 5259 NK_PANEL_NONE = 0, 5260 NK_PANEL_WINDOW = NK_FLAG(0), 5261 NK_PANEL_GROUP = NK_FLAG(1), 5262 NK_PANEL_POPUP = NK_FLAG(2), 5263 NK_PANEL_CONTEXTUAL = NK_FLAG(4), 5264 NK_PANEL_COMBO = NK_FLAG(5), 5265 NK_PANEL_MENU = NK_FLAG(6), 5266 NK_PANEL_TOOLTIP = NK_FLAG(7) 5267}; 5268enum nk_panel_set { 5269 NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP, 5270 NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP, 5271 NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP 5272}; 5273 5274struct nk_chart_slot { 5275 enum nk_chart_type type; 5276 struct nk_color color; 5277 struct nk_color highlight; 5278 float min, max, range; 5279 int count; 5280 struct nk_vec2 last; 5281 int index; 5282}; 5283 5284struct nk_chart { 5285 int slot; 5286 float x, y, w, h; 5287 struct nk_chart_slot slots[NK_CHART_MAX_SLOT]; 5288}; 5289 5290enum nk_panel_row_layout_type { 5291 NK_LAYOUT_DYNAMIC_FIXED = 0, 5292 NK_LAYOUT_DYNAMIC_ROW, 5293 NK_LAYOUT_DYNAMIC_FREE, 5294 NK_LAYOUT_DYNAMIC, 5295 NK_LAYOUT_STATIC_FIXED, 5296 NK_LAYOUT_STATIC_ROW, 5297 NK_LAYOUT_STATIC_FREE, 5298 NK_LAYOUT_STATIC, 5299 NK_LAYOUT_TEMPLATE, 5300 NK_LAYOUT_COUNT 5301}; 5302struct nk_row_layout { 5303 enum nk_panel_row_layout_type type; 5304 int index; 5305 float height; 5306 float min_height; 5307 int columns; 5308 const float *ratio; 5309 float item_width; 5310 float item_height; 5311 float item_offset; 5312 float filled; 5313 struct nk_rect item; 5314 int tree_depth; 5315 float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]; 5316}; 5317 5318struct nk_popup_buffer { 5319 nk_size begin; 5320 nk_size parent; 5321 nk_size last; 5322 nk_size end; 5323 int active; 5324}; 5325 5326struct nk_menu_state { 5327 float x, y, w, h; 5328 struct nk_scroll offset; 5329}; 5330 5331struct nk_panel { 5332 enum nk_panel_type type; 5333 nk_flags flags; 5334 struct nk_rect bounds; 5335 nk_uint *offset_x; 5336 nk_uint *offset_y; 5337 float at_x, at_y, max_x; 5338 float footer_height; 5339 float header_height; 5340 float border; 5341 unsigned int has_scrolling; 5342 struct nk_rect clip; 5343 struct nk_menu_state menu; 5344 struct nk_row_layout row; 5345 struct nk_chart chart; 5346 struct nk_command_buffer *buffer; 5347 struct nk_panel *parent; 5348}; 5349 5350/*============================================================== 5351 * WINDOW 5352 * =============================================================*/ 5353#ifndef NK_WINDOW_MAX_NAME 5354#define NK_WINDOW_MAX_NAME 64 5355#endif 5356 5357struct nk_table; 5358enum nk_window_flags { 5359 NK_WINDOW_PRIVATE = NK_FLAG(11), 5360 NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE, 5361 /* special window type growing up in height while being filled to a certain maximum height */ 5362 NK_WINDOW_ROM = NK_FLAG(12), 5363 /* sets window widgets into a read only mode and does not allow input changes */ 5364 NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT, 5365 /* prevents all interaction caused by input to either window or widgets inside */ 5366 NK_WINDOW_HIDDEN = NK_FLAG(13), 5367 /* Hides window and stops any window interaction and drawing */ 5368 NK_WINDOW_CLOSED = NK_FLAG(14), 5369 /* Directly closes and frees the window at the end of the frame */ 5370 NK_WINDOW_MINIMIZED = NK_FLAG(15), 5371 /* marks the window as minimized */ 5372 NK_WINDOW_REMOVE_ROM = NK_FLAG(16) 5373 /* Removes read only mode at the end of the window */ 5374}; 5375 5376struct nk_popup_state { 5377 struct nk_window *win; 5378 enum nk_panel_type type; 5379 struct nk_popup_buffer buf; 5380 nk_hash name; 5381 int active; 5382 unsigned combo_count; 5383 unsigned con_count, con_old; 5384 unsigned active_con; 5385 struct nk_rect header; 5386}; 5387 5388struct nk_edit_state { 5389 nk_hash name; 5390 unsigned int seq; 5391 unsigned int old; 5392 int active, prev; 5393 int cursor; 5394 int sel_start; 5395 int sel_end; 5396 struct nk_scroll scrollbar; 5397 unsigned char mode; 5398 unsigned char single_line; 5399}; 5400 5401struct nk_property_state { 5402 int active, prev; 5403 char buffer[NK_MAX_NUMBER_BUFFER]; 5404 int length; 5405 int cursor; 5406 int select_start; 5407 int select_end; 5408 nk_hash name; 5409 unsigned int seq; 5410 unsigned int old; 5411 int state; 5412}; 5413 5414struct nk_window { 5415 unsigned int seq; 5416 nk_hash name; 5417 char name_string[NK_WINDOW_MAX_NAME]; 5418 nk_flags flags; 5419 5420 struct nk_rect bounds; 5421 struct nk_scroll scrollbar; 5422 struct nk_command_buffer buffer; 5423 struct nk_panel *layout; 5424 float scrollbar_hiding_timer; 5425 5426 /* persistent widget state */ 5427 struct nk_property_state property; 5428 struct nk_popup_state popup; 5429 struct nk_edit_state edit; 5430 unsigned int scrolled; 5431 5432 struct nk_table *tables; 5433 unsigned int table_count; 5434 5435 /* window list hooks */ 5436 struct nk_window *next; 5437 struct nk_window *prev; 5438 struct nk_window *parent; 5439}; 5440 5441/*============================================================== 5442 * STACK 5443 * =============================================================*/ 5444/* The style modifier stack can be used to temporarily change a 5445 * property inside `nk_style`. For example if you want a special 5446 * red button you can temporarily push the old button color onto a stack 5447 * draw the button with a red color and then you just pop the old color 5448 * back from the stack: 5449 * 5450 * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0))); 5451 * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0))); 5452 * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0))); 5453 * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2)); 5454 * 5455 * nk_button(...); 5456 * 5457 * nk_style_pop_style_item(ctx); 5458 * nk_style_pop_style_item(ctx); 5459 * nk_style_pop_style_item(ctx); 5460 * nk_style_pop_vec2(ctx); 5461 * 5462 * Nuklear has a stack for style_items, float properties, vector properties, 5463 * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack 5464 * which can be changed at compile time. 5465 */ 5466#ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE 5467#define NK_BUTTON_BEHAVIOR_STACK_SIZE 8 5468#endif 5469 5470#ifndef NK_FONT_STACK_SIZE 5471#define NK_FONT_STACK_SIZE 8 5472#endif 5473 5474#ifndef NK_STYLE_ITEM_STACK_SIZE 5475#define NK_STYLE_ITEM_STACK_SIZE 16 5476#endif 5477 5478#ifndef NK_FLOAT_STACK_SIZE 5479#define NK_FLOAT_STACK_SIZE 32 5480#endif 5481 5482#ifndef NK_VECTOR_STACK_SIZE 5483#define NK_VECTOR_STACK_SIZE 16 5484#endif 5485 5486#ifndef NK_FLAGS_STACK_SIZE 5487#define NK_FLAGS_STACK_SIZE 32 5488#endif 5489 5490#ifndef NK_COLOR_STACK_SIZE 5491#define NK_COLOR_STACK_SIZE 32 5492#endif 5493 5494#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\ 5495 struct nk_config_stack_##name##_element {\ 5496 prefix##_##type *address;\ 5497 prefix##_##type old_value;\ 5498 } 5499#define NK_CONFIG_STACK(type,size)\ 5500 struct nk_config_stack_##type {\ 5501 int head;\ 5502 struct nk_config_stack_##type##_element elements[size];\ 5503 } 5504 5505#define nk_float float 5506NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item); 5507NK_CONFIGURATION_STACK_TYPE(nk ,float, float); 5508NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2); 5509NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags); 5510NK_CONFIGURATION_STACK_TYPE(struct nk, color, color); 5511NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*); 5512NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior); 5513 5514NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE); 5515NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE); 5516NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE); 5517NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE); 5518NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE); 5519NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE); 5520NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE); 5521 5522struct nk_configuration_stacks { 5523 struct nk_config_stack_style_item style_items; 5524 struct nk_config_stack_float floats; 5525 struct nk_config_stack_vec2 vectors; 5526 struct nk_config_stack_flags flags; 5527 struct nk_config_stack_color colors; 5528 struct nk_config_stack_user_font fonts; 5529 struct nk_config_stack_button_behavior button_behaviors; 5530}; 5531 5532/*============================================================== 5533 * CONTEXT 5534 * =============================================================*/ 5535#define NK_VALUE_PAGE_CAPACITY \ 5536 (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2) 5537 5538struct nk_table { 5539 unsigned int seq; 5540 unsigned int size; 5541 nk_hash keys[NK_VALUE_PAGE_CAPACITY]; 5542 nk_uint values[NK_VALUE_PAGE_CAPACITY]; 5543 struct nk_table *next, *prev; 5544}; 5545 5546union nk_page_data { 5547 struct nk_table tbl; 5548 struct nk_panel pan; 5549 struct nk_window win; 5550}; 5551 5552struct nk_page_element { 5553 union nk_page_data data; 5554 struct nk_page_element *next; 5555 struct nk_page_element *prev; 5556}; 5557 5558struct nk_page { 5559 unsigned int size; 5560 struct nk_page *next; 5561 struct nk_page_element win[1]; 5562}; 5563 5564struct nk_pool { 5565 struct nk_allocator alloc; 5566 enum nk_allocation_type type; 5567 unsigned int page_count; 5568 struct nk_page *pages; 5569 struct nk_page_element *freelist; 5570 unsigned capacity; 5571 nk_size size; 5572 nk_size cap; 5573}; 5574 5575struct nk_context { 5576/* public: can be accessed freely */ 5577 struct nk_input input; 5578 struct nk_style style; 5579 struct nk_buffer memory; 5580 struct nk_clipboard clip; 5581 nk_flags last_widget_state; 5582 enum nk_button_behavior button_behavior; 5583 struct nk_configuration_stacks stacks; 5584 float delta_time_seconds; 5585 5586/* private: 5587 should only be accessed if you 5588 know what you are doing */ 5589#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 5590 struct nk_draw_list draw_list; 5591#endif 5592#ifdef NK_INCLUDE_COMMAND_USERDATA 5593 nk_handle userdata; 5594#endif 5595 /* text editor objects are quite big because of an internal 5596 * undo/redo stack. Therefore it does not make sense to have one for 5597 * each window for temporary use cases, so I only provide *one* instance 5598 * for all windows. This works because the content is cleared anyway */ 5599 struct nk_text_edit text_edit; 5600 /* draw buffer used for overlay drawing operation like cursor */ 5601 struct nk_command_buffer overlay; 5602 5603 /* windows */ 5604 int build; 5605 int use_pool; 5606 struct nk_pool pool; 5607 struct nk_window *begin; 5608 struct nk_window *end; 5609 struct nk_window *active; 5610 struct nk_window *current; 5611 struct nk_page_element *freelist; 5612 unsigned int count; 5613 unsigned int seq; 5614}; 5615 5616/* ============================================================== 5617 * MATH 5618 * =============================================================== */ 5619#define NK_PI 3.141592654f 5620#define NK_UTF_INVALID 0xFFFD 5621#define NK_MAX_FLOAT_PRECISION 2 5622 5623#define NK_UNUSED(x) ((void)(x)) 5624#define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x))) 5625#define NK_LEN(a) (sizeof(a)/sizeof(a)[0]) 5626#define NK_ABS(a) (((a) < 0) ? -(a) : (a)) 5627#define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b)) 5628#define NK_INBOX(px, py, x, y, w, h)\ 5629 (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h)) 5630#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \ 5631 (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0))) 5632#define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\ 5633 (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh)) 5634 5635#define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y) 5636#define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y) 5637#define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y) 5638#define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t)) 5639 5640#define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i)))) 5641#define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i)))) 5642#define nk_zero_struct(s) nk_zero(&s, sizeof(s)) 5643 5644/* ============================================================== 5645 * ALIGNMENT 5646 * =============================================================== */ 5647/* Pointer to Integer type conversion for pointer alignment */ 5648#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/ 5649# define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x)) 5650# define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x)) 5651#elif !defined(__GNUC__) /* works for compilers other than LLVM */ 5652# define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x]) 5653# define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0)) 5654#elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */ 5655# define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) 5656# define NK_PTR_TO_UINT(x) ((uintptr_t)(x)) 5657#else /* generates warning but works */ 5658# define NK_UINT_TO_PTR(x) ((void*)(x)) 5659# define NK_PTR_TO_UINT(x) ((nk_size)(x)) 5660#endif 5661 5662#define NK_ALIGN_PTR(x, mask)\ 5663 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1)))) 5664#define NK_ALIGN_PTR_BACK(x, mask)\ 5665 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1)))) 5666 5667#define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) 5668#define NK_CONTAINER_OF(ptr,type,member)\ 5669 (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) 5670 5671#ifdef __cplusplus 5672} 5673#endif 5674 5675#ifdef __cplusplus 5676template<typename T> struct nk_alignof; 5677template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};}; 5678template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};}; 5679template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum { 5680 diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};}; 5681#define NK_ALIGNOF(t) (nk_alignof<t>::value) 5682#elif defined(_MSC_VER) 5683#define NK_ALIGNOF(t) (__alignof(t)) 5684#else 5685#define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) 5686#endif 5687 5688#endif /* NK_NUKLEAR_H_ */ 5689 5690#ifdef NK_IMPLEMENTATION 5691 5692#ifndef NK_INTERNAL_H 5693#define NK_INTERNAL_H 5694 5695#ifndef NK_POOL_DEFAULT_CAPACITY 5696#define NK_POOL_DEFAULT_CAPACITY 16 5697#endif 5698 5699#ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE 5700#define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) 5701#endif 5702 5703#ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE 5704#define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024) 5705#endif 5706 5707/* standard library headers */ 5708#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5709#include <stdlib.h> /* malloc, free */ 5710#endif 5711#ifdef NK_INCLUDE_STANDARD_IO 5712#include <stdio.h> /* fopen, fclose,... */ 5713#endif 5714#ifndef NK_ASSERT 5715#include <assert.h> 5716#define NK_ASSERT(expr) assert(expr) 5717#endif 5718 5719#ifndef NK_MEMSET 5720#define NK_MEMSET nk_memset 5721#endif 5722#ifndef NK_MEMCPY 5723#define NK_MEMCPY nk_memcopy 5724#endif 5725#ifndef NK_SQRT 5726#define NK_SQRT nk_sqrt 5727#endif 5728#ifndef NK_SIN 5729#define NK_SIN nk_sin 5730#endif 5731#ifndef NK_COS 5732#define NK_COS nk_cos 5733#endif 5734#ifndef NK_STRTOD 5735#define NK_STRTOD nk_strtod 5736#endif 5737#ifndef NK_DTOA 5738#define NK_DTOA nk_dtoa 5739#endif 5740 5741#define NK_DEFAULT (-1) 5742 5743#ifndef NK_VSNPRINTF 5744/* If your compiler does support `vsnprintf` I would highly recommend 5745 * defining this to vsnprintf instead since `vsprintf` is basically 5746 * unbelievable unsafe and should *NEVER* be used. But I have to support 5747 * it since C89 only provides this unsafe version. */ 5748 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\ 5749 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 5750 (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\ 5751 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\ 5752 defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE) 5753 #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a) 5754 #else 5755 #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a) 5756 #endif 5757#endif 5758 5759#define NK_SCHAR_MIN (-127) 5760#define NK_SCHAR_MAX 127 5761#define NK_UCHAR_MIN 0 5762#define NK_UCHAR_MAX 256 5763#define NK_SSHORT_MIN (-32767) 5764#define NK_SSHORT_MAX 32767 5765#define NK_USHORT_MIN 0 5766#define NK_USHORT_MAX 65535 5767#define NK_SINT_MIN (-2147483647) 5768#define NK_SINT_MAX 2147483647 5769#define NK_UINT_MIN 0 5770#define NK_UINT_MAX 4294967295u 5771 5772/* Make sure correct type size: 5773 * This will fire with a negative subscript error if the type sizes 5774 * are set incorrectly by the compiler, and compile out if not */ 5775NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 5776NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*)); 5777NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 5778NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 5779NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 5780NK_STATIC_ASSERT(sizeof(nk_short) == 2); 5781NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 5782NK_STATIC_ASSERT(sizeof(nk_int) == 4); 5783NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 5784 5785NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384}; 5786#define NK_FLOAT_PRECISION 0.00000000000001 5787 5788NK_GLOBAL const struct nk_color nk_red = {255,0,0,255}; 5789NK_GLOBAL const struct nk_color nk_green = {0,255,0,255}; 5790NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255}; 5791NK_GLOBAL const struct nk_color nk_white = {255,255,255,255}; 5792NK_GLOBAL const struct nk_color nk_black = {0,0,0,255}; 5793NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255}; 5794 5795/* widget */ 5796#define nk_widget_state_reset(s)\ 5797 if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\ 5798 (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\ 5799 else (*(s)) = NK_WIDGET_STATE_INACTIVE; 5800 5801/* math */ 5802NK_LIB float nk_inv_sqrt(float n); 5803NK_LIB float nk_sqrt(float x); 5804NK_LIB float nk_sin(float x); 5805NK_LIB float nk_cos(float x); 5806NK_LIB nk_uint nk_round_up_pow2(nk_uint v); 5807NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount); 5808NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad); 5809NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1); 5810NK_LIB double nk_pow(double x, int n); 5811NK_LIB int nk_ifloord(double x); 5812NK_LIB int nk_ifloorf(float x); 5813NK_LIB int nk_iceilf(float x); 5814NK_LIB int nk_log10(double n); 5815 5816/* util */ 5817enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE}; 5818NK_LIB int nk_is_lower(int c); 5819NK_LIB int nk_is_upper(int c); 5820NK_LIB int nk_to_upper(int c); 5821NK_LIB int nk_to_lower(int c); 5822NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); 5823NK_LIB void nk_memset(void *ptr, int c0, nk_size size); 5824NK_LIB void nk_zero(void *ptr, nk_size size); 5825NK_LIB char *nk_itoa(char *s, long n); 5826NK_LIB int nk_string_float_limit(char *string, int prec); 5827NK_LIB char *nk_dtoa(char *s, double n); 5828NK_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); 5829NK_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); 5830#ifdef NK_INCLUDE_STANDARD_VARARGS 5831NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args); 5832#endif 5833#ifdef NK_INCLUDE_STANDARD_IO 5834NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc); 5835#endif 5836 5837/* buffer */ 5838#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5839NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size); 5840NK_LIB void nk_mfree(nk_handle unused, void *ptr); 5841#endif 5842NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type); 5843NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align); 5844NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size); 5845 5846/* draw */ 5847NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip); 5848NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b); 5849NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size); 5850NK_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); 5851 5852/* buffering */ 5853NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5854NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win); 5855NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win); 5856NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*); 5857NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5858NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w); 5859NK_LIB void nk_build(struct nk_context *ctx); 5860 5861/* text editor */ 5862NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter); 5863NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5864NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5865NK_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); 5866 5867/* window */ 5868enum nk_window_insert_location { 5869 NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */ 5870 NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */ 5871}; 5872NK_LIB void *nk_create_window(struct nk_context *ctx); 5873NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*); 5874NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win); 5875NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name); 5876NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc); 5877 5878/* pool */ 5879NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity); 5880NK_LIB void nk_pool_free(struct nk_pool *pool); 5881NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size); 5882NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool); 5883 5884/* page-element */ 5885NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx); 5886NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem); 5887NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem); 5888 5889/* table */ 5890NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx); 5891NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl); 5892NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl); 5893NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl); 5894NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value); 5895NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name); 5896 5897/* panel */ 5898NK_LIB void *nk_create_panel(struct nk_context *ctx); 5899NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan); 5900NK_LIB int nk_panel_has_header(nk_flags flags, const char *title); 5901NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type); 5902NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type); 5903NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type); 5904NK_LIB int nk_panel_is_sub(enum nk_panel_type type); 5905NK_LIB int nk_panel_is_nonblock(enum nk_panel_type type); 5906NK_LIB int nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type); 5907NK_LIB void nk_panel_end(struct nk_context *ctx); 5908 5909/* layout */ 5910NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns); 5911NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols); 5912NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width); 5913NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win); 5914NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify); 5915NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx); 5916NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx); 5917 5918/* popup */ 5919NK_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); 5920 5921/* text */ 5922struct nk_text { 5923 struct nk_vec2 padding; 5924 struct nk_color background; 5925 struct nk_color text; 5926}; 5927NK_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); 5928NK_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); 5929 5930/* button */ 5931NK_LIB int nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior); 5932NK_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); 5933NK_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); 5934NK_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); 5935NK_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); 5936NK_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); 5937NK_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); 5938NK_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); 5939NK_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); 5940NK_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); 5941NK_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); 5942NK_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); 5943NK_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); 5944 5945/* toggle */ 5946enum nk_toggle_type { 5947 NK_TOGGLE_CHECK, 5948 NK_TOGGLE_OPTION 5949}; 5950NK_LIB int nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, int active); 5951NK_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); 5952NK_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); 5953NK_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); 5954 5955/* progress */ 5956NK_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); 5957NK_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); 5958NK_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); 5959 5960/* slider */ 5961NK_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); 5962NK_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); 5963NK_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); 5964 5965/* scrollbar */ 5966NK_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); 5967NK_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); 5968NK_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); 5969NK_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); 5970 5971/* selectable */ 5972NK_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); 5973NK_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); 5974NK_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); 5975 5976/* edit */ 5977NK_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); 5978NK_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); 5979 5980/* color-picker */ 5981NK_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); 5982NK_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); 5983NK_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); 5984 5985/* property */ 5986enum nk_property_status { 5987 NK_PROPERTY_DEFAULT, 5988 NK_PROPERTY_EDIT, 5989 NK_PROPERTY_DRAG 5990}; 5991enum nk_property_filter { 5992 NK_FILTER_INT, 5993 NK_FILTER_FLOAT 5994}; 5995enum nk_property_kind { 5996 NK_PROPERTY_INT, 5997 NK_PROPERTY_FLOAT, 5998 NK_PROPERTY_DOUBLE 5999}; 6000union nk_property { 6001 int i; 6002 float f; 6003 double d; 6004}; 6005struct nk_property_variant { 6006 enum nk_property_kind kind; 6007 union nk_property value; 6008 union nk_property min_value; 6009 union nk_property max_value; 6010 union nk_property step; 6011}; 6012NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step); 6013NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step); 6014NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step); 6015 6016NK_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); 6017NK_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); 6018NK_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); 6019NK_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); 6020NK_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); 6021 6022#endif 6023 6024 6025 6026 6027 6028/* =============================================================== 6029 * 6030 * MATH 6031 * 6032 * ===============================================================*/ 6033/* Since nuklear is supposed to work on all systems providing floating point 6034 math without any dependencies I also had to implement my own math functions 6035 for sqrt, sin and cos. Since the actual highly accurate implementations for 6036 the standard library functions are quite complex and I do not need high 6037 precision for my use cases I use approximations. 6038 6039 Sqrt 6040 ---- 6041 For square root nuklear uses the famous fast inverse square root: 6042 https://en.wikipedia.org/wiki/Fast_inverse_square_root with 6043 slightly tweaked magic constant. While on today's hardware it is 6044 probably not faster it is still fast and accurate enough for 6045 nuklear's use cases. IMPORTANT: this requires float format IEEE 754 6046 6047 Sine/Cosine 6048 ----------- 6049 All constants inside both function are generated Remez's minimax 6050 approximations for value range 0...2*PI. The reason why I decided to 6051 approximate exactly that range is that nuklear only needs sine and 6052 cosine to generate circles which only requires that exact range. 6053 In addition I used Remez instead of Taylor for additional precision: 6054 www.lolengine.net/blog/2011/12/21/better-function-approximations. 6055 6056 The tool I used to generate constants for both sine and cosine 6057 (it can actually approximate a lot more functions) can be 6058 found here: www.lolengine.net/wiki/oss/lolremez 6059*/ 6060NK_LIB float 6061nk_inv_sqrt(float n) 6062{ 6063 float x2; 6064 const float threehalfs = 1.5f; 6065 union {nk_uint i; float f;} conv = {0}; 6066 conv.f = n; 6067 x2 = n * 0.5f; 6068 conv.i = 0x5f375A84 - (conv.i >> 1); 6069 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f)); 6070 return conv.f; 6071} 6072NK_LIB float 6073nk_sqrt(float x) 6074{ 6075 return x * nk_inv_sqrt(x); 6076} 6077NK_LIB float 6078nk_sin(float x) 6079{ 6080 NK_STORAGE const float a0 = +1.91059300966915117e-31f; 6081 NK_STORAGE const float a1 = +1.00086760103908896f; 6082 NK_STORAGE const float a2 = -1.21276126894734565e-2f; 6083 NK_STORAGE const float a3 = -1.38078780785773762e-1f; 6084 NK_STORAGE const float a4 = -2.67353392911981221e-2f; 6085 NK_STORAGE const float a5 = +2.08026600266304389e-2f; 6086 NK_STORAGE const float a6 = -3.03996055049204407e-3f; 6087 NK_STORAGE const float a7 = +1.38235642404333740e-4f; 6088 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); 6089} 6090NK_LIB float 6091nk_cos(float x) 6092{ 6093 /* New implementation. Also generated using lolremez. */ 6094 /* Old version significantly deviated from expected results. */ 6095 NK_STORAGE const float a0 = 9.9995999154986614e-1f; 6096 NK_STORAGE const float a1 = 1.2548995793001028e-3f; 6097 NK_STORAGE const float a2 = -5.0648546280678015e-1f; 6098 NK_STORAGE const float a3 = 1.2942246466519995e-2f; 6099 NK_STORAGE const float a4 = 2.8668384702547972e-2f; 6100 NK_STORAGE const float a5 = 7.3726485210586547e-3f; 6101 NK_STORAGE const float a6 = -3.8510875386947414e-3f; 6102 NK_STORAGE const float a7 = 4.7196604604366623e-4f; 6103 NK_STORAGE const float a8 = -1.8776444013090451e-5f; 6104 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8))))))); 6105} 6106NK_LIB nk_uint 6107nk_round_up_pow2(nk_uint v) 6108{ 6109 v--; 6110 v |= v >> 1; 6111 v |= v >> 2; 6112 v |= v >> 4; 6113 v |= v >> 8; 6114 v |= v >> 16; 6115 v++; 6116 return v; 6117} 6118NK_LIB double 6119nk_pow(double x, int n) 6120{ 6121 /* check the sign of n */ 6122 double r = 1; 6123 int plus = n >= 0; 6124 n = (plus) ? n : -n; 6125 while (n > 0) { 6126 if ((n & 1) == 1) 6127 r *= x; 6128 n /= 2; 6129 x *= x; 6130 } 6131 return plus ? r : 1.0 / r; 6132} 6133NK_LIB int 6134nk_ifloord(double x) 6135{ 6136 x = (double)((int)x - ((x < 0.0) ? 1 : 0)); 6137 return (int)x; 6138} 6139NK_LIB int 6140nk_ifloorf(float x) 6141{ 6142 x = (float)((int)x - ((x < 0.0f) ? 1 : 0)); 6143 return (int)x; 6144} 6145NK_LIB int 6146nk_iceilf(float x) 6147{ 6148 if (x >= 0) { 6149 int i = (int)x; 6150 return (x > i) ? i+1: i; 6151 } else { 6152 int t = (int)x; 6153 float r = x - (float)t; 6154 return (r > 0.0f) ? t+1: t; 6155 } 6156} 6157NK_LIB int 6158nk_log10(double n) 6159{ 6160 int neg; 6161 int ret; 6162 int exp = 0; 6163 6164 neg = (n < 0) ? 1 : 0; 6165 ret = (neg) ? (int)-n : (int)n; 6166 while ((ret / 10) > 0) { 6167 ret /= 10; 6168 exp++; 6169 } 6170 if (neg) exp = -exp; 6171 return exp; 6172} 6173NK_API struct nk_rect 6174nk_get_null_rect(void) 6175{ 6176 return nk_null_rect; 6177} 6178NK_API struct nk_rect 6179nk_rect(float x, float y, float w, float h) 6180{ 6181 struct nk_rect r; 6182 r.x = x; r.y = y; 6183 r.w = w; r.h = h; 6184 return r; 6185} 6186NK_API struct nk_rect 6187nk_recti(int x, int y, int w, int h) 6188{ 6189 struct nk_rect r; 6190 r.x = (float)x; 6191 r.y = (float)y; 6192 r.w = (float)w; 6193 r.h = (float)h; 6194 return r; 6195} 6196NK_API struct nk_rect 6197nk_recta(struct nk_vec2 pos, struct nk_vec2 size) 6198{ 6199 return nk_rect(pos.x, pos.y, size.x, size.y); 6200} 6201NK_API struct nk_rect 6202nk_rectv(const float *r) 6203{ 6204 return nk_rect(r[0], r[1], r[2], r[3]); 6205} 6206NK_API struct nk_rect 6207nk_rectiv(const int *r) 6208{ 6209 return nk_recti(r[0], r[1], r[2], r[3]); 6210} 6211NK_API struct nk_vec2 6212nk_rect_pos(struct nk_rect r) 6213{ 6214 struct nk_vec2 ret; 6215 ret.x = r.x; ret.y = r.y; 6216 return ret; 6217} 6218NK_API struct nk_vec2 6219nk_rect_size(struct nk_rect r) 6220{ 6221 struct nk_vec2 ret; 6222 ret.x = r.w; ret.y = r.h; 6223 return ret; 6224} 6225NK_LIB struct nk_rect 6226nk_shrink_rect(struct nk_rect r, float amount) 6227{ 6228 struct nk_rect res; 6229 r.w = NK_MAX(r.w, 2 * amount); 6230 r.h = NK_MAX(r.h, 2 * amount); 6231 res.x = r.x + amount; 6232 res.y = r.y + amount; 6233 res.w = r.w - 2 * amount; 6234 res.h = r.h - 2 * amount; 6235 return res; 6236} 6237NK_LIB struct nk_rect 6238nk_pad_rect(struct nk_rect r, struct nk_vec2 pad) 6239{ 6240 r.w = NK_MAX(r.w, 2 * pad.x); 6241 r.h = NK_MAX(r.h, 2 * pad.y); 6242 r.x += pad.x; r.y += pad.y; 6243 r.w -= 2 * pad.x; 6244 r.h -= 2 * pad.y; 6245 return r; 6246} 6247NK_API struct nk_vec2 6248nk_vec2(float x, float y) 6249{ 6250 struct nk_vec2 ret; 6251 ret.x = x; ret.y = y; 6252 return ret; 6253} 6254NK_API struct nk_vec2 6255nk_vec2i(int x, int y) 6256{ 6257 struct nk_vec2 ret; 6258 ret.x = (float)x; 6259 ret.y = (float)y; 6260 return ret; 6261} 6262NK_API struct nk_vec2 6263nk_vec2v(const float *v) 6264{ 6265 return nk_vec2(v[0], v[1]); 6266} 6267NK_API struct nk_vec2 6268nk_vec2iv(const int *v) 6269{ 6270 return nk_vec2i(v[0], v[1]); 6271} 6272NK_LIB void 6273nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, 6274 float x1, float y1) 6275{ 6276 NK_ASSERT(a); 6277 NK_ASSERT(clip); 6278 clip->x = NK_MAX(a->x, x0); 6279 clip->y = NK_MAX(a->y, y0); 6280 clip->w = NK_MIN(a->x + a->w, x1) - clip->x; 6281 clip->h = NK_MIN(a->y + a->h, y1) - clip->y; 6282 clip->w = NK_MAX(0, clip->w); 6283 clip->h = NK_MAX(0, clip->h); 6284} 6285 6286NK_API void 6287nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, 6288 float pad_x, float pad_y, enum nk_heading direction) 6289{ 6290 float w_half, h_half; 6291 NK_ASSERT(result); 6292 6293 r.w = NK_MAX(2 * pad_x, r.w); 6294 r.h = NK_MAX(2 * pad_y, r.h); 6295 r.w = r.w - 2 * pad_x; 6296 r.h = r.h - 2 * pad_y; 6297 6298 r.x = r.x + pad_x; 6299 r.y = r.y + pad_y; 6300 6301 w_half = r.w / 2.0f; 6302 h_half = r.h / 2.0f; 6303 6304 if (direction == NK_UP) { 6305 result[0] = nk_vec2(r.x + w_half, r.y); 6306 result[1] = nk_vec2(r.x + r.w, r.y + r.h); 6307 result[2] = nk_vec2(r.x, r.y + r.h); 6308 } else if (direction == NK_RIGHT) { 6309 result[0] = nk_vec2(r.x, r.y); 6310 result[1] = nk_vec2(r.x + r.w, r.y + h_half); 6311 result[2] = nk_vec2(r.x, r.y + r.h); 6312 } else if (direction == NK_DOWN) { 6313 result[0] = nk_vec2(r.x, r.y); 6314 result[1] = nk_vec2(r.x + r.w, r.y); 6315 result[2] = nk_vec2(r.x + w_half, r.y + r.h); 6316 } else { 6317 result[0] = nk_vec2(r.x, r.y + h_half); 6318 result[1] = nk_vec2(r.x + r.w, r.y); 6319 result[2] = nk_vec2(r.x + r.w, r.y + r.h); 6320 } 6321} 6322 6323 6324 6325 6326 6327/* =============================================================== 6328 * 6329 * UTIL 6330 * 6331 * ===============================================================*/ 6332NK_INTERN int nk_str_match_here(const char *regexp, const char *text); 6333NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text); 6334NK_LIB int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);} 6335NK_LIB int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);} 6336NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;} 6337NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;} 6338 6339NK_LIB void* 6340nk_memcopy(void *dst0, const void *src0, nk_size length) 6341{ 6342 nk_ptr t; 6343 char *dst = (char*)dst0; 6344 const char *src = (const char*)src0; 6345 if (length == 0 || dst == src) 6346 goto done; 6347 6348 #define nk_word int 6349 #define nk_wsize sizeof(nk_word) 6350 #define nk_wmask (nk_wsize-1) 6351 #define NK_TLOOP(s) if (t) NK_TLOOP1(s) 6352 #define NK_TLOOP1(s) do { s; } while (--t) 6353 6354 if (dst < src) { 6355 t = (nk_ptr)src; /* only need low bits */ 6356 if ((t | (nk_ptr)dst) & nk_wmask) { 6357 if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize) 6358 t = length; 6359 else 6360 t = nk_wsize - (t & nk_wmask); 6361 length -= t; 6362 NK_TLOOP1(*dst++ = *src++); 6363 } 6364 t = length / nk_wsize; 6365 NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src; 6366 src += nk_wsize; dst += nk_wsize); 6367 t = length & nk_wmask; 6368 NK_TLOOP(*dst++ = *src++); 6369 } else { 6370 src += length; 6371 dst += length; 6372 t = (nk_ptr)src; 6373 if ((t | (nk_ptr)dst) & nk_wmask) { 6374 if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize) 6375 t = length; 6376 else 6377 t &= nk_wmask; 6378 length -= t; 6379 NK_TLOOP1(*--dst = *--src); 6380 } 6381 t = length / nk_wsize; 6382 NK_TLOOP(src -= nk_wsize; dst -= nk_wsize; 6383 *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src); 6384 t = length & nk_wmask; 6385 NK_TLOOP(*--dst = *--src); 6386 } 6387 #undef nk_word 6388 #undef nk_wsize 6389 #undef nk_wmask 6390 #undef NK_TLOOP 6391 #undef NK_TLOOP1 6392done: 6393 return (dst0); 6394} 6395NK_LIB void 6396nk_memset(void *ptr, int c0, nk_size size) 6397{ 6398 #define nk_word unsigned 6399 #define nk_wsize sizeof(nk_word) 6400 #define nk_wmask (nk_wsize - 1) 6401 nk_byte *dst = (nk_byte*)ptr; 6402 unsigned c = 0; 6403 nk_size t = 0; 6404 6405 if ((c = (nk_byte)c0) != 0) { 6406 c = (c << 8) | c; /* at least 16-bits */ 6407 if (sizeof(unsigned int) > 2) 6408 c = (c << 16) | c; /* at least 32-bits*/ 6409 } 6410 6411 /* too small of a word count */ 6412 dst = (nk_byte*)ptr; 6413 if (size < 3 * nk_wsize) { 6414 while (size--) *dst++ = (nk_byte)c0; 6415 return; 6416 } 6417 6418 /* align destination */ 6419 if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) { 6420 t = nk_wsize -t; 6421 size -= t; 6422 do { 6423 *dst++ = (nk_byte)c0; 6424 } while (--t != 0); 6425 } 6426 6427 /* fill word */ 6428 t = size / nk_wsize; 6429 do { 6430 *(nk_word*)((void*)dst) = c; 6431 dst += nk_wsize; 6432 } while (--t != 0); 6433 6434 /* fill trailing bytes */ 6435 t = (size & nk_wmask); 6436 if (t != 0) { 6437 do { 6438 *dst++ = (nk_byte)c0; 6439 } while (--t != 0); 6440 } 6441 6442 #undef nk_word 6443 #undef nk_wsize 6444 #undef nk_wmask 6445} 6446NK_LIB void 6447nk_zero(void *ptr, nk_size size) 6448{ 6449 NK_ASSERT(ptr); 6450 NK_MEMSET(ptr, 0, size); 6451} 6452NK_API int 6453nk_strlen(const char *str) 6454{ 6455 int siz = 0; 6456 NK_ASSERT(str); 6457 while (str && *str++ != '\0') siz++; 6458 return siz; 6459} 6460NK_API int 6461nk_strtoi(const char *str, const char **endptr) 6462{ 6463 int neg = 1; 6464 const char *p = str; 6465 int value = 0; 6466 6467 NK_ASSERT(str); 6468 if (!str) return 0; 6469 6470 /* skip whitespace */ 6471 while (*p == ' ') p++; 6472 if (*p == '-') { 6473 neg = -1; 6474 p++; 6475 } 6476 while (*p && *p >= '0' && *p <= '9') { 6477 value = value * 10 + (int) (*p - '0'); 6478 p++; 6479 } 6480 if (endptr) 6481 *endptr = p; 6482 return neg*value; 6483} 6484NK_API double 6485nk_strtod(const char *str, const char **endptr) 6486{ 6487 double m; 6488 double neg = 1.0; 6489 const char *p = str; 6490 double value = 0; 6491 double number = 0; 6492 6493 NK_ASSERT(str); 6494 if (!str) return 0; 6495 6496 /* skip whitespace */ 6497 while (*p == ' ') p++; 6498 if (*p == '-') { 6499 neg = -1.0; 6500 p++; 6501 } 6502 6503 while (*p && *p != '.' && *p != 'e') { 6504 value = value * 10.0 + (double) (*p - '0'); 6505 p++; 6506 } 6507 6508 if (*p == '.') { 6509 p++; 6510 for(m = 0.1; *p && *p != 'e'; p++ ) { 6511 value = value + (double) (*p - '0') * m; 6512 m *= 0.1; 6513 } 6514 } 6515 if (*p == 'e') { 6516 int i, pow, div; 6517 p++; 6518 if (*p == '-') { 6519 div = nk_true; 6520 p++; 6521 } else if (*p == '+') { 6522 div = nk_false; 6523 p++; 6524 } else div = nk_false; 6525 6526 for (pow = 0; *p; p++) 6527 pow = pow * 10 + (int) (*p - '0'); 6528 6529 for (m = 1.0, i = 0; i < pow; i++) 6530 m *= 10.0; 6531 6532 if (div) 6533 value /= m; 6534 else value *= m; 6535 } 6536 number = value * neg; 6537 if (endptr) 6538 *endptr = p; 6539 return number; 6540} 6541NK_API float 6542nk_strtof(const char *str, const char **endptr) 6543{ 6544 float float_value; 6545 double double_value; 6546 double_value = NK_STRTOD(str, endptr); 6547 float_value = (float)double_value; 6548 return float_value; 6549} 6550NK_API int 6551nk_stricmp(const char *s1, const char *s2) 6552{ 6553 nk_int c1,c2,d; 6554 do { 6555 c1 = *s1++; 6556 c2 = *s2++; 6557 d = c1 - c2; 6558 while (d) { 6559 if (c1 <= 'Z' && c1 >= 'A') { 6560 d += ('a' - 'A'); 6561 if (!d) break; 6562 } 6563 if (c2 <= 'Z' && c2 >= 'A') { 6564 d -= ('a' - 'A'); 6565 if (!d) break; 6566 } 6567 return ((d >= 0) << 1) - 1; 6568 } 6569 } while (c1); 6570 return 0; 6571} 6572NK_API int 6573nk_stricmpn(const char *s1, const char *s2, int n) 6574{ 6575 int c1,c2,d; 6576 NK_ASSERT(n >= 0); 6577 do { 6578 c1 = *s1++; 6579 c2 = *s2++; 6580 if (!n--) return 0; 6581 6582 d = c1 - c2; 6583 while (d) { 6584 if (c1 <= 'Z' && c1 >= 'A') { 6585 d += ('a' - 'A'); 6586 if (!d) break; 6587 } 6588 if (c2 <= 'Z' && c2 >= 'A') { 6589 d -= ('a' - 'A'); 6590 if (!d) break; 6591 } 6592 return ((d >= 0) << 1) - 1; 6593 } 6594 } while (c1); 6595 return 0; 6596} 6597NK_INTERN int 6598nk_str_match_here(const char *regexp, const char *text) 6599{ 6600 if (regexp[0] == '\0') 6601 return 1; 6602 if (regexp[1] == '*') 6603 return nk_str_match_star(regexp[0], regexp+2, text); 6604 if (regexp[0] == '$' && regexp[1] == '\0') 6605 return *text == '\0'; 6606 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) 6607 return nk_str_match_here(regexp+1, text+1); 6608 return 0; 6609} 6610NK_INTERN int 6611nk_str_match_star(int c, const char *regexp, const char *text) 6612{ 6613 do {/* a '* matches zero or more instances */ 6614 if (nk_str_match_here(regexp, text)) 6615 return 1; 6616 } while (*text != '\0' && (*text++ == c || c == '.')); 6617 return 0; 6618} 6619NK_API int 6620nk_strfilter(const char *text, const char *regexp) 6621{ 6622 /* 6623 c matches any literal character c 6624 . matches any single character 6625 ^ matches the beginning of the input string 6626 $ matches the end of the input string 6627 * matches zero or more occurrences of the previous character*/ 6628 if (regexp[0] == '^') 6629 return nk_str_match_here(regexp+1, text); 6630 do { /* must look even if string is empty */ 6631 if (nk_str_match_here(regexp, text)) 6632 return 1; 6633 } while (*text++ != '\0'); 6634 return 0; 6635} 6636NK_API int 6637nk_strmatch_fuzzy_text(const char *str, int str_len, 6638 const char *pattern, int *out_score) 6639{ 6640 /* Returns true if each character in pattern is found sequentially within str 6641 * if found then out_score is also set. Score value has no intrinsic meaning. 6642 * Range varies with pattern. Can only compare scores with same search pattern. */ 6643 6644 /* bonus for adjacent matches */ 6645 #define NK_ADJACENCY_BONUS 5 6646 /* bonus if match occurs after a separator */ 6647 #define NK_SEPARATOR_BONUS 10 6648 /* bonus if match is uppercase and prev is lower */ 6649 #define NK_CAMEL_BONUS 10 6650 /* penalty applied for every letter in str before the first match */ 6651 #define NK_LEADING_LETTER_PENALTY (-3) 6652 /* maximum penalty for leading letters */ 6653 #define NK_MAX_LEADING_LETTER_PENALTY (-9) 6654 /* penalty for every letter that doesn't matter */ 6655 #define NK_UNMATCHED_LETTER_PENALTY (-1) 6656 6657 /* loop variables */ 6658 int score = 0; 6659 char const * pattern_iter = pattern; 6660 int str_iter = 0; 6661 int prev_matched = nk_false; 6662 int prev_lower = nk_false; 6663 /* true so if first letter match gets separator bonus*/ 6664 int prev_separator = nk_true; 6665 6666 /* use "best" matched letter if multiple string letters match the pattern */ 6667 char const * best_letter = 0; 6668 int best_letter_score = 0; 6669 6670 /* loop over strings */ 6671 NK_ASSERT(str); 6672 NK_ASSERT(pattern); 6673 if (!str || !str_len || !pattern) return 0; 6674 while (str_iter < str_len) 6675 { 6676 const char pattern_letter = *pattern_iter; 6677 const char str_letter = str[str_iter]; 6678 6679 int next_match = *pattern_iter != '\0' && 6680 nk_to_lower(pattern_letter) == nk_to_lower(str_letter); 6681 int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter); 6682 6683 int advanced = next_match && best_letter; 6684 int pattern_repeat = best_letter && *pattern_iter != '\0'; 6685 pattern_repeat = pattern_repeat && 6686 nk_to_lower(*best_letter) == nk_to_lower(pattern_letter); 6687 6688 if (advanced || pattern_repeat) { 6689 score += best_letter_score; 6690 best_letter = 0; 6691 best_letter_score = 0; 6692 } 6693 6694 if (next_match || rematch) 6695 { 6696 int new_score = 0; 6697 /* Apply penalty for each letter before the first pattern match */ 6698 if (pattern_iter == pattern) { 6699 int count = (int)(&str[str_iter] - str); 6700 int penalty = NK_LEADING_LETTER_PENALTY * count; 6701 if (penalty < NK_MAX_LEADING_LETTER_PENALTY) 6702 penalty = NK_MAX_LEADING_LETTER_PENALTY; 6703 6704 score += penalty; 6705 } 6706 6707 /* apply bonus for consecutive bonuses */ 6708 if (prev_matched) 6709 new_score += NK_ADJACENCY_BONUS; 6710 6711 /* apply bonus for matches after a separator */ 6712 if (prev_separator) 6713 new_score += NK_SEPARATOR_BONUS; 6714 6715 /* apply bonus across camel case boundaries */ 6716 if (prev_lower && nk_is_upper(str_letter)) 6717 new_score += NK_CAMEL_BONUS; 6718 6719 /* update pattern iter IFF the next pattern letter was matched */ 6720 if (next_match) 6721 ++pattern_iter; 6722 6723 /* update best letter in str which may be for a "next" letter or a rematch */ 6724 if (new_score >= best_letter_score) { 6725 /* apply penalty for now skipped letter */ 6726 if (best_letter != 0) 6727 score += NK_UNMATCHED_LETTER_PENALTY; 6728 6729 best_letter = &str[str_iter]; 6730 best_letter_score = new_score; 6731 } 6732 prev_matched = nk_true; 6733 } else { 6734 score += NK_UNMATCHED_LETTER_PENALTY; 6735 prev_matched = nk_false; 6736 } 6737 6738 /* separators should be more easily defined */ 6739 prev_lower = nk_is_lower(str_letter) != 0; 6740 prev_separator = str_letter == '_' || str_letter == ' '; 6741 6742 ++str_iter; 6743 } 6744 6745 /* apply score for last match */ 6746 if (best_letter) 6747 score += best_letter_score; 6748 6749 /* did not match full pattern */ 6750 if (*pattern_iter != '\0') 6751 return nk_false; 6752 6753 if (out_score) 6754 *out_score = score; 6755 return nk_true; 6756} 6757NK_API int 6758nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score) 6759{ 6760 return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score); 6761} 6762NK_LIB int 6763nk_string_float_limit(char *string, int prec) 6764{ 6765 int dot = 0; 6766 char *c = string; 6767 while (*c) { 6768 if (*c == '.') { 6769 dot = 1; 6770 c++; 6771 continue; 6772 } 6773 if (dot == (prec+1)) { 6774 *c = 0; 6775 break; 6776 } 6777 if (dot > 0) dot++; 6778 c++; 6779 } 6780 return (int)(c - string); 6781} 6782NK_INTERN void 6783nk_strrev_ascii(char *s) 6784{ 6785 int len = nk_strlen(s); 6786 int end = len / 2; 6787 int i = 0; 6788 char t; 6789 for (; i < end; ++i) { 6790 t = s[i]; 6791 s[i] = s[len - 1 - i]; 6792 s[len -1 - i] = t; 6793 } 6794} 6795NK_LIB char* 6796nk_itoa(char *s, long n) 6797{ 6798 long i = 0; 6799 if (n == 0) { 6800 s[i++] = '0'; 6801 s[i] = 0; 6802 return s; 6803 } 6804 if (n < 0) { 6805 s[i++] = '-'; 6806 n = -n; 6807 } 6808 while (n > 0) { 6809 s[i++] = (char)('0' + (n % 10)); 6810 n /= 10; 6811 } 6812 s[i] = 0; 6813 if (s[0] == '-') 6814 ++s; 6815 6816 nk_strrev_ascii(s); 6817 return s; 6818} 6819NK_LIB char* 6820nk_dtoa(char *s, double n) 6821{ 6822 int useExp = 0; 6823 int digit = 0, m = 0, m1 = 0; 6824 char *c = s; 6825 int neg = 0; 6826 6827 NK_ASSERT(s); 6828 if (!s) return 0; 6829 6830 if (n == 0.0) { 6831 s[0] = '0'; s[1] = '\0'; 6832 return s; 6833 } 6834 6835 neg = (n < 0); 6836 if (neg) n = -n; 6837 6838 /* calculate magnitude */ 6839 m = nk_log10(n); 6840 useExp = (m >= 14 || (neg && m >= 9) || m <= -9); 6841 if (neg) *(c++) = '-'; 6842 6843 /* set up for scientific notation */ 6844 if (useExp) { 6845 if (m < 0) 6846 m -= 1; 6847 n = n / (double)nk_pow(10.0, m); 6848 m1 = m; 6849 m = 0; 6850 } 6851 if (m < 1.0) { 6852 m = 0; 6853 } 6854 6855 /* convert the number */ 6856 while (n > NK_FLOAT_PRECISION || m >= 0) { 6857 double weight = nk_pow(10.0, m); 6858 if (weight > 0) { 6859 double t = (double)n / weight; 6860 digit = nk_ifloord(t); 6861 n -= ((double)digit * weight); 6862 *(c++) = (char)('0' + (char)digit); 6863 } 6864 if (m == 0 && n > 0) 6865 *(c++) = '.'; 6866 m--; 6867 } 6868 6869 if (useExp) { 6870 /* convert the exponent */ 6871 int i, j; 6872 *(c++) = 'e'; 6873 if (m1 > 0) { 6874 *(c++) = '+'; 6875 } else { 6876 *(c++) = '-'; 6877 m1 = -m1; 6878 } 6879 m = 0; 6880 while (m1 > 0) { 6881 *(c++) = (char)('0' + (char)(m1 % 10)); 6882 m1 /= 10; 6883 m++; 6884 } 6885 c -= m; 6886 for (i = 0, j = m-1; i<j; i++, j--) { 6887 /* swap without temporary */ 6888 c[i] ^= c[j]; 6889 c[j] ^= c[i]; 6890 c[i] ^= c[j]; 6891 } 6892 c += m; 6893 } 6894 *(c) = '\0'; 6895 return s; 6896} 6897#ifdef NK_INCLUDE_STANDARD_VARARGS 6898#ifndef NK_INCLUDE_STANDARD_IO 6899NK_INTERN int 6900nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args) 6901{ 6902 enum nk_arg_type { 6903 NK_ARG_TYPE_CHAR, 6904 NK_ARG_TYPE_SHORT, 6905 NK_ARG_TYPE_DEFAULT, 6906 NK_ARG_TYPE_LONG 6907 }; 6908 enum nk_arg_flags { 6909 NK_ARG_FLAG_LEFT = 0x01, 6910 NK_ARG_FLAG_PLUS = 0x02, 6911 NK_ARG_FLAG_SPACE = 0x04, 6912 NK_ARG_FLAG_NUM = 0x10, 6913 NK_ARG_FLAG_ZERO = 0x20 6914 }; 6915 6916 char number_buffer[NK_MAX_NUMBER_BUFFER]; 6917 enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT; 6918 int precision = NK_DEFAULT; 6919 int width = NK_DEFAULT; 6920 nk_flags flag = 0; 6921 6922 int len = 0; 6923 int result = -1; 6924 const char *iter = fmt; 6925 6926 NK_ASSERT(buf); 6927 NK_ASSERT(buf_size); 6928 if (!buf || !buf_size || !fmt) return 0; 6929 for (iter = fmt; *iter && len < buf_size; iter++) { 6930 /* copy all non-format characters */ 6931 while (*iter && (*iter != '%') && (len < buf_size)) 6932 buf[len++] = *iter++; 6933 if (!(*iter) || len >= buf_size) break; 6934 iter++; 6935 6936 /* flag arguments */ 6937 while (*iter) { 6938 if (*iter == '-') flag |= NK_ARG_FLAG_LEFT; 6939 else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS; 6940 else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE; 6941 else if (*iter == '#') flag |= NK_ARG_FLAG_NUM; 6942 else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO; 6943 else break; 6944 iter++; 6945 } 6946 6947 /* width argument */ 6948 width = NK_DEFAULT; 6949 if (*iter >= '1' && *iter <= '9') { 6950 const char *end; 6951 width = nk_strtoi(iter, &end); 6952 if (end == iter) 6953 width = -1; 6954 else iter = end; 6955 } else if (*iter == '*') { 6956 width = va_arg(args, int); 6957 iter++; 6958 } 6959 6960 /* precision argument */ 6961 precision = NK_DEFAULT; 6962 if (*iter == '.') { 6963 iter++; 6964 if (*iter == '*') { 6965 precision = va_arg(args, int); 6966 iter++; 6967 } else { 6968 const char *end; 6969 precision = nk_strtoi(iter, &end); 6970 if (end == iter) 6971 precision = -1; 6972 else iter = end; 6973 } 6974 } 6975 6976 /* length modifier */ 6977 if (*iter == 'h') { 6978 if (*(iter+1) == 'h') { 6979 arg_type = NK_ARG_TYPE_CHAR; 6980 iter++; 6981 } else arg_type = NK_ARG_TYPE_SHORT; 6982 iter++; 6983 } else if (*iter == 'l') { 6984 arg_type = NK_ARG_TYPE_LONG; 6985 iter++; 6986 } else arg_type = NK_ARG_TYPE_DEFAULT; 6987 6988 /* specifier */ 6989 if (*iter == '%') { 6990 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 6991 NK_ASSERT(precision == NK_DEFAULT); 6992 NK_ASSERT(width == NK_DEFAULT); 6993 if (len < buf_size) 6994 buf[len++] = '%'; 6995 } else if (*iter == 's') { 6996 /* string */ 6997 const char *str = va_arg(args, const char*); 6998 NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!"); 6999 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7000 NK_ASSERT(precision == NK_DEFAULT); 7001 NK_ASSERT(width == NK_DEFAULT); 7002 if (str == buf) return -1; 7003 while (str && *str && len < buf_size) 7004 buf[len++] = *str++; 7005 } else if (*iter == 'n') { 7006 /* current length callback */ 7007 signed int *n = va_arg(args, int*); 7008 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7009 NK_ASSERT(precision == NK_DEFAULT); 7010 NK_ASSERT(width == NK_DEFAULT); 7011 if (n) *n = len; 7012 } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') { 7013 /* signed integer */ 7014 long value = 0; 7015 const char *num_iter; 7016 int num_len, num_print, padding; 7017 int cur_precision = NK_MAX(precision, 1); 7018 int cur_width = NK_MAX(width, 0); 7019 7020 /* retrieve correct value type */ 7021 if (arg_type == NK_ARG_TYPE_CHAR) 7022 value = (signed char)va_arg(args, int); 7023 else if (arg_type == NK_ARG_TYPE_SHORT) 7024 value = (signed short)va_arg(args, int); 7025 else if (arg_type == NK_ARG_TYPE_LONG) 7026 value = va_arg(args, signed long); 7027 else if (*iter == 'c') 7028 value = (unsigned char)va_arg(args, int); 7029 else value = va_arg(args, signed int); 7030 7031 /* convert number to string */ 7032 nk_itoa(number_buffer, value); 7033 num_len = nk_strlen(number_buffer); 7034 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7035 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7036 padding = NK_MAX(padding-1, 0); 7037 7038 /* fill left padding up to a total of `width` characters */ 7039 if (!(flag & NK_ARG_FLAG_LEFT)) { 7040 while (padding-- > 0 && (len < buf_size)) { 7041 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7042 buf[len++] = '0'; 7043 else buf[len++] = ' '; 7044 } 7045 } 7046 7047 /* copy string value representation into buffer */ 7048 if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size) 7049 buf[len++] = '+'; 7050 else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size) 7051 buf[len++] = ' '; 7052 7053 /* fill up to precision number of digits with '0' */ 7054 num_print = NK_MAX(cur_precision, num_len); 7055 while (precision && (num_print > num_len) && (len < buf_size)) { 7056 buf[len++] = '0'; 7057 num_print--; 7058 } 7059 7060 /* copy string value representation into buffer */ 7061 num_iter = number_buffer; 7062 while (precision && *num_iter && len < buf_size) 7063 buf[len++] = *num_iter++; 7064 7065 /* fill right padding up to width characters */ 7066 if (flag & NK_ARG_FLAG_LEFT) { 7067 while ((padding-- > 0) && (len < buf_size)) 7068 buf[len++] = ' '; 7069 } 7070 } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') { 7071 /* unsigned integer */ 7072 unsigned long value = 0; 7073 int num_len = 0, num_print, padding = 0; 7074 int cur_precision = NK_MAX(precision, 1); 7075 int cur_width = NK_MAX(width, 0); 7076 unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16; 7077 7078 /* print oct/hex/dec value */ 7079 const char *upper_output_format = "0123456789ABCDEF"; 7080 const char *lower_output_format = "0123456789abcdef"; 7081 const char *output_format = (*iter == 'x') ? 7082 lower_output_format: upper_output_format; 7083 7084 /* retrieve correct value type */ 7085 if (arg_type == NK_ARG_TYPE_CHAR) 7086 value = (unsigned char)va_arg(args, int); 7087 else if (arg_type == NK_ARG_TYPE_SHORT) 7088 value = (unsigned short)va_arg(args, int); 7089 else if (arg_type == NK_ARG_TYPE_LONG) 7090 value = va_arg(args, unsigned long); 7091 else value = va_arg(args, unsigned int); 7092 7093 do { 7094 /* convert decimal number into hex/oct number */ 7095 int digit = output_format[value % base]; 7096 if (num_len < NK_MAX_NUMBER_BUFFER) 7097 number_buffer[num_len++] = (char)digit; 7098 value /= base; 7099 } while (value > 0); 7100 7101 num_print = NK_MAX(cur_precision, num_len); 7102 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7103 if (flag & NK_ARG_FLAG_NUM) 7104 padding = NK_MAX(padding-1, 0); 7105 7106 /* fill left padding up to a total of `width` characters */ 7107 if (!(flag & NK_ARG_FLAG_LEFT)) { 7108 while ((padding-- > 0) && (len < buf_size)) { 7109 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7110 buf[len++] = '0'; 7111 else buf[len++] = ' '; 7112 } 7113 } 7114 7115 /* fill up to precision number of digits */ 7116 if (num_print && (flag & NK_ARG_FLAG_NUM)) { 7117 if ((*iter == 'o') && (len < buf_size)) { 7118 buf[len++] = '0'; 7119 } else if ((*iter == 'x') && ((len+1) < buf_size)) { 7120 buf[len++] = '0'; 7121 buf[len++] = 'x'; 7122 } else if ((*iter == 'X') && ((len+1) < buf_size)) { 7123 buf[len++] = '0'; 7124 buf[len++] = 'X'; 7125 } 7126 } 7127 while (precision && (num_print > num_len) && (len < buf_size)) { 7128 buf[len++] = '0'; 7129 num_print--; 7130 } 7131 7132 /* reverse number direction */ 7133 while (num_len > 0) { 7134 if (precision && (len < buf_size)) 7135 buf[len++] = number_buffer[num_len-1]; 7136 num_len--; 7137 } 7138 7139 /* fill right padding up to width characters */ 7140 if (flag & NK_ARG_FLAG_LEFT) { 7141 while ((padding-- > 0) && (len < buf_size)) 7142 buf[len++] = ' '; 7143 } 7144 } else if (*iter == 'f') { 7145 /* floating point */ 7146 const char *num_iter; 7147 int cur_precision = (precision < 0) ? 6: precision; 7148 int prefix, cur_width = NK_MAX(width, 0); 7149 double value = va_arg(args, double); 7150 int num_len = 0, frac_len = 0, dot = 0; 7151 int padding = 0; 7152 7153 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7154 NK_DTOA(number_buffer, value); 7155 num_len = nk_strlen(number_buffer); 7156 7157 /* calculate padding */ 7158 num_iter = number_buffer; 7159 while (*num_iter && *num_iter != '.') 7160 num_iter++; 7161 7162 prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0; 7163 padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0); 7164 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7165 padding = NK_MAX(padding-1, 0); 7166 7167 /* fill left padding up to a total of `width` characters */ 7168 if (!(flag & NK_ARG_FLAG_LEFT)) { 7169 while (padding-- > 0 && (len < buf_size)) { 7170 if (flag & NK_ARG_FLAG_ZERO) 7171 buf[len++] = '0'; 7172 else buf[len++] = ' '; 7173 } 7174 } 7175 7176 /* copy string value representation into buffer */ 7177 num_iter = number_buffer; 7178 if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size)) 7179 buf[len++] = '+'; 7180 else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size)) 7181 buf[len++] = ' '; 7182 while (*num_iter) { 7183 if (dot) frac_len++; 7184 if (len < buf_size) 7185 buf[len++] = *num_iter; 7186 if (*num_iter == '.') dot = 1; 7187 if (frac_len >= cur_precision) break; 7188 num_iter++; 7189 } 7190 7191 /* fill number up to precision */ 7192 while (frac_len < cur_precision) { 7193 if (!dot && len < buf_size) { 7194 buf[len++] = '.'; 7195 dot = 1; 7196 } 7197 if (len < buf_size) 7198 buf[len++] = '0'; 7199 frac_len++; 7200 } 7201 7202 /* fill right padding up to width characters */ 7203 if (flag & NK_ARG_FLAG_LEFT) { 7204 while ((padding-- > 0) && (len < buf_size)) 7205 buf[len++] = ' '; 7206 } 7207 } else { 7208 /* Specifier not supported: g,G,e,E,p,z */ 7209 NK_ASSERT(0 && "specifier is not supported!"); 7210 return result; 7211 } 7212 } 7213 buf[(len >= buf_size)?(buf_size-1):len] = 0; 7214 result = (len >= buf_size)?-1:len; 7215 return result; 7216} 7217#endif 7218NK_LIB int 7219nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args) 7220{ 7221 int result = -1; 7222 NK_ASSERT(buf); 7223 NK_ASSERT(buf_size); 7224 if (!buf || !buf_size || !fmt) return 0; 7225#ifdef NK_INCLUDE_STANDARD_IO 7226 result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args); 7227 result = (result >= buf_size) ? -1: result; 7228 buf[buf_size-1] = 0; 7229#else 7230 result = nk_vsnprintf(buf, buf_size, fmt, args); 7231#endif 7232 return result; 7233} 7234#endif 7235NK_API nk_hash 7236nk_murmur_hash(const void * key, int len, nk_hash seed) 7237{ 7238 /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ 7239 #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) 7240 7241 nk_uint h1 = seed; 7242 nk_uint k1; 7243 const nk_byte *data = (const nk_byte*)key; 7244 const nk_byte *keyptr = data; 7245 nk_byte *k1ptr; 7246 const int bsize = sizeof(k1); 7247 const int nblocks = len/4; 7248 7249 const nk_uint c1 = 0xcc9e2d51; 7250 const nk_uint c2 = 0x1b873593; 7251 const nk_byte *tail; 7252 int i; 7253 7254 /* body */ 7255 if (!key) return 0; 7256 for (i = 0; i < nblocks; ++i, keyptr += bsize) { 7257 k1ptr = (nk_byte*)&k1; 7258 k1ptr[0] = keyptr[0]; 7259 k1ptr[1] = keyptr[1]; 7260 k1ptr[2] = keyptr[2]; 7261 k1ptr[3] = keyptr[3]; 7262 7263 k1 *= c1; 7264 k1 = NK_ROTL(k1,15); 7265 k1 *= c2; 7266 7267 h1 ^= k1; 7268 h1 = NK_ROTL(h1,13); 7269 h1 = h1*5+0xe6546b64; 7270 } 7271 7272 /* tail */ 7273 tail = (const nk_byte*)(data + nblocks*4); 7274 k1 = 0; 7275 switch (len & 3) { 7276 case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */ 7277 case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */ 7278 case 1: k1 ^= tail[0]; 7279 k1 *= c1; 7280 k1 = NK_ROTL(k1,15); 7281 k1 *= c2; 7282 h1 ^= k1; 7283 break; 7284 default: break; 7285 } 7286 7287 /* finalization */ 7288 h1 ^= (nk_uint)len; 7289 /* fmix32 */ 7290 h1 ^= h1 >> 16; 7291 h1 *= 0x85ebca6b; 7292 h1 ^= h1 >> 13; 7293 h1 *= 0xc2b2ae35; 7294 h1 ^= h1 >> 16; 7295 7296 #undef NK_ROTL 7297 return h1; 7298} 7299#ifdef NK_INCLUDE_STANDARD_IO 7300NK_LIB char* 7301nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc) 7302{ 7303 char *buf; 7304 FILE *fd; 7305 long ret; 7306 7307 NK_ASSERT(path); 7308 NK_ASSERT(siz); 7309 NK_ASSERT(alloc); 7310 if (!path || !siz || !alloc) 7311 return 0; 7312 7313 fd = fopen(path, "rb"); 7314 if (!fd) return 0; 7315 fseek(fd, 0, SEEK_END); 7316 ret = ftell(fd); 7317 if (ret < 0) { 7318 fclose(fd); 7319 return 0; 7320 } 7321 *siz = (nk_size)ret; 7322 fseek(fd, 0, SEEK_SET); 7323 buf = (char*)alloc->alloc(alloc->userdata,0, *siz); 7324 NK_ASSERT(buf); 7325 if (!buf) { 7326 fclose(fd); 7327 return 0; 7328 } 7329 *siz = (nk_size)fread(buf, 1,*siz, fd); 7330 fclose(fd); 7331 return buf; 7332} 7333#endif 7334NK_LIB int 7335nk_text_clamp(const struct nk_user_font *font, const char *text, 7336 int text_len, float space, int *glyphs, float *text_width, 7337 nk_rune *sep_list, int sep_count) 7338{ 7339 int i = 0; 7340 int glyph_len = 0; 7341 float last_width = 0; 7342 nk_rune unicode = 0; 7343 float width = 0; 7344 int len = 0; 7345 int g = 0; 7346 float s; 7347 7348 int sep_len = 0; 7349 int sep_g = 0; 7350 float sep_width = 0; 7351 sep_count = NK_MAX(sep_count,0); 7352 7353 glyph_len = nk_utf_decode(text, &unicode, text_len); 7354 while (glyph_len && (width < space) && (len < text_len)) { 7355 len += glyph_len; 7356 s = font->width(font->userdata, font->height, text, len); 7357 for (i = 0; i < sep_count; ++i) { 7358 if (unicode != sep_list[i]) continue; 7359 sep_width = last_width = width; 7360 sep_g = g+1; 7361 sep_len = len; 7362 break; 7363 } 7364 if (i == sep_count){ 7365 last_width = sep_width = width; 7366 sep_g = g+1; 7367 } 7368 width = s; 7369 glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len); 7370 g++; 7371 } 7372 if (len >= text_len) { 7373 *glyphs = g; 7374 *text_width = last_width; 7375 return len; 7376 } else { 7377 *glyphs = sep_g; 7378 *text_width = sep_width; 7379 return (!sep_len) ? len: sep_len; 7380 } 7381} 7382NK_LIB struct nk_vec2 7383nk_text_calculate_text_bounds(const struct nk_user_font *font, 7384 const char *begin, int byte_len, float row_height, const char **remaining, 7385 struct nk_vec2 *out_offset, int *glyphs, int op) 7386{ 7387 float line_height = row_height; 7388 struct nk_vec2 text_size = nk_vec2(0,0); 7389 float line_width = 0.0f; 7390 7391 float glyph_width; 7392 int glyph_len = 0; 7393 nk_rune unicode = 0; 7394 int text_len = 0; 7395 if (!begin || byte_len <= 0 || !font) 7396 return nk_vec2(0,row_height); 7397 7398 glyph_len = nk_utf_decode(begin, &unicode, byte_len); 7399 if (!glyph_len) return text_size; 7400 glyph_width = font->width(font->userdata, font->height, begin, glyph_len); 7401 7402 *glyphs = 0; 7403 while ((text_len < byte_len) && glyph_len) { 7404 if (unicode == '\n') { 7405 text_size.x = NK_MAX(text_size.x, line_width); 7406 text_size.y += line_height; 7407 line_width = 0; 7408 *glyphs+=1; 7409 if (op == NK_STOP_ON_NEW_LINE) 7410 break; 7411 7412 text_len++; 7413 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7414 continue; 7415 } 7416 7417 if (unicode == '\r') { 7418 text_len++; 7419 *glyphs+=1; 7420 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7421 continue; 7422 } 7423 7424 *glyphs = *glyphs + 1; 7425 text_len += glyph_len; 7426 line_width += (float)glyph_width; 7427 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7428 glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len); 7429 continue; 7430 } 7431 7432 if (text_size.x < line_width) 7433 text_size.x = line_width; 7434 if (out_offset) 7435 *out_offset = nk_vec2(line_width, text_size.y + line_height); 7436 if (line_width > 0 || text_size.y == 0.0f) 7437 text_size.y += line_height; 7438 if (remaining) 7439 *remaining = begin+text_len; 7440 return text_size; 7441} 7442 7443 7444 7445 7446 7447/* ============================================================== 7448 * 7449 * COLOR 7450 * 7451 * ===============================================================*/ 7452NK_INTERN int 7453nk_parse_hex(const char *p, int length) 7454{ 7455 int i = 0; 7456 int len = 0; 7457 while (len < length) { 7458 i <<= 4; 7459 if (p[len] >= 'a' && p[len] <= 'f') 7460 i += ((p[len] - 'a') + 10); 7461 else if (p[len] >= 'A' && p[len] <= 'F') 7462 i += ((p[len] - 'A') + 10); 7463 else i += (p[len] - '0'); 7464 len++; 7465 } 7466 return i; 7467} 7468NK_API struct nk_color 7469nk_rgba(int r, int g, int b, int a) 7470{ 7471 struct nk_color ret; 7472 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7473 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7474 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7475 ret.a = (nk_byte)NK_CLAMP(0, a, 255); 7476 return ret; 7477} 7478NK_API struct nk_color 7479nk_rgb_hex(const char *rgb) 7480{ 7481 struct nk_color col; 7482 const char *c = rgb; 7483 if (*c == '#') c++; 7484 col.r = (nk_byte)nk_parse_hex(c, 2); 7485 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7486 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7487 col.a = 255; 7488 return col; 7489} 7490NK_API struct nk_color 7491nk_rgba_hex(const char *rgb) 7492{ 7493 struct nk_color col; 7494 const char *c = rgb; 7495 if (*c == '#') c++; 7496 col.r = (nk_byte)nk_parse_hex(c, 2); 7497 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7498 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7499 col.a = (nk_byte)nk_parse_hex(c+6, 2); 7500 return col; 7501} 7502NK_API void 7503nk_color_hex_rgba(char *output, struct nk_color col) 7504{ 7505 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7506 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7507 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7508 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7509 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7510 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7511 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7512 output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4); 7513 output[7] = (char)NK_TO_HEX((col.a & 0x0F)); 7514 output[8] = '\0'; 7515 #undef NK_TO_HEX 7516} 7517NK_API void 7518nk_color_hex_rgb(char *output, struct nk_color col) 7519{ 7520 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7521 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7522 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7523 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7524 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7525 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7526 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7527 output[6] = '\0'; 7528 #undef NK_TO_HEX 7529} 7530NK_API struct nk_color 7531nk_rgba_iv(const int *c) 7532{ 7533 return nk_rgba(c[0], c[1], c[2], c[3]); 7534} 7535NK_API struct nk_color 7536nk_rgba_bv(const nk_byte *c) 7537{ 7538 return nk_rgba(c[0], c[1], c[2], c[3]); 7539} 7540NK_API struct nk_color 7541nk_rgb(int r, int g, int b) 7542{ 7543 struct nk_color ret; 7544 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7545 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7546 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7547 ret.a = (nk_byte)255; 7548 return ret; 7549} 7550NK_API struct nk_color 7551nk_rgb_iv(const int *c) 7552{ 7553 return nk_rgb(c[0], c[1], c[2]); 7554} 7555NK_API struct nk_color 7556nk_rgb_bv(const nk_byte* c) 7557{ 7558 return nk_rgb(c[0], c[1], c[2]); 7559} 7560NK_API struct nk_color 7561nk_rgba_u32(nk_uint in) 7562{ 7563 struct nk_color ret; 7564 ret.r = (in & 0xFF); 7565 ret.g = ((in >> 8) & 0xFF); 7566 ret.b = ((in >> 16) & 0xFF); 7567 ret.a = (nk_byte)((in >> 24) & 0xFF); 7568 return ret; 7569} 7570NK_API struct nk_color 7571nk_rgba_f(float r, float g, float b, float a) 7572{ 7573 struct nk_color ret; 7574 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7575 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7576 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7577 ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f); 7578 return ret; 7579} 7580NK_API struct nk_color 7581nk_rgba_fv(const float *c) 7582{ 7583 return nk_rgba_f(c[0], c[1], c[2], c[3]); 7584} 7585NK_API struct nk_color 7586nk_rgba_cf(struct nk_colorf c) 7587{ 7588 return nk_rgba_f(c.r, c.g, c.b, c.a); 7589} 7590NK_API struct nk_color 7591nk_rgb_f(float r, float g, float b) 7592{ 7593 struct nk_color ret; 7594 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7595 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7596 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7597 ret.a = 255; 7598 return ret; 7599} 7600NK_API struct nk_color 7601nk_rgb_fv(const float *c) 7602{ 7603 return nk_rgb_f(c[0], c[1], c[2]); 7604} 7605NK_API struct nk_color 7606nk_rgb_cf(struct nk_colorf c) 7607{ 7608 return nk_rgb_f(c.r, c.g, c.b); 7609} 7610NK_API struct nk_color 7611nk_hsv(int h, int s, int v) 7612{ 7613 return nk_hsva(h, s, v, 255); 7614} 7615NK_API struct nk_color 7616nk_hsv_iv(const int *c) 7617{ 7618 return nk_hsv(c[0], c[1], c[2]); 7619} 7620NK_API struct nk_color 7621nk_hsv_bv(const nk_byte *c) 7622{ 7623 return nk_hsv(c[0], c[1], c[2]); 7624} 7625NK_API struct nk_color 7626nk_hsv_f(float h, float s, float v) 7627{ 7628 return nk_hsva_f(h, s, v, 1.0f); 7629} 7630NK_API struct nk_color 7631nk_hsv_fv(const float *c) 7632{ 7633 return nk_hsv_f(c[0], c[1], c[2]); 7634} 7635NK_API struct nk_color 7636nk_hsva(int h, int s, int v, int a) 7637{ 7638 float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f; 7639 float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f; 7640 float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f; 7641 float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f; 7642 return nk_hsva_f(hf, sf, vf, af); 7643} 7644NK_API struct nk_color 7645nk_hsva_iv(const int *c) 7646{ 7647 return nk_hsva(c[0], c[1], c[2], c[3]); 7648} 7649NK_API struct nk_color 7650nk_hsva_bv(const nk_byte *c) 7651{ 7652 return nk_hsva(c[0], c[1], c[2], c[3]); 7653} 7654NK_API struct nk_colorf 7655nk_hsva_colorf(float h, float s, float v, float a) 7656{ 7657 int i; 7658 float p, q, t, f; 7659 struct nk_colorf out = {0,0,0,0}; 7660 if (s <= 0.0f) { 7661 out.r = v; out.g = v; out.b = v; out.a = a; 7662 return out; 7663 } 7664 h = h / (60.0f/360.0f); 7665 i = (int)h; 7666 f = h - (float)i; 7667 p = v * (1.0f - s); 7668 q = v * (1.0f - (s * f)); 7669 t = v * (1.0f - s * (1.0f - f)); 7670 7671 switch (i) { 7672 case 0: default: out.r = v; out.g = t; out.b = p; break; 7673 case 1: out.r = q; out.g = v; out.b = p; break; 7674 case 2: out.r = p; out.g = v; out.b = t; break; 7675 case 3: out.r = p; out.g = q; out.b = v; break; 7676 case 4: out.r = t; out.g = p; out.b = v; break; 7677 case 5: out.r = v; out.g = p; out.b = q; break;} 7678 out.a = a; 7679 return out; 7680} 7681NK_API struct nk_colorf 7682nk_hsva_colorfv(float *c) 7683{ 7684 return nk_hsva_colorf(c[0], c[1], c[2], c[3]); 7685} 7686NK_API struct nk_color 7687nk_hsva_f(float h, float s, float v, float a) 7688{ 7689 struct nk_colorf c = nk_hsva_colorf(h, s, v, a); 7690 return nk_rgba_f(c.r, c.g, c.b, c.a); 7691} 7692NK_API struct nk_color 7693nk_hsva_fv(const float *c) 7694{ 7695 return nk_hsva_f(c[0], c[1], c[2], c[3]); 7696} 7697NK_API nk_uint 7698nk_color_u32(struct nk_color in) 7699{ 7700 nk_uint out = (nk_uint)in.r; 7701 out |= ((nk_uint)in.g << 8); 7702 out |= ((nk_uint)in.b << 16); 7703 out |= ((nk_uint)in.a << 24); 7704 return out; 7705} 7706NK_API void 7707nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in) 7708{ 7709 NK_STORAGE const float s = 1.0f/255.0f; 7710 *r = (float)in.r * s; 7711 *g = (float)in.g * s; 7712 *b = (float)in.b * s; 7713 *a = (float)in.a * s; 7714} 7715NK_API void 7716nk_color_fv(float *c, struct nk_color in) 7717{ 7718 nk_color_f(&c[0], &c[1], &c[2], &c[3], in); 7719} 7720NK_API struct nk_colorf 7721nk_color_cf(struct nk_color in) 7722{ 7723 struct nk_colorf o; 7724 nk_color_f(&o.r, &o.g, &o.b, &o.a, in); 7725 return o; 7726} 7727NK_API void 7728nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in) 7729{ 7730 NK_STORAGE const double s = 1.0/255.0; 7731 *r = (double)in.r * s; 7732 *g = (double)in.g * s; 7733 *b = (double)in.b * s; 7734 *a = (double)in.a * s; 7735} 7736NK_API void 7737nk_color_dv(double *c, struct nk_color in) 7738{ 7739 nk_color_d(&c[0], &c[1], &c[2], &c[3], in); 7740} 7741NK_API void 7742nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in) 7743{ 7744 float a; 7745 nk_color_hsva_f(out_h, out_s, out_v, &a, in); 7746} 7747NK_API void 7748nk_color_hsv_fv(float *out, struct nk_color in) 7749{ 7750 float a; 7751 nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in); 7752} 7753NK_API void 7754nk_colorf_hsva_f(float *out_h, float *out_s, 7755 float *out_v, float *out_a, struct nk_colorf in) 7756{ 7757 float chroma; 7758 float K = 0.0f; 7759 if (in.g < in.b) { 7760 const float t = in.g; in.g = in.b; in.b = t; 7761 K = -1.f; 7762 } 7763 if (in.r < in.g) { 7764 const float t = in.r; in.r = in.g; in.g = t; 7765 K = -2.f/6.0f - K; 7766 } 7767 chroma = in.r - ((in.g < in.b) ? in.g: in.b); 7768 *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f)); 7769 *out_s = chroma / (in.r + 1e-20f); 7770 *out_v = in.r; 7771 *out_a = in.a; 7772 7773} 7774NK_API void 7775nk_colorf_hsva_fv(float *hsva, struct nk_colorf in) 7776{ 7777 nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in); 7778} 7779NK_API void 7780nk_color_hsva_f(float *out_h, float *out_s, 7781 float *out_v, float *out_a, struct nk_color in) 7782{ 7783 struct nk_colorf col; 7784 nk_color_f(&col.r,&col.g,&col.b,&col.a, in); 7785 nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col); 7786} 7787NK_API void 7788nk_color_hsva_fv(float *out, struct nk_color in) 7789{ 7790 nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in); 7791} 7792NK_API void 7793nk_color_hsva_i(int *out_h, int *out_s, int *out_v, 7794 int *out_a, struct nk_color in) 7795{ 7796 float h,s,v,a; 7797 nk_color_hsva_f(&h, &s, &v, &a, in); 7798 *out_h = (nk_byte)(h * 255.0f); 7799 *out_s = (nk_byte)(s * 255.0f); 7800 *out_v = (nk_byte)(v * 255.0f); 7801 *out_a = (nk_byte)(a * 255.0f); 7802} 7803NK_API void 7804nk_color_hsva_iv(int *out, struct nk_color in) 7805{ 7806 nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in); 7807} 7808NK_API void 7809nk_color_hsva_bv(nk_byte *out, struct nk_color in) 7810{ 7811 int tmp[4]; 7812 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7813 out[0] = (nk_byte)tmp[0]; 7814 out[1] = (nk_byte)tmp[1]; 7815 out[2] = (nk_byte)tmp[2]; 7816 out[3] = (nk_byte)tmp[3]; 7817} 7818NK_API void 7819nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in) 7820{ 7821 int tmp[4]; 7822 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7823 *h = (nk_byte)tmp[0]; 7824 *s = (nk_byte)tmp[1]; 7825 *v = (nk_byte)tmp[2]; 7826 *a = (nk_byte)tmp[3]; 7827} 7828NK_API void 7829nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in) 7830{ 7831 int a; 7832 nk_color_hsva_i(out_h, out_s, out_v, &a, in); 7833} 7834NK_API void 7835nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in) 7836{ 7837 int tmp[4]; 7838 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7839 *out_h = (nk_byte)tmp[0]; 7840 *out_s = (nk_byte)tmp[1]; 7841 *out_v = (nk_byte)tmp[2]; 7842} 7843NK_API void 7844nk_color_hsv_iv(int *out, struct nk_color in) 7845{ 7846 nk_color_hsv_i(&out[0], &out[1], &out[2], in); 7847} 7848NK_API void 7849nk_color_hsv_bv(nk_byte *out, struct nk_color in) 7850{ 7851 int tmp[4]; 7852 nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in); 7853 out[0] = (nk_byte)tmp[0]; 7854 out[1] = (nk_byte)tmp[1]; 7855 out[2] = (nk_byte)tmp[2]; 7856} 7857 7858 7859 7860 7861 7862/* =============================================================== 7863 * 7864 * UTF-8 7865 * 7866 * ===============================================================*/ 7867NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 7868NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 7869NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000}; 7870NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 7871 7872NK_INTERN int 7873nk_utf_validate(nk_rune *u, int i) 7874{ 7875 NK_ASSERT(u); 7876 if (!u) return 0; 7877 if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) || 7878 NK_BETWEEN(*u, 0xD800, 0xDFFF)) 7879 *u = NK_UTF_INVALID; 7880 for (i = 1; *u > nk_utfmax[i]; ++i); 7881 return i; 7882} 7883NK_INTERN nk_rune 7884nk_utf_decode_byte(char c, int *i) 7885{ 7886 NK_ASSERT(i); 7887 if (!i) return 0; 7888 for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) { 7889 if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i]) 7890 return (nk_byte)(c & ~nk_utfmask[*i]); 7891 } 7892 return 0; 7893} 7894NK_API int 7895nk_utf_decode(const char *c, nk_rune *u, int clen) 7896{ 7897 int i, j, len, type=0; 7898 nk_rune udecoded; 7899 7900 NK_ASSERT(c); 7901 NK_ASSERT(u); 7902 7903 if (!c || !u) return 0; 7904 if (!clen) return 0; 7905 *u = NK_UTF_INVALID; 7906 7907 udecoded = nk_utf_decode_byte(c[0], &len); 7908 if (!NK_BETWEEN(len, 1, NK_UTF_SIZE)) 7909 return 1; 7910 7911 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 7912 udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type); 7913 if (type != 0) 7914 return j; 7915 } 7916 if (j < len) 7917 return 0; 7918 *u = udecoded; 7919 nk_utf_validate(u, len); 7920 return len; 7921} 7922NK_INTERN char 7923nk_utf_encode_byte(nk_rune u, int i) 7924{ 7925 return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i])); 7926} 7927NK_API int 7928nk_utf_encode(nk_rune u, char *c, int clen) 7929{ 7930 int len, i; 7931 len = nk_utf_validate(&u, 0); 7932 if (clen < len || !len || len > NK_UTF_SIZE) 7933 return 0; 7934 7935 for (i = len - 1; i != 0; --i) { 7936 c[i] = nk_utf_encode_byte(u, 0); 7937 u >>= 6; 7938 } 7939 c[0] = nk_utf_encode_byte(u, len); 7940 return len; 7941} 7942NK_API int 7943nk_utf_len(const char *str, int len) 7944{ 7945 const char *text; 7946 int glyphs = 0; 7947 int text_len; 7948 int glyph_len; 7949 int src_len = 0; 7950 nk_rune unicode; 7951 7952 NK_ASSERT(str); 7953 if (!str || !len) return 0; 7954 7955 text = str; 7956 text_len = len; 7957 glyph_len = nk_utf_decode(text, &unicode, text_len); 7958 while (glyph_len && src_len < len) { 7959 glyphs++; 7960 src_len = src_len + glyph_len; 7961 glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len); 7962 } 7963 return glyphs; 7964} 7965NK_API const char* 7966nk_utf_at(const char *buffer, int length, int index, 7967 nk_rune *unicode, int *len) 7968{ 7969 int i = 0; 7970 int src_len = 0; 7971 int glyph_len = 0; 7972 const char *text; 7973 int text_len; 7974 7975 NK_ASSERT(buffer); 7976 NK_ASSERT(unicode); 7977 NK_ASSERT(len); 7978 7979 if (!buffer || !unicode || !len) return 0; 7980 if (index < 0) { 7981 *unicode = NK_UTF_INVALID; 7982 *len = 0; 7983 return 0; 7984 } 7985 7986 text = buffer; 7987 text_len = length; 7988 glyph_len = nk_utf_decode(text, unicode, text_len); 7989 while (glyph_len) { 7990 if (i == index) { 7991 *len = glyph_len; 7992 break; 7993 } 7994 7995 i++; 7996 src_len = src_len + glyph_len; 7997 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 7998 } 7999 if (i != index) return 0; 8000 return buffer + src_len; 8001} 8002 8003 8004 8005 8006 8007/* ============================================================== 8008 * 8009 * BUFFER 8010 * 8011 * ===============================================================*/ 8012#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8013NK_LIB void* 8014nk_malloc(nk_handle unused, void *old,nk_size size) 8015{ 8016 NK_UNUSED(unused); 8017 NK_UNUSED(old); 8018 return malloc(size); 8019} 8020NK_LIB void 8021nk_mfree(nk_handle unused, void *ptr) 8022{ 8023 NK_UNUSED(unused); 8024 free(ptr); 8025} 8026NK_API void 8027nk_buffer_init_default(struct nk_buffer *buffer) 8028{ 8029 struct nk_allocator alloc; 8030 alloc.userdata.ptr = 0; 8031 alloc.alloc = nk_malloc; 8032 alloc.free = nk_mfree; 8033 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE); 8034} 8035#endif 8036 8037NK_API void 8038nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a, 8039 nk_size initial_size) 8040{ 8041 NK_ASSERT(b); 8042 NK_ASSERT(a); 8043 NK_ASSERT(initial_size); 8044 if (!b || !a || !initial_size) return; 8045 8046 nk_zero(b, sizeof(*b)); 8047 b->type = NK_BUFFER_DYNAMIC; 8048 b->memory.ptr = a->alloc(a->userdata,0, initial_size); 8049 b->memory.size = initial_size; 8050 b->size = initial_size; 8051 b->grow_factor = 2.0f; 8052 b->pool = *a; 8053} 8054NK_API void 8055nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size) 8056{ 8057 NK_ASSERT(b); 8058 NK_ASSERT(m); 8059 NK_ASSERT(size); 8060 if (!b || !m || !size) return; 8061 8062 nk_zero(b, sizeof(*b)); 8063 b->type = NK_BUFFER_FIXED; 8064 b->memory.ptr = m; 8065 b->memory.size = size; 8066 b->size = size; 8067} 8068NK_LIB void* 8069nk_buffer_align(void *unaligned, 8070 nk_size align, nk_size *alignment, 8071 enum nk_buffer_allocation_type type) 8072{ 8073 void *memory = 0; 8074 switch (type) { 8075 default: 8076 case NK_BUFFER_MAX: 8077 case NK_BUFFER_FRONT: 8078 if (align) { 8079 memory = NK_ALIGN_PTR(unaligned, align); 8080 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8081 } else { 8082 memory = unaligned; 8083 *alignment = 0; 8084 } 8085 break; 8086 case NK_BUFFER_BACK: 8087 if (align) { 8088 memory = NK_ALIGN_PTR_BACK(unaligned, align); 8089 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory); 8090 } else { 8091 memory = unaligned; 8092 *alignment = 0; 8093 } 8094 break; 8095 } 8096 return memory; 8097} 8098NK_LIB void* 8099nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size) 8100{ 8101 void *temp; 8102 nk_size buffer_size; 8103 8104 NK_ASSERT(b); 8105 NK_ASSERT(size); 8106 if (!b || !size || !b->pool.alloc || !b->pool.free) 8107 return 0; 8108 8109 buffer_size = b->memory.size; 8110 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity); 8111 NK_ASSERT(temp); 8112 if (!temp) return 0; 8113 8114 *size = capacity; 8115 if (temp != b->memory.ptr) { 8116 NK_MEMCPY(temp, b->memory.ptr, buffer_size); 8117 b->pool.free(b->pool.userdata, b->memory.ptr); 8118 } 8119 8120 if (b->size == buffer_size) { 8121 /* no back buffer so just set correct size */ 8122 b->size = capacity; 8123 return temp; 8124 } else { 8125 /* copy back buffer to the end of the new buffer */ 8126 void *dst, *src; 8127 nk_size back_size; 8128 back_size = buffer_size - b->size; 8129 dst = nk_ptr_add(void, temp, capacity - back_size); 8130 src = nk_ptr_add(void, temp, b->size); 8131 NK_MEMCPY(dst, src, back_size); 8132 b->size = capacity - back_size; 8133 } 8134 return temp; 8135} 8136NK_LIB void* 8137nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8138 nk_size size, nk_size align) 8139{ 8140 int full; 8141 nk_size alignment; 8142 void *unaligned; 8143 void *memory; 8144 8145 NK_ASSERT(b); 8146 NK_ASSERT(size); 8147 if (!b || !size) return 0; 8148 b->needed += size; 8149 8150 /* calculate total size with needed alignment + size */ 8151 if (type == NK_BUFFER_FRONT) 8152 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8153 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8154 memory = nk_buffer_align(unaligned, align, &alignment, type); 8155 8156 /* check if buffer has enough memory*/ 8157 if (type == NK_BUFFER_FRONT) 8158 full = ((b->allocated + size + alignment) > b->size); 8159 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated); 8160 8161 if (full) { 8162 nk_size capacity; 8163 if (b->type != NK_BUFFER_DYNAMIC) 8164 return 0; 8165 NK_ASSERT(b->pool.alloc && b->pool.free); 8166 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free) 8167 return 0; 8168 8169 /* buffer is full so allocate bigger buffer if dynamic */ 8170 capacity = (nk_size)((float)b->memory.size * b->grow_factor); 8171 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size))); 8172 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size); 8173 if (!b->memory.ptr) return 0; 8174 8175 /* align newly allocated pointer */ 8176 if (type == NK_BUFFER_FRONT) 8177 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8178 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8179 memory = nk_buffer_align(unaligned, align, &alignment, type); 8180 } 8181 if (type == NK_BUFFER_FRONT) 8182 b->allocated += size + alignment; 8183 else b->size -= (size + alignment); 8184 b->needed += alignment; 8185 b->calls++; 8186 return memory; 8187} 8188NK_API void 8189nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8190 const void *memory, nk_size size, nk_size align) 8191{ 8192 void *mem = nk_buffer_alloc(b, type, size, align); 8193 if (!mem) return; 8194 NK_MEMCPY(mem, memory, size); 8195} 8196NK_API void 8197nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8198{ 8199 NK_ASSERT(buffer); 8200 if (!buffer) return; 8201 buffer->marker[type].active = nk_true; 8202 if (type == NK_BUFFER_BACK) 8203 buffer->marker[type].offset = buffer->size; 8204 else buffer->marker[type].offset = buffer->allocated; 8205} 8206NK_API void 8207nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8208{ 8209 NK_ASSERT(buffer); 8210 if (!buffer) return; 8211 if (type == NK_BUFFER_BACK) { 8212 /* reset back buffer either back to marker or empty */ 8213 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset); 8214 if (buffer->marker[type].active) 8215 buffer->size = buffer->marker[type].offset; 8216 else buffer->size = buffer->memory.size; 8217 buffer->marker[type].active = nk_false; 8218 } else { 8219 /* reset front buffer either back to back marker or empty */ 8220 buffer->needed -= (buffer->allocated - buffer->marker[type].offset); 8221 if (buffer->marker[type].active) 8222 buffer->allocated = buffer->marker[type].offset; 8223 else buffer->allocated = 0; 8224 buffer->marker[type].active = nk_false; 8225 } 8226} 8227NK_API void 8228nk_buffer_clear(struct nk_buffer *b) 8229{ 8230 NK_ASSERT(b); 8231 if (!b) return; 8232 b->allocated = 0; 8233 b->size = b->memory.size; 8234 b->calls = 0; 8235 b->needed = 0; 8236} 8237NK_API void 8238nk_buffer_free(struct nk_buffer *b) 8239{ 8240 NK_ASSERT(b); 8241 if (!b || !b->memory.ptr) return; 8242 if (b->type == NK_BUFFER_FIXED) return; 8243 if (!b->pool.free) return; 8244 NK_ASSERT(b->pool.free); 8245 b->pool.free(b->pool.userdata, b->memory.ptr); 8246} 8247NK_API void 8248nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b) 8249{ 8250 NK_ASSERT(b); 8251 NK_ASSERT(s); 8252 if (!s || !b) return; 8253 s->allocated = b->allocated; 8254 s->size = b->memory.size; 8255 s->needed = b->needed; 8256 s->memory = b->memory.ptr; 8257 s->calls = b->calls; 8258} 8259NK_API void* 8260nk_buffer_memory(struct nk_buffer *buffer) 8261{ 8262 NK_ASSERT(buffer); 8263 if (!buffer) return 0; 8264 return buffer->memory.ptr; 8265} 8266NK_API const void* 8267nk_buffer_memory_const(const struct nk_buffer *buffer) 8268{ 8269 NK_ASSERT(buffer); 8270 if (!buffer) return 0; 8271 return buffer->memory.ptr; 8272} 8273NK_API nk_size 8274nk_buffer_total(struct nk_buffer *buffer) 8275{ 8276 NK_ASSERT(buffer); 8277 if (!buffer) return 0; 8278 return buffer->memory.size; 8279} 8280 8281 8282 8283 8284 8285/* =============================================================== 8286 * 8287 * STRING 8288 * 8289 * ===============================================================*/ 8290#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8291NK_API void 8292nk_str_init_default(struct nk_str *str) 8293{ 8294 struct nk_allocator alloc; 8295 alloc.userdata.ptr = 0; 8296 alloc.alloc = nk_malloc; 8297 alloc.free = nk_mfree; 8298 nk_buffer_init(&str->buffer, &alloc, 32); 8299 str->len = 0; 8300} 8301#endif 8302 8303NK_API void 8304nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size) 8305{ 8306 nk_buffer_init(&str->buffer, alloc, size); 8307 str->len = 0; 8308} 8309NK_API void 8310nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size) 8311{ 8312 nk_buffer_init_fixed(&str->buffer, memory, size); 8313 str->len = 0; 8314} 8315NK_API int 8316nk_str_append_text_char(struct nk_str *s, const char *str, int len) 8317{ 8318 char *mem; 8319 NK_ASSERT(s); 8320 NK_ASSERT(str); 8321 if (!s || !str || !len) return 0; 8322 mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8323 if (!mem) return 0; 8324 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8325 s->len += nk_utf_len(str, len); 8326 return len; 8327} 8328NK_API int 8329nk_str_append_str_char(struct nk_str *s, const char *str) 8330{ 8331 return nk_str_append_text_char(s, str, nk_strlen(str)); 8332} 8333NK_API int 8334nk_str_append_text_utf8(struct nk_str *str, const char *text, int len) 8335{ 8336 int i = 0; 8337 int byte_len = 0; 8338 nk_rune unicode; 8339 if (!str || !text || !len) return 0; 8340 for (i = 0; i < len; ++i) 8341 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8342 nk_str_append_text_char(str, text, byte_len); 8343 return len; 8344} 8345NK_API int 8346nk_str_append_str_utf8(struct nk_str *str, const char *text) 8347{ 8348 int runes = 0; 8349 int byte_len = 0; 8350 int num_runes = 0; 8351 int glyph_len = 0; 8352 nk_rune unicode; 8353 if (!str || !text) return 0; 8354 8355 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8356 while (unicode != '\0' && glyph_len) { 8357 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8358 byte_len += glyph_len; 8359 num_runes++; 8360 } 8361 nk_str_append_text_char(str, text, byte_len); 8362 return runes; 8363} 8364NK_API int 8365nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) 8366{ 8367 int i = 0; 8368 int byte_len = 0; 8369 nk_glyph glyph; 8370 8371 NK_ASSERT(str); 8372 if (!str || !text || !len) return 0; 8373 for (i = 0; i < len; ++i) { 8374 byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE); 8375 if (!byte_len) break; 8376 nk_str_append_text_char(str, glyph, byte_len); 8377 } 8378 return len; 8379} 8380NK_API int 8381nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes) 8382{ 8383 int i = 0; 8384 nk_glyph glyph; 8385 int byte_len; 8386 NK_ASSERT(str); 8387 if (!str || !runes) return 0; 8388 while (runes[i] != '\0') { 8389 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8390 nk_str_append_text_char(str, glyph, byte_len); 8391 i++; 8392 } 8393 return i; 8394} 8395NK_API int 8396nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len) 8397{ 8398 int i; 8399 void *mem; 8400 char *src; 8401 char *dst; 8402 8403 int copylen; 8404 NK_ASSERT(s); 8405 NK_ASSERT(str); 8406 NK_ASSERT(len >= 0); 8407 if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0; 8408 if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) && 8409 (s->buffer.type == NK_BUFFER_FIXED)) return 0; 8410 8411 copylen = (int)s->buffer.allocated - pos; 8412 if (!copylen) { 8413 nk_str_append_text_char(s, str, len); 8414 return 1; 8415 } 8416 mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8417 if (!mem) return 0; 8418 8419 /* memmove */ 8420 NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0); 8421 NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0); 8422 dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1)); 8423 src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1)); 8424 for (i = 0; i < copylen; ++i) *dst-- = *src--; 8425 mem = nk_ptr_add(void, s->buffer.memory.ptr, pos); 8426 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8427 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8428 return 1; 8429} 8430NK_API int 8431nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len) 8432{ 8433 int glyph_len; 8434 nk_rune unicode; 8435 const char *begin; 8436 const char *buffer; 8437 8438 NK_ASSERT(str); 8439 NK_ASSERT(cstr); 8440 NK_ASSERT(len); 8441 if (!str || !cstr || !len) return 0; 8442 begin = nk_str_at_rune(str, pos, &unicode, &glyph_len); 8443 if (!str->len) 8444 return nk_str_append_text_char(str, cstr, len); 8445 buffer = nk_str_get_const(str); 8446 if (!begin) return 0; 8447 return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len); 8448} 8449NK_API int 8450nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len) 8451{ 8452 return nk_str_insert_text_utf8(str, pos, text, len); 8453} 8454NK_API int 8455nk_str_insert_str_char(struct nk_str *str, int pos, const char *text) 8456{ 8457 return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text)); 8458} 8459NK_API int 8460nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len) 8461{ 8462 int i = 0; 8463 int byte_len = 0; 8464 nk_rune unicode; 8465 8466 NK_ASSERT(str); 8467 NK_ASSERT(text); 8468 if (!str || !text || !len) return 0; 8469 for (i = 0; i < len; ++i) 8470 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8471 nk_str_insert_at_rune(str, pos, text, byte_len); 8472 return len; 8473} 8474NK_API int 8475nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) 8476{ 8477 int runes = 0; 8478 int byte_len = 0; 8479 int num_runes = 0; 8480 int glyph_len = 0; 8481 nk_rune unicode; 8482 if (!str || !text) return 0; 8483 8484 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8485 while (unicode != '\0' && glyph_len) { 8486 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8487 byte_len += glyph_len; 8488 num_runes++; 8489 } 8490 nk_str_insert_at_rune(str, pos, text, byte_len); 8491 return runes; 8492} 8493NK_API int 8494nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) 8495{ 8496 int i = 0; 8497 int byte_len = 0; 8498 nk_glyph glyph; 8499 8500 NK_ASSERT(str); 8501 if (!str || !runes || !len) return 0; 8502 for (i = 0; i < len; ++i) { 8503 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8504 if (!byte_len) break; 8505 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8506 } 8507 return len; 8508} 8509NK_API int 8510nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes) 8511{ 8512 int i = 0; 8513 nk_glyph glyph; 8514 int byte_len; 8515 NK_ASSERT(str); 8516 if (!str || !runes) return 0; 8517 while (runes[i] != '\0') { 8518 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8519 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8520 i++; 8521 } 8522 return i; 8523} 8524NK_API void 8525nk_str_remove_chars(struct nk_str *s, int len) 8526{ 8527 NK_ASSERT(s); 8528 NK_ASSERT(len >= 0); 8529 if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return; 8530 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8531 s->buffer.allocated -= (nk_size)len; 8532 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8533} 8534NK_API void 8535nk_str_remove_runes(struct nk_str *str, int len) 8536{ 8537 int index; 8538 const char *begin; 8539 const char *end; 8540 nk_rune unicode; 8541 8542 NK_ASSERT(str); 8543 NK_ASSERT(len >= 0); 8544 if (!str || len < 0) return; 8545 if (len >= str->len) { 8546 str->len = 0; 8547 return; 8548 } 8549 8550 index = str->len - len; 8551 begin = nk_str_at_rune(str, index, &unicode, &len); 8552 end = (const char*)str->buffer.memory.ptr + str->buffer.allocated; 8553 nk_str_remove_chars(str, (int)(end-begin)+1); 8554} 8555NK_API void 8556nk_str_delete_chars(struct nk_str *s, int pos, int len) 8557{ 8558 NK_ASSERT(s); 8559 if (!s || !len || (nk_size)pos > s->buffer.allocated || 8560 (nk_size)(pos + len) > s->buffer.allocated) return; 8561 8562 if ((nk_size)(pos + len) < s->buffer.allocated) { 8563 /* memmove */ 8564 char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos); 8565 char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len); 8566 NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len)); 8567 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8568 s->buffer.allocated -= (nk_size)len; 8569 } else nk_str_remove_chars(s, len); 8570 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8571} 8572NK_API void 8573nk_str_delete_runes(struct nk_str *s, int pos, int len) 8574{ 8575 char *temp; 8576 nk_rune unicode; 8577 char *begin; 8578 char *end; 8579 int unused; 8580 8581 NK_ASSERT(s); 8582 NK_ASSERT(s->len >= pos + len); 8583 if (s->len < pos + len) 8584 len = NK_CLAMP(0, (s->len - pos), s->len); 8585 if (!len) return; 8586 8587 temp = (char *)s->buffer.memory.ptr; 8588 begin = nk_str_at_rune(s, pos, &unicode, &unused); 8589 if (!begin) return; 8590 s->buffer.memory.ptr = begin; 8591 end = nk_str_at_rune(s, len, &unicode, &unused); 8592 s->buffer.memory.ptr = temp; 8593 if (!end) return; 8594 nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin)); 8595} 8596NK_API char* 8597nk_str_at_char(struct nk_str *s, int pos) 8598{ 8599 NK_ASSERT(s); 8600 if (!s || pos > (int)s->buffer.allocated) return 0; 8601 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8602} 8603NK_API char* 8604nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len) 8605{ 8606 int i = 0; 8607 int src_len = 0; 8608 int glyph_len = 0; 8609 char *text; 8610 int text_len; 8611 8612 NK_ASSERT(str); 8613 NK_ASSERT(unicode); 8614 NK_ASSERT(len); 8615 8616 if (!str || !unicode || !len) return 0; 8617 if (pos < 0) { 8618 *unicode = 0; 8619 *len = 0; 8620 return 0; 8621 } 8622 8623 text = (char*)str->buffer.memory.ptr; 8624 text_len = (int)str->buffer.allocated; 8625 glyph_len = nk_utf_decode(text, unicode, text_len); 8626 while (glyph_len) { 8627 if (i == pos) { 8628 *len = glyph_len; 8629 break; 8630 } 8631 8632 i++; 8633 src_len = src_len + glyph_len; 8634 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8635 } 8636 if (i != pos) return 0; 8637 return text + src_len; 8638} 8639NK_API const char* 8640nk_str_at_char_const(const struct nk_str *s, int pos) 8641{ 8642 NK_ASSERT(s); 8643 if (!s || pos > (int)s->buffer.allocated) return 0; 8644 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8645} 8646NK_API const char* 8647nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len) 8648{ 8649 int i = 0; 8650 int src_len = 0; 8651 int glyph_len = 0; 8652 char *text; 8653 int text_len; 8654 8655 NK_ASSERT(str); 8656 NK_ASSERT(unicode); 8657 NK_ASSERT(len); 8658 8659 if (!str || !unicode || !len) return 0; 8660 if (pos < 0) { 8661 *unicode = 0; 8662 *len = 0; 8663 return 0; 8664 } 8665 8666 text = (char*)str->buffer.memory.ptr; 8667 text_len = (int)str->buffer.allocated; 8668 glyph_len = nk_utf_decode(text, unicode, text_len); 8669 while (glyph_len) { 8670 if (i == pos) { 8671 *len = glyph_len; 8672 break; 8673 } 8674 8675 i++; 8676 src_len = src_len + glyph_len; 8677 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8678 } 8679 if (i != pos) return 0; 8680 return text + src_len; 8681} 8682NK_API nk_rune 8683nk_str_rune_at(const struct nk_str *str, int pos) 8684{ 8685 int len; 8686 nk_rune unicode = 0; 8687 nk_str_at_const(str, pos, &unicode, &len); 8688 return unicode; 8689} 8690NK_API char* 8691nk_str_get(struct nk_str *s) 8692{ 8693 NK_ASSERT(s); 8694 if (!s || !s->len || !s->buffer.allocated) return 0; 8695 return (char*)s->buffer.memory.ptr; 8696} 8697NK_API const char* 8698nk_str_get_const(const struct nk_str *s) 8699{ 8700 NK_ASSERT(s); 8701 if (!s || !s->len || !s->buffer.allocated) return 0; 8702 return (const char*)s->buffer.memory.ptr; 8703} 8704NK_API int 8705nk_str_len(struct nk_str *s) 8706{ 8707 NK_ASSERT(s); 8708 if (!s || !s->len || !s->buffer.allocated) return 0; 8709 return s->len; 8710} 8711NK_API int 8712nk_str_len_char(struct nk_str *s) 8713{ 8714 NK_ASSERT(s); 8715 if (!s || !s->len || !s->buffer.allocated) return 0; 8716 return (int)s->buffer.allocated; 8717} 8718NK_API void 8719nk_str_clear(struct nk_str *str) 8720{ 8721 NK_ASSERT(str); 8722 nk_buffer_clear(&str->buffer); 8723 str->len = 0; 8724} 8725NK_API void 8726nk_str_free(struct nk_str *str) 8727{ 8728 NK_ASSERT(str); 8729 nk_buffer_free(&str->buffer); 8730 str->len = 0; 8731} 8732 8733 8734 8735 8736 8737/* ============================================================== 8738 * 8739 * DRAW 8740 * 8741 * ===============================================================*/ 8742NK_LIB void 8743nk_command_buffer_init(struct nk_command_buffer *cb, 8744 struct nk_buffer *b, enum nk_command_clipping clip) 8745{ 8746 NK_ASSERT(cb); 8747 NK_ASSERT(b); 8748 if (!cb || !b) return; 8749 cb->base = b; 8750 cb->use_clipping = (int)clip; 8751 cb->begin = b->allocated; 8752 cb->end = b->allocated; 8753 cb->last = b->allocated; 8754} 8755NK_LIB void 8756nk_command_buffer_reset(struct nk_command_buffer *b) 8757{ 8758 NK_ASSERT(b); 8759 if (!b) return; 8760 b->begin = 0; 8761 b->end = 0; 8762 b->last = 0; 8763 b->clip = nk_null_rect; 8764#ifdef NK_INCLUDE_COMMAND_USERDATA 8765 b->userdata.ptr = 0; 8766#endif 8767} 8768NK_LIB void* 8769nk_command_buffer_push(struct nk_command_buffer* b, 8770 enum nk_command_type t, nk_size size) 8771{ 8772 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command); 8773 struct nk_command *cmd; 8774 nk_size alignment; 8775 void *unaligned; 8776 void *memory; 8777 8778 NK_ASSERT(b); 8779 NK_ASSERT(b->base); 8780 if (!b) return 0; 8781 cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align); 8782 if (!cmd) return 0; 8783 8784 /* make sure the offset to the next command is aligned */ 8785 b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr); 8786 unaligned = (nk_byte*)cmd + size; 8787 memory = NK_ALIGN_PTR(unaligned, align); 8788 alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8789#ifdef NK_ZERO_COMMAND_MEMORY 8790 NK_MEMSET(cmd, 0, size + alignment); 8791#endif 8792 8793 cmd->type = t; 8794 cmd->next = b->base->allocated + alignment; 8795#ifdef NK_INCLUDE_COMMAND_USERDATA 8796 cmd->userdata = b->userdata; 8797#endif 8798 b->end = cmd->next; 8799 return cmd; 8800} 8801NK_API void 8802nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r) 8803{ 8804 struct nk_command_scissor *cmd; 8805 NK_ASSERT(b); 8806 if (!b) return; 8807 8808 b->clip.x = r.x; 8809 b->clip.y = r.y; 8810 b->clip.w = r.w; 8811 b->clip.h = r.h; 8812 cmd = (struct nk_command_scissor*) 8813 nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd)); 8814 8815 if (!cmd) return; 8816 cmd->x = (short)r.x; 8817 cmd->y = (short)r.y; 8818 cmd->w = (unsigned short)NK_MAX(0, r.w); 8819 cmd->h = (unsigned short)NK_MAX(0, r.h); 8820} 8821NK_API void 8822nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, 8823 float x1, float y1, float line_thickness, struct nk_color c) 8824{ 8825 struct nk_command_line *cmd; 8826 NK_ASSERT(b); 8827 if (!b || line_thickness <= 0) return; 8828 cmd = (struct nk_command_line*) 8829 nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd)); 8830 if (!cmd) return; 8831 cmd->line_thickness = (unsigned short)line_thickness; 8832 cmd->begin.x = (short)x0; 8833 cmd->begin.y = (short)y0; 8834 cmd->end.x = (short)x1; 8835 cmd->end.y = (short)y1; 8836 cmd->color = c; 8837} 8838NK_API void 8839nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay, 8840 float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, 8841 float bx, float by, float line_thickness, struct nk_color col) 8842{ 8843 struct nk_command_curve *cmd; 8844 NK_ASSERT(b); 8845 if (!b || col.a == 0 || line_thickness <= 0) return; 8846 8847 cmd = (struct nk_command_curve*) 8848 nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd)); 8849 if (!cmd) return; 8850 cmd->line_thickness = (unsigned short)line_thickness; 8851 cmd->begin.x = (short)ax; 8852 cmd->begin.y = (short)ay; 8853 cmd->ctrl[0].x = (short)ctrl0x; 8854 cmd->ctrl[0].y = (short)ctrl0y; 8855 cmd->ctrl[1].x = (short)ctrl1x; 8856 cmd->ctrl[1].y = (short)ctrl1y; 8857 cmd->end.x = (short)bx; 8858 cmd->end.y = (short)by; 8859 cmd->color = col; 8860} 8861NK_API void 8862nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect, 8863 float rounding, float line_thickness, struct nk_color c) 8864{ 8865 struct nk_command_rect *cmd; 8866 NK_ASSERT(b); 8867 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return; 8868 if (b->use_clipping) { 8869 const struct nk_rect *clip = &b->clip; 8870 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8871 clip->x, clip->y, clip->w, clip->h)) return; 8872 } 8873 cmd = (struct nk_command_rect*) 8874 nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd)); 8875 if (!cmd) return; 8876 cmd->rounding = (unsigned short)rounding; 8877 cmd->line_thickness = (unsigned short)line_thickness; 8878 cmd->x = (short)rect.x; 8879 cmd->y = (short)rect.y; 8880 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8881 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8882 cmd->color = c; 8883} 8884NK_API void 8885nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect, 8886 float rounding, struct nk_color c) 8887{ 8888 struct nk_command_rect_filled *cmd; 8889 NK_ASSERT(b); 8890 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; 8891 if (b->use_clipping) { 8892 const struct nk_rect *clip = &b->clip; 8893 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8894 clip->x, clip->y, clip->w, clip->h)) return; 8895 } 8896 8897 cmd = (struct nk_command_rect_filled*) 8898 nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd)); 8899 if (!cmd) return; 8900 cmd->rounding = (unsigned short)rounding; 8901 cmd->x = (short)rect.x; 8902 cmd->y = (short)rect.y; 8903 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8904 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8905 cmd->color = c; 8906} 8907NK_API void 8908nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect, 8909 struct nk_color left, struct nk_color top, struct nk_color right, 8910 struct nk_color bottom) 8911{ 8912 struct nk_command_rect_multi_color *cmd; 8913 NK_ASSERT(b); 8914 if (!b || rect.w == 0 || rect.h == 0) return; 8915 if (b->use_clipping) { 8916 const struct nk_rect *clip = &b->clip; 8917 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8918 clip->x, clip->y, clip->w, clip->h)) return; 8919 } 8920 8921 cmd = (struct nk_command_rect_multi_color*) 8922 nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd)); 8923 if (!cmd) return; 8924 cmd->x = (short)rect.x; 8925 cmd->y = (short)rect.y; 8926 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8927 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8928 cmd->left = left; 8929 cmd->top = top; 8930 cmd->right = right; 8931 cmd->bottom = bottom; 8932} 8933NK_API void 8934nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r, 8935 float line_thickness, struct nk_color c) 8936{ 8937 struct nk_command_circle *cmd; 8938 if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return; 8939 if (b->use_clipping) { 8940 const struct nk_rect *clip = &b->clip; 8941 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 8942 return; 8943 } 8944 8945 cmd = (struct nk_command_circle*) 8946 nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd)); 8947 if (!cmd) return; 8948 cmd->line_thickness = (unsigned short)line_thickness; 8949 cmd->x = (short)r.x; 8950 cmd->y = (short)r.y; 8951 cmd->w = (unsigned short)NK_MAX(r.w, 0); 8952 cmd->h = (unsigned short)NK_MAX(r.h, 0); 8953 cmd->color = c; 8954} 8955NK_API void 8956nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c) 8957{ 8958 struct nk_command_circle_filled *cmd; 8959 NK_ASSERT(b); 8960 if (!b || c.a == 0 || r.w == 0 || r.h == 0) return; 8961 if (b->use_clipping) { 8962 const struct nk_rect *clip = &b->clip; 8963 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 8964 return; 8965 } 8966 8967 cmd = (struct nk_command_circle_filled*) 8968 nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); 8969 if (!cmd) return; 8970 cmd->x = (short)r.x; 8971 cmd->y = (short)r.y; 8972 cmd->w = (unsigned short)NK_MAX(r.w, 0); 8973 cmd->h = (unsigned short)NK_MAX(r.h, 0); 8974 cmd->color = c; 8975} 8976NK_API void 8977nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 8978 float a_min, float a_max, float line_thickness, struct nk_color c) 8979{ 8980 struct nk_command_arc *cmd; 8981 if (!b || c.a == 0 || line_thickness <= 0) return; 8982 cmd = (struct nk_command_arc*) 8983 nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd)); 8984 if (!cmd) return; 8985 cmd->line_thickness = (unsigned short)line_thickness; 8986 cmd->cx = (short)cx; 8987 cmd->cy = (short)cy; 8988 cmd->r = (unsigned short)radius; 8989 cmd->a[0] = a_min; 8990 cmd->a[1] = a_max; 8991 cmd->color = c; 8992} 8993NK_API void 8994nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 8995 float a_min, float a_max, struct nk_color c) 8996{ 8997 struct nk_command_arc_filled *cmd; 8998 NK_ASSERT(b); 8999 if (!b || c.a == 0) return; 9000 cmd = (struct nk_command_arc_filled*) 9001 nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd)); 9002 if (!cmd) return; 9003 cmd->cx = (short)cx; 9004 cmd->cy = (short)cy; 9005 cmd->r = (unsigned short)radius; 9006 cmd->a[0] = a_min; 9007 cmd->a[1] = a_max; 9008 cmd->color = c; 9009} 9010NK_API void 9011nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 9012 float y1, float x2, float y2, float line_thickness, struct nk_color c) 9013{ 9014 struct nk_command_triangle *cmd; 9015 NK_ASSERT(b); 9016 if (!b || c.a == 0 || line_thickness <= 0) return; 9017 if (b->use_clipping) { 9018 const struct nk_rect *clip = &b->clip; 9019 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 9020 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 9021 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 9022 return; 9023 } 9024 9025 cmd = (struct nk_command_triangle*) 9026 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd)); 9027 if (!cmd) return; 9028 cmd->line_thickness = (unsigned short)line_thickness; 9029 cmd->a.x = (short)x0; 9030 cmd->a.y = (short)y0; 9031 cmd->b.x = (short)x1; 9032 cmd->b.y = (short)y1; 9033 cmd->c.x = (short)x2; 9034 cmd->c.y = (short)y2; 9035 cmd->color = c; 9036} 9037NK_API void 9038nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 9039 float y1, float x2, float y2, struct nk_color c) 9040{ 9041 struct nk_command_triangle_filled *cmd; 9042 NK_ASSERT(b); 9043 if (!b || c.a == 0) return; 9044 if (!b) return; 9045 if (b->use_clipping) { 9046 const struct nk_rect *clip = &b->clip; 9047 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 9048 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 9049 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 9050 return; 9051 } 9052 9053 cmd = (struct nk_command_triangle_filled*) 9054 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); 9055 if (!cmd) return; 9056 cmd->a.x = (short)x0; 9057 cmd->a.y = (short)y0; 9058 cmd->b.x = (short)x1; 9059 cmd->b.y = (short)y1; 9060 cmd->c.x = (short)x2; 9061 cmd->c.y = (short)y2; 9062 cmd->color = c; 9063} 9064NK_API void 9065nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count, 9066 float line_thickness, struct nk_color col) 9067{ 9068 int i; 9069 nk_size size = 0; 9070 struct nk_command_polygon *cmd; 9071 9072 NK_ASSERT(b); 9073 if (!b || col.a == 0 || line_thickness <= 0) return; 9074 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9075 cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size); 9076 if (!cmd) return; 9077 cmd->color = col; 9078 cmd->line_thickness = (unsigned short)line_thickness; 9079 cmd->point_count = (unsigned short)point_count; 9080 for (i = 0; i < point_count; ++i) { 9081 cmd->points[i].x = (short)points[i*2]; 9082 cmd->points[i].y = (short)points[i*2+1]; 9083 } 9084} 9085NK_API void 9086nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count, 9087 struct nk_color col) 9088{ 9089 int i; 9090 nk_size size = 0; 9091 struct nk_command_polygon_filled *cmd; 9092 9093 NK_ASSERT(b); 9094 if (!b || col.a == 0) return; 9095 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9096 cmd = (struct nk_command_polygon_filled*) 9097 nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size); 9098 if (!cmd) return; 9099 cmd->color = col; 9100 cmd->point_count = (unsigned short)point_count; 9101 for (i = 0; i < point_count; ++i) { 9102 cmd->points[i].x = (short)points[i*2+0]; 9103 cmd->points[i].y = (short)points[i*2+1]; 9104 } 9105} 9106NK_API void 9107nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count, 9108 float line_thickness, struct nk_color col) 9109{ 9110 int i; 9111 nk_size size = 0; 9112 struct nk_command_polyline *cmd; 9113 9114 NK_ASSERT(b); 9115 if (!b || col.a == 0 || line_thickness <= 0) return; 9116 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9117 cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size); 9118 if (!cmd) return; 9119 cmd->color = col; 9120 cmd->point_count = (unsigned short)point_count; 9121 cmd->line_thickness = (unsigned short)line_thickness; 9122 for (i = 0; i < point_count; ++i) { 9123 cmd->points[i].x = (short)points[i*2]; 9124 cmd->points[i].y = (short)points[i*2+1]; 9125 } 9126} 9127NK_API void 9128nk_draw_image(struct nk_command_buffer *b, struct nk_rect r, 9129 const struct nk_image *img, struct nk_color col) 9130{ 9131 struct nk_command_image *cmd; 9132 NK_ASSERT(b); 9133 if (!b) return; 9134 if (b->use_clipping) { 9135 const struct nk_rect *c = &b->clip; 9136 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)) 9137 return; 9138 } 9139 9140 cmd = (struct nk_command_image*) 9141 nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd)); 9142 if (!cmd) return; 9143 cmd->x = (short)r.x; 9144 cmd->y = (short)r.y; 9145 cmd->w = (unsigned short)NK_MAX(0, r.w); 9146 cmd->h = (unsigned short)NK_MAX(0, r.h); 9147 cmd->img = *img; 9148 cmd->col = col; 9149} 9150NK_API void 9151nk_push_custom(struct nk_command_buffer *b, struct nk_rect r, 9152 nk_command_custom_callback cb, nk_handle usr) 9153{ 9154 struct nk_command_custom *cmd; 9155 NK_ASSERT(b); 9156 if (!b) return; 9157 if (b->use_clipping) { 9158 const struct nk_rect *c = &b->clip; 9159 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)) 9160 return; 9161 } 9162 9163 cmd = (struct nk_command_custom*) 9164 nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd)); 9165 if (!cmd) return; 9166 cmd->x = (short)r.x; 9167 cmd->y = (short)r.y; 9168 cmd->w = (unsigned short)NK_MAX(0, r.w); 9169 cmd->h = (unsigned short)NK_MAX(0, r.h); 9170 cmd->callback_data = usr; 9171 cmd->callback = cb; 9172} 9173NK_API void 9174nk_draw_text(struct nk_command_buffer *b, struct nk_rect r, 9175 const char *string, int length, const struct nk_user_font *font, 9176 struct nk_color bg, struct nk_color fg) 9177{ 9178 float text_width = 0; 9179 struct nk_command_text *cmd; 9180 9181 NK_ASSERT(b); 9182 NK_ASSERT(font); 9183 if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; 9184 if (b->use_clipping) { 9185 const struct nk_rect *c = &b->clip; 9186 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)) 9187 return; 9188 } 9189 9190 /* make sure text fits inside bounds */ 9191 text_width = font->width(font->userdata, font->height, string, length); 9192 if (text_width > r.w){ 9193 int glyphs = 0; 9194 float txt_width = (float)text_width; 9195 length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0); 9196 } 9197 9198 if (!length) return; 9199 cmd = (struct nk_command_text*) 9200 nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1)); 9201 if (!cmd) return; 9202 cmd->x = (short)r.x; 9203 cmd->y = (short)r.y; 9204 cmd->w = (unsigned short)r.w; 9205 cmd->h = (unsigned short)r.h; 9206 cmd->background = bg; 9207 cmd->foreground = fg; 9208 cmd->font = font; 9209 cmd->length = length; 9210 cmd->height = font->height; 9211 NK_MEMCPY(cmd->string, string, (nk_size)length); 9212 cmd->string[length] = '\0'; 9213} 9214 9215 9216 9217 9218 9219/* =============================================================== 9220 * 9221 * VERTEX 9222 * 9223 * ===============================================================*/ 9224#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 9225NK_API void 9226nk_draw_list_init(struct nk_draw_list *list) 9227{ 9228 nk_size i = 0; 9229 NK_ASSERT(list); 9230 if (!list) return; 9231 nk_zero(list, sizeof(*list)); 9232 for (i = 0; i < NK_LEN(list->circle_vtx); ++i) { 9233 const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI; 9234 list->circle_vtx[i].x = (float)NK_COS(a); 9235 list->circle_vtx[i].y = (float)NK_SIN(a); 9236 } 9237} 9238NK_API void 9239nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config, 9240 struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, 9241 enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa) 9242{ 9243 NK_ASSERT(canvas); 9244 NK_ASSERT(config); 9245 NK_ASSERT(cmds); 9246 NK_ASSERT(vertices); 9247 NK_ASSERT(elements); 9248 if (!canvas || !config || !cmds || !vertices || !elements) 9249 return; 9250 9251 canvas->buffer = cmds; 9252 canvas->config = *config; 9253 canvas->elements = elements; 9254 canvas->vertices = vertices; 9255 canvas->line_AA = line_aa; 9256 canvas->shape_AA = shape_aa; 9257 canvas->clip_rect = nk_null_rect; 9258 9259 canvas->cmd_offset = 0; 9260 canvas->element_count = 0; 9261 canvas->vertex_count = 0; 9262 canvas->cmd_offset = 0; 9263 canvas->cmd_count = 0; 9264 canvas->path_count = 0; 9265} 9266NK_API const struct nk_draw_command* 9267nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9268{ 9269 nk_byte *memory; 9270 nk_size offset; 9271 const struct nk_draw_command *cmd; 9272 9273 NK_ASSERT(buffer); 9274 if (!buffer || !buffer->size || !canvas->cmd_count) 9275 return 0; 9276 9277 memory = (nk_byte*)buffer->memory.ptr; 9278 offset = buffer->memory.size - canvas->cmd_offset; 9279 cmd = nk_ptr_add(const struct nk_draw_command, memory, offset); 9280 return cmd; 9281} 9282NK_API const struct nk_draw_command* 9283nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9284{ 9285 nk_size size; 9286 nk_size offset; 9287 nk_byte *memory; 9288 const struct nk_draw_command *end; 9289 9290 NK_ASSERT(buffer); 9291 NK_ASSERT(canvas); 9292 if (!buffer || !canvas) 9293 return 0; 9294 9295 memory = (nk_byte*)buffer->memory.ptr; 9296 size = buffer->memory.size; 9297 offset = size - canvas->cmd_offset; 9298 end = nk_ptr_add(const struct nk_draw_command, memory, offset); 9299 end -= (canvas->cmd_count-1); 9300 return end; 9301} 9302NK_API const struct nk_draw_command* 9303nk__draw_list_next(const struct nk_draw_command *cmd, 9304 const struct nk_buffer *buffer, const struct nk_draw_list *canvas) 9305{ 9306 const struct nk_draw_command *end; 9307 NK_ASSERT(buffer); 9308 NK_ASSERT(canvas); 9309 if (!cmd || !buffer || !canvas) 9310 return 0; 9311 9312 end = nk__draw_list_end(canvas, buffer); 9313 if (cmd <= end) return 0; 9314 return (cmd-1); 9315} 9316NK_INTERN struct nk_vec2* 9317nk_draw_list_alloc_path(struct nk_draw_list *list, int count) 9318{ 9319 struct nk_vec2 *points; 9320 NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2); 9321 NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2); 9322 points = (struct nk_vec2*) 9323 nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT, 9324 point_size * (nk_size)count, point_align); 9325 9326 if (!points) return 0; 9327 if (!list->path_offset) { 9328 void *memory = nk_buffer_memory(list->buffer); 9329 list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory); 9330 } 9331 list->path_count += (unsigned int)count; 9332 return points; 9333} 9334NK_INTERN struct nk_vec2 9335nk_draw_list_path_last(struct nk_draw_list *list) 9336{ 9337 void *memory; 9338 struct nk_vec2 *point; 9339 NK_ASSERT(list->path_count); 9340 memory = nk_buffer_memory(list->buffer); 9341 point = nk_ptr_add(struct nk_vec2, memory, list->path_offset); 9342 point += (list->path_count-1); 9343 return *point; 9344} 9345NK_INTERN struct nk_draw_command* 9346nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip, 9347 nk_handle texture) 9348{ 9349 NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command); 9350 NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command); 9351 struct nk_draw_command *cmd; 9352 9353 NK_ASSERT(list); 9354 cmd = (struct nk_draw_command*) 9355 nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align); 9356 9357 if (!cmd) return 0; 9358 if (!list->cmd_count) { 9359 nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer); 9360 nk_size total = nk_buffer_total(list->buffer); 9361 memory = nk_ptr_add(nk_byte, memory, total); 9362 list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd); 9363 } 9364 9365 cmd->elem_count = 0; 9366 cmd->clip_rect = clip; 9367 cmd->texture = texture; 9368#ifdef NK_INCLUDE_COMMAND_USERDATA 9369 cmd->userdata = list->userdata; 9370#endif 9371 9372 list->cmd_count++; 9373 list->clip_rect = clip; 9374 return cmd; 9375} 9376NK_INTERN struct nk_draw_command* 9377nk_draw_list_command_last(struct nk_draw_list *list) 9378{ 9379 void *memory; 9380 nk_size size; 9381 struct nk_draw_command *cmd; 9382 NK_ASSERT(list->cmd_count); 9383 9384 memory = nk_buffer_memory(list->buffer); 9385 size = nk_buffer_total(list->buffer); 9386 cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset); 9387 return (cmd - (list->cmd_count-1)); 9388} 9389NK_INTERN void 9390nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect) 9391{ 9392 NK_ASSERT(list); 9393 if (!list) return; 9394 if (!list->cmd_count) { 9395 nk_draw_list_push_command(list, rect, list->config.null.texture); 9396 } else { 9397 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9398 if (prev->elem_count == 0) 9399 prev->clip_rect = rect; 9400 nk_draw_list_push_command(list, rect, prev->texture); 9401 } 9402} 9403NK_INTERN void 9404nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture) 9405{ 9406 NK_ASSERT(list); 9407 if (!list) return; 9408 if (!list->cmd_count) { 9409 nk_draw_list_push_command(list, nk_null_rect, texture); 9410 } else { 9411 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9412 if (prev->elem_count == 0) { 9413 prev->texture = texture; 9414 #ifdef NK_INCLUDE_COMMAND_USERDATA 9415 prev->userdata = list->userdata; 9416 #endif 9417 } else if (prev->texture.id != texture.id 9418 #ifdef NK_INCLUDE_COMMAND_USERDATA 9419 || prev->userdata.id != list->userdata.id 9420 #endif 9421 ) nk_draw_list_push_command(list, prev->clip_rect, texture); 9422 } 9423} 9424#ifdef NK_INCLUDE_COMMAND_USERDATA 9425NK_API void 9426nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata) 9427{ 9428 list->userdata = userdata; 9429} 9430#endif 9431NK_INTERN void* 9432nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) 9433{ 9434 void *vtx; 9435 NK_ASSERT(list); 9436 if (!list) return 0; 9437 vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, 9438 list->config.vertex_size*count, list->config.vertex_alignment); 9439 if (!vtx) return 0; 9440 list->vertex_count += (unsigned int)count; 9441 9442 /* This assert triggers because your are drawing a lot of stuff and nuklear 9443 * defined `nk_draw_index` as `nk_ushort` to safe space be default. 9444 * 9445 * So you reached the maximum number of indicies or rather vertexes. 9446 * To solve this issue please change typdef `nk_draw_index` to `nk_uint` 9447 * and don't forget to specify the new element size in your drawing 9448 * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements` 9449 * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`. 9450 * Sorry for the inconvenience. */ 9451 if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX && 9452 "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem")); 9453 return vtx; 9454} 9455NK_INTERN nk_draw_index* 9456nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count) 9457{ 9458 nk_draw_index *ids; 9459 struct nk_draw_command *cmd; 9460 NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index); 9461 NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index); 9462 NK_ASSERT(list); 9463 if (!list) return 0; 9464 9465 ids = (nk_draw_index*) 9466 nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align); 9467 if (!ids) return 0; 9468 cmd = nk_draw_list_command_last(list); 9469 list->element_count += (unsigned int)count; 9470 cmd->elem_count += (unsigned int)count; 9471 return ids; 9472} 9473NK_INTERN int 9474nk_draw_vertex_layout_element_is_end_of_layout( 9475 const struct nk_draw_vertex_layout_element *element) 9476{ 9477 return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT || 9478 element->format == NK_FORMAT_COUNT); 9479} 9480NK_INTERN void 9481nk_draw_vertex_color(void *attr, const float *vals, 9482 enum nk_draw_vertex_layout_format format) 9483{ 9484 /* if this triggers you tried to provide a value format for a color */ 9485 float val[4]; 9486 NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN); 9487 NK_ASSERT(format <= NK_FORMAT_COLOR_END); 9488 if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return; 9489 9490 val[0] = NK_SATURATE(vals[0]); 9491 val[1] = NK_SATURATE(vals[1]); 9492 val[2] = NK_SATURATE(vals[2]); 9493 val[3] = NK_SATURATE(vals[3]); 9494 9495 switch (format) { 9496 default: NK_ASSERT(0 && "Invalid vertex layout color format"); break; 9497 case NK_FORMAT_R8G8B8A8: 9498 case NK_FORMAT_R8G8B8: { 9499 struct nk_color col = nk_rgba_fv(val); 9500 NK_MEMCPY(attr, &col.r, sizeof(col)); 9501 } break; 9502 case NK_FORMAT_B8G8R8A8: { 9503 struct nk_color col = nk_rgba_fv(val); 9504 struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a); 9505 NK_MEMCPY(attr, &bgra, sizeof(bgra)); 9506 } break; 9507 case NK_FORMAT_R16G15B16: { 9508 nk_ushort col[3]; 9509 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9510 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9511 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9512 NK_MEMCPY(attr, col, sizeof(col)); 9513 } break; 9514 case NK_FORMAT_R16G15B16A16: { 9515 nk_ushort col[4]; 9516 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9517 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9518 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9519 col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX); 9520 NK_MEMCPY(attr, col, sizeof(col)); 9521 } break; 9522 case NK_FORMAT_R32G32B32: { 9523 nk_uint col[3]; 9524 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9525 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9526 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9527 NK_MEMCPY(attr, col, sizeof(col)); 9528 } break; 9529 case NK_FORMAT_R32G32B32A32: { 9530 nk_uint col[4]; 9531 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9532 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9533 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9534 col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX); 9535 NK_MEMCPY(attr, col, sizeof(col)); 9536 } break; 9537 case NK_FORMAT_R32G32B32A32_FLOAT: 9538 NK_MEMCPY(attr, val, sizeof(float)*4); 9539 break; 9540 case NK_FORMAT_R32G32B32A32_DOUBLE: { 9541 double col[4]; 9542 col[0] = (double)val[0]; 9543 col[1] = (double)val[1]; 9544 col[2] = (double)val[2]; 9545 col[3] = (double)val[3]; 9546 NK_MEMCPY(attr, col, sizeof(col)); 9547 } break; 9548 case NK_FORMAT_RGB32: 9549 case NK_FORMAT_RGBA32: { 9550 struct nk_color col = nk_rgba_fv(val); 9551 nk_uint color = nk_color_u32(col); 9552 NK_MEMCPY(attr, &color, sizeof(color)); 9553 } break; } 9554} 9555NK_INTERN void 9556nk_draw_vertex_element(void *dst, const float *values, int value_count, 9557 enum nk_draw_vertex_layout_format format) 9558{ 9559 int value_index; 9560 void *attribute = dst; 9561 /* if this triggers you tried to provide a color format for a value */ 9562 NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN); 9563 if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return; 9564 for (value_index = 0; value_index < value_count; ++value_index) { 9565 switch (format) { 9566 default: NK_ASSERT(0 && "invalid vertex layout format"); break; 9567 case NK_FORMAT_SCHAR: { 9568 char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX); 9569 NK_MEMCPY(attribute, &value, sizeof(value)); 9570 attribute = (void*)((char*)attribute + sizeof(char)); 9571 } break; 9572 case NK_FORMAT_SSHORT: { 9573 nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX); 9574 NK_MEMCPY(attribute, &value, sizeof(value)); 9575 attribute = (void*)((char*)attribute + sizeof(value)); 9576 } break; 9577 case NK_FORMAT_SINT: { 9578 nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX); 9579 NK_MEMCPY(attribute, &value, sizeof(value)); 9580 attribute = (void*)((char*)attribute + sizeof(nk_int)); 9581 } break; 9582 case NK_FORMAT_UCHAR: { 9583 unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX); 9584 NK_MEMCPY(attribute, &value, sizeof(value)); 9585 attribute = (void*)((char*)attribute + sizeof(unsigned char)); 9586 } break; 9587 case NK_FORMAT_USHORT: { 9588 nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX); 9589 NK_MEMCPY(attribute, &value, sizeof(value)); 9590 attribute = (void*)((char*)attribute + sizeof(value)); 9591 } break; 9592 case NK_FORMAT_UINT: { 9593 nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX); 9594 NK_MEMCPY(attribute, &value, sizeof(value)); 9595 attribute = (void*)((char*)attribute + sizeof(nk_uint)); 9596 } break; 9597 case NK_FORMAT_FLOAT: 9598 NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index])); 9599 attribute = (void*)((char*)attribute + sizeof(float)); 9600 break; 9601 case NK_FORMAT_DOUBLE: { 9602 double value = (double)values[value_index]; 9603 NK_MEMCPY(attribute, &value, sizeof(value)); 9604 attribute = (void*)((char*)attribute + sizeof(double)); 9605 } break; 9606 } 9607 } 9608} 9609NK_INTERN void* 9610nk_draw_vertex(void *dst, const struct nk_convert_config *config, 9611 struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color) 9612{ 9613 void *result = (void*)((char*)dst + config->vertex_size); 9614 const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout; 9615 while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) { 9616 void *address = (void*)((char*)dst + elem_iter->offset); 9617 switch (elem_iter->attribute) { 9618 case NK_VERTEX_ATTRIBUTE_COUNT: 9619 default: NK_ASSERT(0 && "wrong element attribute"); break; 9620 case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break; 9621 case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break; 9622 case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break; 9623 } 9624 elem_iter++; 9625 } 9626 return result; 9627} 9628NK_API void 9629nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points, 9630 const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed, 9631 float thickness, enum nk_anti_aliasing aliasing) 9632{ 9633 nk_size count; 9634 int thick_line; 9635 struct nk_colorf col; 9636 struct nk_colorf col_trans; 9637 NK_ASSERT(list); 9638 if (!list || points_count < 2) return; 9639 9640 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9641 count = points_count; 9642 if (!closed) count = points_count-1; 9643 thick_line = thickness > 1.0f; 9644 9645#ifdef NK_INCLUDE_COMMAND_USERDATA 9646 nk_draw_list_push_userdata(list, list->userdata); 9647#endif 9648 9649 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9650 nk_color_fv(&col.r, color); 9651 col_trans = col; 9652 col_trans.a = 0; 9653 9654 if (aliasing == NK_ANTI_ALIASING_ON) { 9655 /* ANTI-ALIASED STROKE */ 9656 const float AA_SIZE = 1.0f; 9657 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9658 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9659 9660 /* allocate vertices and elements */ 9661 nk_size i1 = 0; 9662 nk_size vertex_offset; 9663 nk_size index = list->vertex_count; 9664 9665 const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12); 9666 const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3); 9667 9668 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9669 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9670 9671 nk_size size; 9672 struct nk_vec2 *normals, *temp; 9673 if (!vtx || !ids) return; 9674 9675 /* temporary allocate normals + points */ 9676 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9677 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9678 size = pnt_size * ((thick_line) ? 5 : 3) * points_count; 9679 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9680 if (!normals) return; 9681 temp = normals + points_count; 9682 9683 /* make sure vertex pointer is still correct */ 9684 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9685 9686 /* calculate normals */ 9687 for (i1 = 0; i1 < count; ++i1) { 9688 const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9689 struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]); 9690 float len; 9691 9692 /* vec2 inverted length */ 9693 len = nk_vec2_len_sqr(diff); 9694 if (len != 0.0f) 9695 len = nk_inv_sqrt(len); 9696 else len = 1.0f; 9697 9698 diff = nk_vec2_muls(diff, len); 9699 normals[i1].x = diff.y; 9700 normals[i1].y = -diff.x; 9701 } 9702 9703 if (!closed) 9704 normals[points_count-1] = normals[points_count-2]; 9705 9706 if (!thick_line) { 9707 nk_size idx1, i; 9708 if (!closed) { 9709 struct nk_vec2 d; 9710 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9711 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9712 d = nk_vec2_muls(normals[points_count-1], AA_SIZE); 9713 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d); 9714 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d); 9715 } 9716 9717 /* fill elements */ 9718 idx1 = index; 9719 for (i1 = 0; i1 < count; i1++) { 9720 struct nk_vec2 dm; 9721 float dmr2; 9722 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9723 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3); 9724 9725 /* average normals */ 9726 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9727 dmr2 = dm.x * dm.x + dm.y* dm.y; 9728 if (dmr2 > 0.000001f) { 9729 float scale = 1.0f/dmr2; 9730 scale = NK_MIN(100.0f, scale); 9731 dm = nk_vec2_muls(dm, scale); 9732 } 9733 9734 dm = nk_vec2_muls(dm, AA_SIZE); 9735 temp[i2*2+0] = nk_vec2_add(points[i2], dm); 9736 temp[i2*2+1] = nk_vec2_sub(points[i2], dm); 9737 9738 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0); 9739 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9740 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0); 9741 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9742 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9743 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1); 9744 ids += 12; 9745 idx1 = idx2; 9746 } 9747 9748 /* fill vertices */ 9749 for (i = 0; i < points_count; ++i) { 9750 const struct nk_vec2 uv = list->config.null.uv; 9751 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); 9752 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); 9753 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); 9754 } 9755 } else { 9756 nk_size idx1, i; 9757 const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; 9758 if (!closed) { 9759 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE); 9760 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness); 9761 9762 temp[0] = nk_vec2_add(points[0], d1); 9763 temp[1] = nk_vec2_add(points[0], d2); 9764 temp[2] = nk_vec2_sub(points[0], d2); 9765 temp[3] = nk_vec2_sub(points[0], d1); 9766 9767 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE); 9768 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness); 9769 9770 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1); 9771 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2); 9772 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2); 9773 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1); 9774 } 9775 9776 /* add all elements */ 9777 idx1 = index; 9778 for (i1 = 0; i1 < count; ++i1) { 9779 struct nk_vec2 dm_out, dm_in; 9780 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1); 9781 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4); 9782 9783 /* average normals */ 9784 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9785 float dmr2 = dm.x * dm.x + dm.y* dm.y; 9786 if (dmr2 > 0.000001f) { 9787 float scale = 1.0f/dmr2; 9788 scale = NK_MIN(100.0f, scale); 9789 dm = nk_vec2_muls(dm, scale); 9790 } 9791 9792 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE)); 9793 dm_in = nk_vec2_muls(dm, half_inner_thickness); 9794 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out); 9795 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in); 9796 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in); 9797 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out); 9798 9799 /* add indexes */ 9800 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1); 9801 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9802 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1); 9803 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9804 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9805 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1); 9806 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2); 9807 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3); 9808 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2); 9809 ids += 18; 9810 idx1 = idx2; 9811 } 9812 9813 /* add vertices */ 9814 for (i = 0; i < points_count; ++i) { 9815 const struct nk_vec2 uv = list->config.null.uv; 9816 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); 9817 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); 9818 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); 9819 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans); 9820 } 9821 } 9822 /* free temporary normals + points */ 9823 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 9824 } else { 9825 /* NON ANTI-ALIASED STROKE */ 9826 nk_size i1 = 0; 9827 nk_size idx = list->vertex_count; 9828 const nk_size idx_count = count * 6; 9829 const nk_size vtx_count = count * 4; 9830 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9831 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9832 if (!vtx || !ids) return; 9833 9834 for (i1 = 0; i1 < count; ++i1) { 9835 float dx, dy; 9836 const struct nk_vec2 uv = list->config.null.uv; 9837 const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; 9838 const struct nk_vec2 p1 = points[i1]; 9839 const struct nk_vec2 p2 = points[i2]; 9840 struct nk_vec2 diff = nk_vec2_sub(p2, p1); 9841 float len; 9842 9843 /* vec2 inverted length */ 9844 len = nk_vec2_len_sqr(diff); 9845 if (len != 0.0f) 9846 len = nk_inv_sqrt(len); 9847 else len = 1.0f; 9848 diff = nk_vec2_muls(diff, len); 9849 9850 /* add vertices */ 9851 dx = diff.x * (thickness * 0.5f); 9852 dy = diff.y * (thickness * 0.5f); 9853 9854 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col); 9855 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col); 9856 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col); 9857 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col); 9858 9859 ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1); 9860 ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0); 9861 ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3); 9862 9863 ids += 6; 9864 idx += 4; 9865 } 9866 } 9867} 9868NK_API void 9869nk_draw_list_fill_poly_convex(struct nk_draw_list *list, 9870 const struct nk_vec2 *points, const unsigned int points_count, 9871 struct nk_color color, enum nk_anti_aliasing aliasing) 9872{ 9873 struct nk_colorf col; 9874 struct nk_colorf col_trans; 9875 9876 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9877 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9878 NK_ASSERT(list); 9879 if (!list || points_count < 3) return; 9880 9881#ifdef NK_INCLUDE_COMMAND_USERDATA 9882 nk_draw_list_push_userdata(list, list->userdata); 9883#endif 9884 9885 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9886 nk_color_fv(&col.r, color); 9887 col_trans = col; 9888 col_trans.a = 0; 9889 9890 if (aliasing == NK_ANTI_ALIASING_ON) { 9891 nk_size i = 0; 9892 nk_size i0 = 0; 9893 nk_size i1 = 0; 9894 9895 const float AA_SIZE = 1.0f; 9896 nk_size vertex_offset = 0; 9897 nk_size index = list->vertex_count; 9898 9899 const nk_size idx_count = (points_count-2)*3 + points_count*6; 9900 const nk_size vtx_count = (points_count*2); 9901 9902 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9903 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9904 9905 nk_size size = 0; 9906 struct nk_vec2 *normals = 0; 9907 unsigned int vtx_inner_idx = (unsigned int)(index + 0); 9908 unsigned int vtx_outer_idx = (unsigned int)(index + 1); 9909 if (!vtx || !ids) return; 9910 9911 /* temporary allocate normals */ 9912 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9913 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9914 size = pnt_size * points_count; 9915 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9916 if (!normals) return; 9917 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9918 9919 /* add elements */ 9920 for (i = 2; i < points_count; i++) { 9921 ids[0] = (nk_draw_index)(vtx_inner_idx); 9922 ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1)); 9923 ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1)); 9924 ids += 3; 9925 } 9926 9927 /* compute normals */ 9928 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 9929 struct nk_vec2 p0 = points[i0]; 9930 struct nk_vec2 p1 = points[i1]; 9931 struct nk_vec2 diff = nk_vec2_sub(p1, p0); 9932 9933 /* vec2 inverted length */ 9934 float len = nk_vec2_len_sqr(diff); 9935 if (len != 0.0f) 9936 len = nk_inv_sqrt(len); 9937 else len = 1.0f; 9938 diff = nk_vec2_muls(diff, len); 9939 9940 normals[i0].x = diff.y; 9941 normals[i0].y = -diff.x; 9942 } 9943 9944 /* add vertices + indexes */ 9945 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 9946 const struct nk_vec2 uv = list->config.null.uv; 9947 struct nk_vec2 n0 = normals[i0]; 9948 struct nk_vec2 n1 = normals[i1]; 9949 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); 9950 float dmr2 = dm.x*dm.x + dm.y*dm.y; 9951 if (dmr2 > 0.000001f) { 9952 float scale = 1.0f / dmr2; 9953 scale = NK_MIN(scale, 100.0f); 9954 dm = nk_vec2_muls(dm, scale); 9955 } 9956 dm = nk_vec2_muls(dm, AA_SIZE * 0.5f); 9957 9958 /* add vertices */ 9959 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col); 9960 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans); 9961 9962 /* add indexes */ 9963 ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 9964 ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1)); 9965 ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 9966 ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 9967 ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1)); 9968 ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 9969 ids += 6; 9970 } 9971 /* free temporary normals + points */ 9972 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 9973 } else { 9974 nk_size i = 0; 9975 nk_size index = list->vertex_count; 9976 const nk_size idx_count = (points_count-2)*3; 9977 const nk_size vtx_count = points_count; 9978 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9979 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9980 9981 if (!vtx || !ids) return; 9982 for (i = 0; i < vtx_count; ++i) 9983 vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col); 9984 for (i = 2; i < points_count; ++i) { 9985 ids[0] = (nk_draw_index)index; 9986 ids[1] = (nk_draw_index)(index+ i - 1); 9987 ids[2] = (nk_draw_index)(index+i); 9988 ids += 3; 9989 } 9990 } 9991} 9992NK_API void 9993nk_draw_list_path_clear(struct nk_draw_list *list) 9994{ 9995 NK_ASSERT(list); 9996 if (!list) return; 9997 nk_buffer_reset(list->buffer, NK_BUFFER_FRONT); 9998 list->path_count = 0; 9999 list->path_offset = 0; 10000} 10001NK_API void 10002nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos) 10003{ 10004 struct nk_vec2 *points = 0; 10005 struct nk_draw_command *cmd = 0; 10006 NK_ASSERT(list); 10007 if (!list) return; 10008 if (!list->cmd_count) 10009 nk_draw_list_add_clip(list, nk_null_rect); 10010 10011 cmd = nk_draw_list_command_last(list); 10012 if (cmd && cmd->texture.ptr != list->config.null.texture.ptr) 10013 nk_draw_list_push_image(list, list->config.null.texture); 10014 10015 points = nk_draw_list_alloc_path(list, 1); 10016 if (!points) return; 10017 points[0] = pos; 10018} 10019NK_API void 10020nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center, 10021 float radius, int a_min, int a_max) 10022{ 10023 int a = 0; 10024 NK_ASSERT(list); 10025 if (!list) return; 10026 if (a_min <= a_max) { 10027 for (a = a_min; a <= a_max; a++) { 10028 const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)]; 10029 const float x = center.x + c.x * radius; 10030 const float y = center.y + c.y * radius; 10031 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 10032 } 10033 } 10034} 10035NK_API void 10036nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center, 10037 float radius, float a_min, float a_max, unsigned int segments) 10038{ 10039 unsigned int i = 0; 10040 NK_ASSERT(list); 10041 if (!list) return; 10042 if (radius == 0.0f) return; 10043 10044 /* This algorithm for arc drawing relies on these two trigonometric identities[1]: 10045 sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) 10046 cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) 10047 10048 Two coordinates (x, y) of a point on a circle centered on 10049 the origin can be written in polar form as: 10050 x = r * cos(a) 10051 y = r * sin(a) 10052 where r is the radius of the circle, 10053 a is the angle between (x, y) and the origin. 10054 10055 This allows us to rotate the coordinates around the 10056 origin by an angle b using the following transformation: 10057 x' = r * cos(a + b) = x * cos(b) - y * sin(b) 10058 y' = r * sin(a + b) = y * cos(b) + x * sin(b) 10059 10060 [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities 10061 */ 10062 {const float d_angle = (a_max - a_min) / (float)segments; 10063 const float sin_d = (float)NK_SIN(d_angle); 10064 const float cos_d = (float)NK_COS(d_angle); 10065 10066 float cx = (float)NK_COS(a_min) * radius; 10067 float cy = (float)NK_SIN(a_min) * radius; 10068 for(i = 0; i <= segments; ++i) { 10069 float new_cx, new_cy; 10070 const float x = center.x + cx; 10071 const float y = center.y + cy; 10072 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 10073 10074 new_cx = cx * cos_d - cy * sin_d; 10075 new_cy = cy * cos_d + cx * sin_d; 10076 cx = new_cx; 10077 cy = new_cy; 10078 }} 10079} 10080NK_API void 10081nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a, 10082 struct nk_vec2 b, float rounding) 10083{ 10084 float r; 10085 NK_ASSERT(list); 10086 if (!list) return; 10087 r = rounding; 10088 r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x)); 10089 r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y)); 10090 10091 if (r == 0.0f) { 10092 nk_draw_list_path_line_to(list, a); 10093 nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y)); 10094 nk_draw_list_path_line_to(list, b); 10095 nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y)); 10096 } else { 10097 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9); 10098 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12); 10099 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3); 10100 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6); 10101 } 10102} 10103NK_API void 10104nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2, 10105 struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments) 10106{ 10107 float t_step; 10108 unsigned int i_step; 10109 struct nk_vec2 p1; 10110 10111 NK_ASSERT(list); 10112 NK_ASSERT(list->path_count); 10113 if (!list || !list->path_count) return; 10114 num_segments = NK_MAX(num_segments, 1); 10115 10116 p1 = nk_draw_list_path_last(list); 10117 t_step = 1.0f/(float)num_segments; 10118 for (i_step = 1; i_step <= num_segments; ++i_step) { 10119 float t = t_step * (float)i_step; 10120 float u = 1.0f - t; 10121 float w1 = u*u*u; 10122 float w2 = 3*u*u*t; 10123 float w3 = 3*u*t*t; 10124 float w4 = t * t *t; 10125 float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; 10126 float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; 10127 nk_draw_list_path_line_to(list, nk_vec2(x,y)); 10128 } 10129} 10130NK_API void 10131nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color) 10132{ 10133 struct nk_vec2 *points; 10134 NK_ASSERT(list); 10135 if (!list) return; 10136 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10137 nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA); 10138 nk_draw_list_path_clear(list); 10139} 10140NK_API void 10141nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color, 10142 enum nk_draw_list_stroke closed, float thickness) 10143{ 10144 struct nk_vec2 *points; 10145 NK_ASSERT(list); 10146 if (!list) return; 10147 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10148 nk_draw_list_stroke_poly_line(list, points, list->path_count, color, 10149 closed, thickness, list->config.line_AA); 10150 nk_draw_list_path_clear(list); 10151} 10152NK_API void 10153nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a, 10154 struct nk_vec2 b, struct nk_color col, float thickness) 10155{ 10156 NK_ASSERT(list); 10157 if (!list || !col.a) return; 10158 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10159 nk_draw_list_path_line_to(list, a); 10160 nk_draw_list_path_line_to(list, b); 10161 } else { 10162 nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f))); 10163 nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f))); 10164 } 10165 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10166} 10167NK_API void 10168nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect, 10169 struct nk_color col, float rounding) 10170{ 10171 NK_ASSERT(list); 10172 if (!list || !col.a) return; 10173 10174 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10175 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10176 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10177 } else { 10178 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10179 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10180 } nk_draw_list_path_fill(list, col); 10181} 10182NK_API void 10183nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect, 10184 struct nk_color col, float rounding, float thickness) 10185{ 10186 NK_ASSERT(list); 10187 if (!list || !col.a) return; 10188 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10189 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10190 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10191 } else { 10192 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10193 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10194 } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10195} 10196NK_API void 10197nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect, 10198 struct nk_color left, struct nk_color top, struct nk_color right, 10199 struct nk_color bottom) 10200{ 10201 void *vtx; 10202 struct nk_colorf col_left, col_top; 10203 struct nk_colorf col_right, col_bottom; 10204 nk_draw_index *idx; 10205 nk_draw_index index; 10206 10207 nk_color_fv(&col_left.r, left); 10208 nk_color_fv(&col_right.r, right); 10209 nk_color_fv(&col_top.r, top); 10210 nk_color_fv(&col_bottom.r, bottom); 10211 10212 NK_ASSERT(list); 10213 if (!list) return; 10214 10215 nk_draw_list_push_image(list, list->config.null.texture); 10216 index = (nk_draw_index)list->vertex_count; 10217 vtx = nk_draw_list_alloc_vertices(list, 4); 10218 idx = nk_draw_list_alloc_elements(list, 6); 10219 if (!vtx || !idx) return; 10220 10221 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10222 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10223 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10224 10225 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left); 10226 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top); 10227 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right); 10228 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom); 10229} 10230NK_API void 10231nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10232 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col) 10233{ 10234 NK_ASSERT(list); 10235 if (!list || !col.a) return; 10236 nk_draw_list_path_line_to(list, a); 10237 nk_draw_list_path_line_to(list, b); 10238 nk_draw_list_path_line_to(list, c); 10239 nk_draw_list_path_fill(list, col); 10240} 10241NK_API void 10242nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10243 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness) 10244{ 10245 NK_ASSERT(list); 10246 if (!list || !col.a) return; 10247 nk_draw_list_path_line_to(list, a); 10248 nk_draw_list_path_line_to(list, b); 10249 nk_draw_list_path_line_to(list, c); 10250 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10251} 10252NK_API void 10253nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center, 10254 float radius, struct nk_color col, unsigned int segs) 10255{ 10256 float a_max; 10257 NK_ASSERT(list); 10258 if (!list || !col.a) return; 10259 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10260 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10261 nk_draw_list_path_fill(list, col); 10262} 10263NK_API void 10264nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center, 10265 float radius, struct nk_color col, unsigned int segs, float thickness) 10266{ 10267 float a_max; 10268 NK_ASSERT(list); 10269 if (!list || !col.a) return; 10270 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10271 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10272 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10273} 10274NK_API void 10275nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0, 10276 struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, 10277 struct nk_color col, unsigned int segments, float thickness) 10278{ 10279 NK_ASSERT(list); 10280 if (!list || !col.a) return; 10281 nk_draw_list_path_line_to(list, p0); 10282 nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments); 10283 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10284} 10285NK_INTERN void 10286nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a, 10287 struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc, 10288 struct nk_color color) 10289{ 10290 void *vtx; 10291 struct nk_vec2 uvb; 10292 struct nk_vec2 uvd; 10293 struct nk_vec2 b; 10294 struct nk_vec2 d; 10295 10296 struct nk_colorf col; 10297 nk_draw_index *idx; 10298 nk_draw_index index; 10299 NK_ASSERT(list); 10300 if (!list) return; 10301 10302 nk_color_fv(&col.r, color); 10303 uvb = nk_vec2(uvc.x, uva.y); 10304 uvd = nk_vec2(uva.x, uvc.y); 10305 b = nk_vec2(c.x, a.y); 10306 d = nk_vec2(a.x, c.y); 10307 10308 index = (nk_draw_index)list->vertex_count; 10309 vtx = nk_draw_list_alloc_vertices(list, 4); 10310 idx = nk_draw_list_alloc_elements(list, 6); 10311 if (!vtx || !idx) return; 10312 10313 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10314 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10315 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10316 10317 vtx = nk_draw_vertex(vtx, &list->config, a, uva, col); 10318 vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col); 10319 vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col); 10320 vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col); 10321} 10322NK_API void 10323nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture, 10324 struct nk_rect rect, struct nk_color color) 10325{ 10326 NK_ASSERT(list); 10327 if (!list) return; 10328 /* push new command with given texture */ 10329 nk_draw_list_push_image(list, texture.handle); 10330 if (nk_image_is_subimage(&texture)) { 10331 /* add region inside of the texture */ 10332 struct nk_vec2 uv[2]; 10333 uv[0].x = (float)texture.region[0]/(float)texture.w; 10334 uv[0].y = (float)texture.region[1]/(float)texture.h; 10335 uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w; 10336 uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h; 10337 nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10338 nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color); 10339 } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10340 nk_vec2(rect.x + rect.w, rect.y + rect.h), 10341 nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color); 10342} 10343NK_API void 10344nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font, 10345 struct nk_rect rect, const char *text, int len, float font_height, 10346 struct nk_color fg) 10347{ 10348 float x = 0; 10349 int text_len = 0; 10350 nk_rune unicode = 0; 10351 nk_rune next = 0; 10352 int glyph_len = 0; 10353 int next_glyph_len = 0; 10354 struct nk_user_font_glyph g; 10355 10356 NK_ASSERT(list); 10357 if (!list || !len || !text) return; 10358 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 10359 list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return; 10360 10361 nk_draw_list_push_image(list, font->texture); 10362 x = rect.x; 10363 glyph_len = nk_utf_decode(text, &unicode, len); 10364 if (!glyph_len) return; 10365 10366 /* draw every glyph image */ 10367 fg.a = (nk_byte)((float)fg.a * list->config.global_alpha); 10368 while (text_len < len && glyph_len) { 10369 float gx, gy, gh, gw; 10370 float char_width = 0; 10371 if (unicode == NK_UTF_INVALID) break; 10372 10373 /* query currently drawn glyph information */ 10374 next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); 10375 font->query(font->userdata, font_height, &g, unicode, 10376 (next == NK_UTF_INVALID) ? '\0' : next); 10377 10378 /* calculate and draw glyph drawing rectangle and image */ 10379 gx = x + g.offset.x; 10380 gy = rect.y + g.offset.y; 10381 gw = g.width; gh = g.height; 10382 char_width = g.xadvance; 10383 nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh), 10384 g.uv[0], g.uv[1], fg); 10385 10386 /* offset next glyph */ 10387 text_len += glyph_len; 10388 x += char_width; 10389 glyph_len = next_glyph_len; 10390 unicode = next; 10391 } 10392} 10393NK_API nk_flags 10394nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 10395 struct nk_buffer *vertices, struct nk_buffer *elements, 10396 const struct nk_convert_config *config) 10397{ 10398 nk_flags res = NK_CONVERT_SUCCESS; 10399 const struct nk_command *cmd; 10400 NK_ASSERT(ctx); 10401 NK_ASSERT(cmds); 10402 NK_ASSERT(vertices); 10403 NK_ASSERT(elements); 10404 NK_ASSERT(config); 10405 NK_ASSERT(config->vertex_layout); 10406 NK_ASSERT(config->vertex_size); 10407 if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout) 10408 return NK_CONVERT_INVALID_PARAM; 10409 10410 nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements, 10411 config->line_AA, config->shape_AA); 10412 nk_foreach(cmd, ctx) 10413 { 10414#ifdef NK_INCLUDE_COMMAND_USERDATA 10415 ctx->draw_list.userdata = cmd->userdata; 10416#endif 10417 switch (cmd->type) { 10418 case NK_COMMAND_NOP: break; 10419 case NK_COMMAND_SCISSOR: { 10420 const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd; 10421 nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h)); 10422 } break; 10423 case NK_COMMAND_LINE: { 10424 const struct nk_command_line *l = (const struct nk_command_line*)cmd; 10425 nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y), 10426 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness); 10427 } break; 10428 case NK_COMMAND_CURVE: { 10429 const struct nk_command_curve *q = (const struct nk_command_curve*)cmd; 10430 nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y), 10431 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x, 10432 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color, 10433 config->curve_segment_count, q->line_thickness); 10434 } break; 10435 case NK_COMMAND_RECT: { 10436 const struct nk_command_rect *r = (const struct nk_command_rect*)cmd; 10437 nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10438 r->color, (float)r->rounding, r->line_thickness); 10439 } break; 10440 case NK_COMMAND_RECT_FILLED: { 10441 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd; 10442 nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10443 r->color, (float)r->rounding); 10444 } break; 10445 case NK_COMMAND_RECT_MULTI_COLOR: { 10446 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd; 10447 nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10448 r->left, r->top, r->right, r->bottom); 10449 } break; 10450 case NK_COMMAND_CIRCLE: { 10451 const struct nk_command_circle *c = (const struct nk_command_circle*)cmd; 10452 nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10453 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10454 config->circle_segment_count, c->line_thickness); 10455 } break; 10456 case NK_COMMAND_CIRCLE_FILLED: { 10457 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; 10458 nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10459 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10460 config->circle_segment_count); 10461 } break; 10462 case NK_COMMAND_ARC: { 10463 const struct nk_command_arc *c = (const struct nk_command_arc*)cmd; 10464 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10465 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10466 c->a[0], c->a[1], config->arc_segment_count); 10467 nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness); 10468 } break; 10469 case NK_COMMAND_ARC_FILLED: { 10470 const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd; 10471 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10472 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10473 c->a[0], c->a[1], config->arc_segment_count); 10474 nk_draw_list_path_fill(&ctx->draw_list, c->color); 10475 } break; 10476 case NK_COMMAND_TRIANGLE: { 10477 const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; 10478 nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10479 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color, 10480 t->line_thickness); 10481 } break; 10482 case NK_COMMAND_TRIANGLE_FILLED: { 10483 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; 10484 nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10485 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color); 10486 } break; 10487 case NK_COMMAND_POLYGON: { 10488 int i; 10489 const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd; 10490 for (i = 0; i < p->point_count; ++i) { 10491 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10492 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10493 } 10494 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness); 10495 } break; 10496 case NK_COMMAND_POLYGON_FILLED: { 10497 int i; 10498 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; 10499 for (i = 0; i < p->point_count; ++i) { 10500 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10501 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10502 } 10503 nk_draw_list_path_fill(&ctx->draw_list, p->color); 10504 } break; 10505 case NK_COMMAND_POLYLINE: { 10506 int i; 10507 const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd; 10508 for (i = 0; i < p->point_count; ++i) { 10509 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10510 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10511 } 10512 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness); 10513 } break; 10514 case NK_COMMAND_TEXT: { 10515 const struct nk_command_text *t = (const struct nk_command_text*)cmd; 10516 nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h), 10517 t->string, t->length, t->height, t->foreground); 10518 } break; 10519 case NK_COMMAND_IMAGE: { 10520 const struct nk_command_image *i = (const struct nk_command_image*)cmd; 10521 nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col); 10522 } break; 10523 case NK_COMMAND_CUSTOM: { 10524 const struct nk_command_custom *c = (const struct nk_command_custom*)cmd; 10525 c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data); 10526 } break; 10527 default: break; 10528 } 10529 } 10530 res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0; 10531 res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0; 10532 res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0; 10533 return res; 10534} 10535NK_API const struct nk_draw_command* 10536nk__draw_begin(const struct nk_context *ctx, 10537 const struct nk_buffer *buffer) 10538{ 10539 return nk__draw_list_begin(&ctx->draw_list, buffer); 10540} 10541NK_API const struct nk_draw_command* 10542nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer) 10543{ 10544 return nk__draw_list_end(&ctx->draw_list, buffer); 10545} 10546NK_API const struct nk_draw_command* 10547nk__draw_next(const struct nk_draw_command *cmd, 10548 const struct nk_buffer *buffer, const struct nk_context *ctx) 10549{ 10550 return nk__draw_list_next(cmd, buffer, &ctx->draw_list); 10551} 10552#endif 10553 10554 10555 10556 10557 10558#ifdef NK_INCLUDE_FONT_BAKING 10559/* ------------------------------------------------------------- 10560 * 10561 * RECT PACK 10562 * 10563 * --------------------------------------------------------------*/ 10564/* stb_rect_pack.h - v0.05 - public domain - rectangle packing */ 10565/* Sean Barrett 2014 */ 10566#define NK_RP__MAXVAL 0xffff 10567typedef unsigned short nk_rp_coord; 10568 10569struct nk_rp_rect { 10570 /* reserved for your use: */ 10571 int id; 10572 /* input: */ 10573 nk_rp_coord w, h; 10574 /* output: */ 10575 nk_rp_coord x, y; 10576 int was_packed; 10577 /* non-zero if valid packing */ 10578}; /* 16 bytes, nominally */ 10579 10580struct nk_rp_node { 10581 nk_rp_coord x,y; 10582 struct nk_rp_node *next; 10583}; 10584 10585struct nk_rp_context { 10586 int width; 10587 int height; 10588 int align; 10589 int init_mode; 10590 int heuristic; 10591 int num_nodes; 10592 struct nk_rp_node *active_head; 10593 struct nk_rp_node *free_head; 10594 struct nk_rp_node extra[2]; 10595 /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */ 10596}; 10597 10598struct nk_rp__findresult { 10599 int x,y; 10600 struct nk_rp_node **prev_link; 10601}; 10602 10603enum NK_RP_HEURISTIC { 10604 NK_RP_HEURISTIC_Skyline_default=0, 10605 NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default, 10606 NK_RP_HEURISTIC_Skyline_BF_sortHeight 10607}; 10608enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1}; 10609 10610NK_INTERN void 10611nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem) 10612{ 10613 if (allow_out_of_mem) 10614 /* if it's ok to run out of memory, then don't bother aligning them; */ 10615 /* this gives better packing, but may fail due to OOM (even though */ 10616 /* the rectangles easily fit). @TODO a smarter approach would be to only */ 10617 /* quantize once we've hit OOM, then we could get rid of this parameter. */ 10618 context->align = 1; 10619 else { 10620 /* if it's not ok to run out of memory, then quantize the widths */ 10621 /* so that num_nodes is always enough nodes. */ 10622 /* */ 10623 /* I.e. num_nodes * align >= width */ 10624 /* align >= width / num_nodes */ 10625 /* align = ceil(width/num_nodes) */ 10626 context->align = (context->width + context->num_nodes-1) / context->num_nodes; 10627 } 10628} 10629NK_INTERN void 10630nk_rp_init_target(struct nk_rp_context *context, int width, int height, 10631 struct nk_rp_node *nodes, int num_nodes) 10632{ 10633 int i; 10634#ifndef STBRP_LARGE_RECTS 10635 NK_ASSERT(width <= 0xffff && height <= 0xffff); 10636#endif 10637 10638 for (i=0; i < num_nodes-1; ++i) 10639 nodes[i].next = &nodes[i+1]; 10640 nodes[i].next = 0; 10641 context->init_mode = NK_RP__INIT_skyline; 10642 context->heuristic = NK_RP_HEURISTIC_Skyline_default; 10643 context->free_head = &nodes[0]; 10644 context->active_head = &context->extra[0]; 10645 context->width = width; 10646 context->height = height; 10647 context->num_nodes = num_nodes; 10648 nk_rp_setup_allow_out_of_mem(context, 0); 10649 10650 /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */ 10651 context->extra[0].x = 0; 10652 context->extra[0].y = 0; 10653 context->extra[0].next = &context->extra[1]; 10654 context->extra[1].x = (nk_rp_coord) width; 10655 context->extra[1].y = 65535; 10656 context->extra[1].next = 0; 10657} 10658/* find minimum y position if it starts at x1 */ 10659NK_INTERN int 10660nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first, 10661 int x0, int width, int *pwaste) 10662{ 10663 struct nk_rp_node *node = first; 10664 int x1 = x0 + width; 10665 int min_y, visited_width, waste_area; 10666 NK_ASSERT(first->x <= x0); 10667 NK_UNUSED(c); 10668 10669 NK_ASSERT(node->next->x > x0); 10670 /* we ended up handling this in the caller for efficiency */ 10671 NK_ASSERT(node->x <= x0); 10672 10673 min_y = 0; 10674 waste_area = 0; 10675 visited_width = 0; 10676 while (node->x < x1) 10677 { 10678 if (node->y > min_y) { 10679 /* raise min_y higher. */ 10680 /* we've accounted for all waste up to min_y, */ 10681 /* but we'll now add more waste for everything we've visited */ 10682 waste_area += visited_width * (node->y - min_y); 10683 min_y = node->y; 10684 /* the first time through, visited_width might be reduced */ 10685 if (node->x < x0) 10686 visited_width += node->next->x - x0; 10687 else 10688 visited_width += node->next->x - node->x; 10689 } else { 10690 /* add waste area */ 10691 int under_width = node->next->x - node->x; 10692 if (under_width + visited_width > width) 10693 under_width = width - visited_width; 10694 waste_area += under_width * (min_y - node->y); 10695 visited_width += under_width; 10696 } 10697 node = node->next; 10698 } 10699 *pwaste = waste_area; 10700 return min_y; 10701} 10702NK_INTERN struct nk_rp__findresult 10703nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height) 10704{ 10705 int best_waste = (1<<30), best_x, best_y = (1 << 30); 10706 struct nk_rp__findresult fr; 10707 struct nk_rp_node **prev, *node, *tail, **best = 0; 10708 10709 /* align to multiple of c->align */ 10710 width = (width + c->align - 1); 10711 width -= width % c->align; 10712 NK_ASSERT(width % c->align == 0); 10713 10714 node = c->active_head; 10715 prev = &c->active_head; 10716 while (node->x + width <= c->width) { 10717 int y,waste; 10718 y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste); 10719 /* actually just want to test BL */ 10720 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) { 10721 /* bottom left */ 10722 if (y < best_y) { 10723 best_y = y; 10724 best = prev; 10725 } 10726 } else { 10727 /* best-fit */ 10728 if (y + height <= c->height) { 10729 /* can only use it if it first vertically */ 10730 if (y < best_y || (y == best_y && waste < best_waste)) { 10731 best_y = y; 10732 best_waste = waste; 10733 best = prev; 10734 } 10735 } 10736 } 10737 prev = &node->next; 10738 node = node->next; 10739 } 10740 best_x = (best == 0) ? 0 : (*best)->x; 10741 10742 /* if doing best-fit (BF), we also have to try aligning right edge to each node position */ 10743 /* */ 10744 /* e.g, if fitting */ 10745 /* */ 10746 /* ____________________ */ 10747 /* |____________________| */ 10748 /* */ 10749 /* into */ 10750 /* */ 10751 /* | | */ 10752 /* | ____________| */ 10753 /* |____________| */ 10754 /* */ 10755 /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */ 10756 /* */ 10757 /* This makes BF take about 2x the time */ 10758 if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight) 10759 { 10760 tail = c->active_head; 10761 node = c->active_head; 10762 prev = &c->active_head; 10763 /* find first node that's admissible */ 10764 while (tail->x < width) 10765 tail = tail->next; 10766 while (tail) 10767 { 10768 int xpos = tail->x - width; 10769 int y,waste; 10770 NK_ASSERT(xpos >= 0); 10771 /* find the left position that matches this */ 10772 while (node->next->x <= xpos) { 10773 prev = &node->next; 10774 node = node->next; 10775 } 10776 NK_ASSERT(node->next->x > xpos && node->x <= xpos); 10777 y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste); 10778 if (y + height < c->height) { 10779 if (y <= best_y) { 10780 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 10781 best_x = xpos; 10782 NK_ASSERT(y <= best_y); 10783 best_y = y; 10784 best_waste = waste; 10785 best = prev; 10786 } 10787 } 10788 } 10789 tail = tail->next; 10790 } 10791 } 10792 fr.prev_link = best; 10793 fr.x = best_x; 10794 fr.y = best_y; 10795 return fr; 10796} 10797NK_INTERN struct nk_rp__findresult 10798nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height) 10799{ 10800 /* find best position according to heuristic */ 10801 struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height); 10802 struct nk_rp_node *node, *cur; 10803 10804 /* bail if: */ 10805 /* 1. it failed */ 10806 /* 2. the best node doesn't fit (we don't always check this) */ 10807 /* 3. we're out of memory */ 10808 if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) { 10809 res.prev_link = 0; 10810 return res; 10811 } 10812 10813 /* on success, create new node */ 10814 node = context->free_head; 10815 node->x = (nk_rp_coord) res.x; 10816 node->y = (nk_rp_coord) (res.y + height); 10817 10818 context->free_head = node->next; 10819 10820 /* insert the new node into the right starting point, and */ 10821 /* let 'cur' point to the remaining nodes needing to be */ 10822 /* stitched back in */ 10823 cur = *res.prev_link; 10824 if (cur->x < res.x) { 10825 /* preserve the existing one, so start testing with the next one */ 10826 struct nk_rp_node *next = cur->next; 10827 cur->next = node; 10828 cur = next; 10829 } else { 10830 *res.prev_link = node; 10831 } 10832 10833 /* from here, traverse cur and free the nodes, until we get to one */ 10834 /* that shouldn't be freed */ 10835 while (cur->next && cur->next->x <= res.x + width) { 10836 struct nk_rp_node *next = cur->next; 10837 /* move the current node to the free list */ 10838 cur->next = context->free_head; 10839 context->free_head = cur; 10840 cur = next; 10841 } 10842 /* stitch the list back in */ 10843 node->next = cur; 10844 10845 if (cur->x < res.x + width) 10846 cur->x = (nk_rp_coord) (res.x + width); 10847 return res; 10848} 10849NK_INTERN int 10850nk_rect_height_compare(const void *a, const void *b) 10851{ 10852 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; 10853 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; 10854 if (p->h > q->h) 10855 return -1; 10856 if (p->h < q->h) 10857 return 1; 10858 return (p->w > q->w) ? -1 : (p->w < q->w); 10859} 10860NK_INTERN int 10861nk_rect_original_order(const void *a, const void *b) 10862{ 10863 const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; 10864 const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; 10865 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 10866} 10867NK_INTERN void 10868nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*)) 10869{ 10870 /* iterative quick sort */ 10871 #define NK_MAX_SORT_STACK 64 10872 unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0; 10873 unsigned seed = len/2 * 69069+1; 10874 for (;;) { 10875 for (; left+1 < len; len++) { 10876 struct nk_rp_rect pivot, tmp; 10877 if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0]; 10878 pivot = array[left+seed%(len-left)]; 10879 seed = seed * 69069 + 1; 10880 stack[pos++] = len; 10881 for (right = left-1;;) { 10882 while (cmp(&array[++right], &pivot) < 0); 10883 while (cmp(&pivot, &array[--len]) < 0); 10884 if (right >= len) break; 10885 tmp = array[right]; 10886 array[right] = array[len]; 10887 array[len] = tmp; 10888 } 10889 } 10890 if (pos == 0) break; 10891 left = len; 10892 len = stack[--pos]; 10893 } 10894 #undef NK_MAX_SORT_STACK 10895} 10896NK_INTERN void 10897nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects) 10898{ 10899 int i; 10900 /* we use the 'was_packed' field internally to allow sorting/unsorting */ 10901 for (i=0; i < num_rects; ++i) { 10902 rects[i].was_packed = i; 10903 } 10904 10905 /* sort according to heuristic */ 10906 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare); 10907 10908 for (i=0; i < num_rects; ++i) { 10909 struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 10910 if (fr.prev_link) { 10911 rects[i].x = (nk_rp_coord) fr.x; 10912 rects[i].y = (nk_rp_coord) fr.y; 10913 } else { 10914 rects[i].x = rects[i].y = NK_RP__MAXVAL; 10915 } 10916 } 10917 10918 /* unsort */ 10919 nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order); 10920 10921 /* set was_packed flags */ 10922 for (i=0; i < num_rects; ++i) 10923 rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL); 10924} 10925 10926/* 10927 * ============================================================== 10928 * 10929 * TRUETYPE 10930 * 10931 * =============================================================== 10932 */ 10933/* stb_truetype.h - v1.07 - public domain */ 10934#define NK_TT_MAX_OVERSAMPLE 8 10935#define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1) 10936 10937struct nk_tt_bakedchar { 10938 unsigned short x0,y0,x1,y1; 10939 /* coordinates of bbox in bitmap */ 10940 float xoff,yoff,xadvance; 10941}; 10942 10943struct nk_tt_aligned_quad{ 10944 float x0,y0,s0,t0; /* top-left */ 10945 float x1,y1,s1,t1; /* bottom-right */ 10946}; 10947 10948struct nk_tt_packedchar { 10949 unsigned short x0,y0,x1,y1; 10950 /* coordinates of bbox in bitmap */ 10951 float xoff,yoff,xadvance; 10952 float xoff2,yoff2; 10953}; 10954 10955struct nk_tt_pack_range { 10956 float font_size; 10957 int first_unicode_codepoint_in_range; 10958 /* if non-zero, then the chars are continuous, and this is the first codepoint */ 10959 int *array_of_unicode_codepoints; 10960 /* if non-zero, then this is an array of unicode codepoints */ 10961 int num_chars; 10962 struct nk_tt_packedchar *chardata_for_range; /* output */ 10963 unsigned char h_oversample, v_oversample; 10964 /* don't set these, they're used internally */ 10965}; 10966 10967struct nk_tt_pack_context { 10968 void *pack_info; 10969 int width; 10970 int height; 10971 int stride_in_bytes; 10972 int padding; 10973 unsigned int h_oversample, v_oversample; 10974 unsigned char *pixels; 10975 void *nodes; 10976}; 10977 10978struct nk_tt_fontinfo { 10979 const unsigned char* data; /* pointer to .ttf file */ 10980 int fontstart;/* offset of start of font */ 10981 int numGlyphs;/* number of glyphs, needed for range checking */ 10982 int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */ 10983 int index_map; /* a cmap mapping for our chosen character encoding */ 10984 int indexToLocFormat; /* format needed to map from glyph index to glyph */ 10985}; 10986 10987enum { 10988 NK_TT_vmove=1, 10989 NK_TT_vline, 10990 NK_TT_vcurve 10991}; 10992 10993struct nk_tt_vertex { 10994 short x,y,cx,cy; 10995 unsigned char type,padding; 10996}; 10997 10998struct nk_tt__bitmap{ 10999 int w,h,stride; 11000 unsigned char *pixels; 11001}; 11002 11003struct nk_tt__hheap_chunk { 11004 struct nk_tt__hheap_chunk *next; 11005}; 11006struct nk_tt__hheap { 11007 struct nk_allocator alloc; 11008 struct nk_tt__hheap_chunk *head; 11009 void *first_free; 11010 int num_remaining_in_head_chunk; 11011}; 11012 11013struct nk_tt__edge { 11014 float x0,y0, x1,y1; 11015 int invert; 11016}; 11017 11018struct nk_tt__active_edge { 11019 struct nk_tt__active_edge *next; 11020 float fx,fdx,fdy; 11021 float direction; 11022 float sy; 11023 float ey; 11024}; 11025struct nk_tt__point {float x,y;}; 11026 11027#define NK_TT_MACSTYLE_DONTCARE 0 11028#define NK_TT_MACSTYLE_BOLD 1 11029#define NK_TT_MACSTYLE_ITALIC 2 11030#define NK_TT_MACSTYLE_UNDERSCORE 4 11031#define NK_TT_MACSTYLE_NONE 8 11032/* <= not same as 0, this makes us check the bitfield is 0 */ 11033 11034enum { /* platformID */ 11035 NK_TT_PLATFORM_ID_UNICODE =0, 11036 NK_TT_PLATFORM_ID_MAC =1, 11037 NK_TT_PLATFORM_ID_ISO =2, 11038 NK_TT_PLATFORM_ID_MICROSOFT =3 11039}; 11040 11041enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */ 11042 NK_TT_UNICODE_EID_UNICODE_1_0 =0, 11043 NK_TT_UNICODE_EID_UNICODE_1_1 =1, 11044 NK_TT_UNICODE_EID_ISO_10646 =2, 11045 NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3, 11046 NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4 11047}; 11048 11049enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */ 11050 NK_TT_MS_EID_SYMBOL =0, 11051 NK_TT_MS_EID_UNICODE_BMP =1, 11052 NK_TT_MS_EID_SHIFTJIS =2, 11053 NK_TT_MS_EID_UNICODE_FULL =10 11054}; 11055 11056enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */ 11057 NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4, 11058 NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5, 11059 NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6, 11060 NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7 11061}; 11062 11063enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */ 11064 /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */ 11065 NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410, 11066 NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411, 11067 NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412, 11068 NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419, 11069 NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409, 11070 NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D 11071}; 11072 11073enum { /* languageID for NK_TT_PLATFORM_ID_MAC */ 11074 NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11, 11075 NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23, 11076 NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32, 11077 NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 , 11078 NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 , 11079 NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33, 11080 NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19 11081}; 11082 11083#define nk_ttBYTE(p) (* (const nk_byte *) (p)) 11084#define nk_ttCHAR(p) (* (const char *) (p)) 11085 11086#if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE) 11087 #define nk_ttUSHORT(p) (* (nk_ushort *) (p)) 11088 #define nk_ttSHORT(p) (* (nk_short *) (p)) 11089 #define nk_ttULONG(p) (* (nk_uint *) (p)) 11090 #define nk_ttLONG(p) (* (nk_int *) (p)) 11091#else 11092 static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); } 11093 static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); } 11094 static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); } 11095#endif 11096 11097#define nk_tt_tag4(p,c0,c1,c2,c3)\ 11098 ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) 11099#define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3]) 11100 11101NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, 11102 int glyph_index, struct nk_tt_vertex **pvertices); 11103 11104NK_INTERN nk_uint 11105nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag) 11106{ 11107 /* @OPTIMIZE: binary search */ 11108 nk_int num_tables = nk_ttUSHORT(data+fontstart+4); 11109 nk_uint tabledir = fontstart + 12; 11110 nk_int i; 11111 for (i = 0; i < num_tables; ++i) { 11112 nk_uint loc = tabledir + (nk_uint)(16*i); 11113 if (nk_tt_tag(data+loc+0, tag)) 11114 return nk_ttULONG(data+loc+8); 11115 } 11116 return 0; 11117} 11118NK_INTERN int 11119nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart) 11120{ 11121 nk_uint cmap, t; 11122 nk_int i,numTables; 11123 const nk_byte *data = (const nk_byte *) data2; 11124 11125 info->data = data; 11126 info->fontstart = fontstart; 11127 11128 cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */ 11129 info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */ 11130 info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */ 11131 info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */ 11132 info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */ 11133 info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */ 11134 info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */ 11135 if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) 11136 return 0; 11137 11138 t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp"); 11139 if (t) info->numGlyphs = nk_ttUSHORT(data+t+4); 11140 else info->numGlyphs = 0xffff; 11141 11142 /* find a cmap encoding table we understand *now* to avoid searching */ 11143 /* later. (todo: could make this installable) */ 11144 /* the same regardless of glyph. */ 11145 numTables = nk_ttUSHORT(data + cmap + 2); 11146 info->index_map = 0; 11147 for (i=0; i < numTables; ++i) 11148 { 11149 nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i; 11150 /* find an encoding we understand: */ 11151 switch(nk_ttUSHORT(data+encoding_record)) { 11152 case NK_TT_PLATFORM_ID_MICROSOFT: 11153 switch (nk_ttUSHORT(data+encoding_record+2)) { 11154 case NK_TT_MS_EID_UNICODE_BMP: 11155 case NK_TT_MS_EID_UNICODE_FULL: 11156 /* MS/Unicode */ 11157 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); 11158 break; 11159 default: break; 11160 } break; 11161 case NK_TT_PLATFORM_ID_UNICODE: 11162 /* Mac/iOS has these */ 11163 /* all the encodingIDs are unicode, so we don't bother to check it */ 11164 info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); 11165 break; 11166 default: break; 11167 } 11168 } 11169 if (info->index_map == 0) 11170 return 0; 11171 info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50); 11172 return 1; 11173} 11174NK_INTERN int 11175nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint) 11176{ 11177 const nk_byte *data = info->data; 11178 nk_uint index_map = (nk_uint)info->index_map; 11179 11180 nk_ushort format = nk_ttUSHORT(data + index_map + 0); 11181 if (format == 0) { /* apple byte encoding */ 11182 nk_int bytes = nk_ttUSHORT(data + index_map + 2); 11183 if (unicode_codepoint < bytes-6) 11184 return nk_ttBYTE(data + index_map + 6 + unicode_codepoint); 11185 return 0; 11186 } else if (format == 6) { 11187 nk_uint first = nk_ttUSHORT(data + index_map + 6); 11188 nk_uint count = nk_ttUSHORT(data + index_map + 8); 11189 if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count) 11190 return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2); 11191 return 0; 11192 } else if (format == 2) { 11193 NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */ 11194 return 0; 11195 } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */ 11196 nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1; 11197 nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1; 11198 nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10); 11199 nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1; 11200 11201 /* do a binary search of the segments */ 11202 nk_uint endCount = index_map + 14; 11203 nk_uint search = endCount; 11204 11205 if (unicode_codepoint > 0xffff) 11206 return 0; 11207 11208 /* they lie from endCount .. endCount + segCount */ 11209 /* but searchRange is the nearest power of two, so... */ 11210 if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2)) 11211 search += (nk_uint)(rangeShift*2); 11212 11213 /* now decrement to bias correctly to find smallest */ 11214 search -= 2; 11215 while (entrySelector) { 11216 nk_ushort end; 11217 searchRange >>= 1; 11218 end = nk_ttUSHORT(data + search + searchRange*2); 11219 if (unicode_codepoint > end) 11220 search += (nk_uint)(searchRange*2); 11221 --entrySelector; 11222 } 11223 search += 2; 11224 11225 { 11226 nk_ushort offset, start; 11227 nk_ushort item = (nk_ushort) ((search - endCount) >> 1); 11228 11229 NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item)); 11230 start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); 11231 if (unicode_codepoint < start) 11232 return 0; 11233 11234 offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); 11235 if (offset == 0) 11236 return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); 11237 11238 return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); 11239 } 11240 } else if (format == 12 || format == 13) { 11241 nk_uint ngroups = nk_ttULONG(data+index_map+12); 11242 nk_int low,high; 11243 low = 0; high = (nk_int)ngroups; 11244 /* Binary search the right group. */ 11245 while (low < high) { 11246 nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */ 11247 nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12); 11248 nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4); 11249 if ((nk_uint) unicode_codepoint < start_char) 11250 high = mid; 11251 else if ((nk_uint) unicode_codepoint > end_char) 11252 low = mid+1; 11253 else { 11254 nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8); 11255 if (format == 12) 11256 return (int)start_glyph + (int)unicode_codepoint - (int)start_char; 11257 else /* format == 13 */ 11258 return (int)start_glyph; 11259 } 11260 } 11261 return 0; /* not found */ 11262 } 11263 /* @TODO */ 11264 NK_ASSERT(0); 11265 return 0; 11266} 11267NK_INTERN void 11268nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy) 11269{ 11270 v->type = type; 11271 v->x = (nk_short) x; 11272 v->y = (nk_short) y; 11273 v->cx = (nk_short) cx; 11274 v->cy = (nk_short) cy; 11275} 11276NK_INTERN int 11277nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index) 11278{ 11279 int g1,g2; 11280 if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */ 11281 if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */ 11282 11283 if (info->indexToLocFormat == 0) { 11284 g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; 11285 g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; 11286 } else { 11287 g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4); 11288 g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4); 11289 } 11290 return g1==g2 ? -1 : g1; /* if length is 0, return -1 */ 11291} 11292NK_INTERN int 11293nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index, 11294 int *x0, int *y0, int *x1, int *y1) 11295{ 11296 int g = nk_tt__GetGlyfOffset(info, glyph_index); 11297 if (g < 0) return 0; 11298 11299 if (x0) *x0 = nk_ttSHORT(info->data + g + 2); 11300 if (y0) *y0 = nk_ttSHORT(info->data + g + 4); 11301 if (x1) *x1 = nk_ttSHORT(info->data + g + 6); 11302 if (y1) *y1 = nk_ttSHORT(info->data + g + 8); 11303 return 1; 11304} 11305NK_INTERN int 11306nk_tt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off, 11307 int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy) 11308{ 11309 if (start_off) { 11310 if (was_off) 11311 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); 11312 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy); 11313 } else { 11314 if (was_off) 11315 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy); 11316 else 11317 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0); 11318 } 11319 return num_vertices; 11320} 11321NK_INTERN int 11322nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, 11323 int glyph_index, struct nk_tt_vertex **pvertices) 11324{ 11325 nk_short numberOfContours; 11326 const nk_byte *endPtsOfContours; 11327 const nk_byte *data = info->data; 11328 struct nk_tt_vertex *vertices=0; 11329 int num_vertices=0; 11330 int g = nk_tt__GetGlyfOffset(info, glyph_index); 11331 *pvertices = 0; 11332 11333 if (g < 0) return 0; 11334 numberOfContours = nk_ttSHORT(data + g); 11335 if (numberOfContours > 0) { 11336 nk_byte flags=0,flagcount; 11337 nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; 11338 nk_int x,y,cx,cy,sx,sy, scx,scy; 11339 const nk_byte *points; 11340 endPtsOfContours = (data + g + 10); 11341 ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2); 11342 points = data + g + 10 + numberOfContours * 2 + 2 + ins; 11343 11344 n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2); 11345 m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */ 11346 vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0])); 11347 if (vertices == 0) 11348 return 0; 11349 11350 next_move = 0; 11351 flagcount=0; 11352 11353 /* in first pass, we load uninterpreted data into the allocated array */ 11354 /* above, shifted to the end of the array so we won't overwrite it when */ 11355 /* we create our final data starting from the front */ 11356 off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */ 11357 11358 /* first load flags */ 11359 for (i=0; i < n; ++i) { 11360 if (flagcount == 0) { 11361 flags = *points++; 11362 if (flags & 8) 11363 flagcount = *points++; 11364 } else --flagcount; 11365 vertices[off+i].type = flags; 11366 } 11367 11368 /* now load x coordinates */ 11369 x=0; 11370 for (i=0; i < n; ++i) { 11371 flags = vertices[off+i].type; 11372 if (flags & 2) { 11373 nk_short dx = *points++; 11374 x += (flags & 16) ? dx : -dx; /* ??? */ 11375 } else { 11376 if (!(flags & 16)) { 11377 x = x + (nk_short) (points[0]*256 + points[1]); 11378 points += 2; 11379 } 11380 } 11381 vertices[off+i].x = (nk_short) x; 11382 } 11383 11384 /* now load y coordinates */ 11385 y=0; 11386 for (i=0; i < n; ++i) { 11387 flags = vertices[off+i].type; 11388 if (flags & 4) { 11389 nk_short dy = *points++; 11390 y += (flags & 32) ? dy : -dy; /* ??? */ 11391 } else { 11392 if (!(flags & 32)) { 11393 y = y + (nk_short) (points[0]*256 + points[1]); 11394 points += 2; 11395 } 11396 } 11397 vertices[off+i].y = (nk_short) y; 11398 } 11399 11400 /* now convert them to our format */ 11401 num_vertices=0; 11402 sx = sy = cx = cy = scx = scy = 0; 11403 for (i=0; i < n; ++i) 11404 { 11405 flags = vertices[off+i].type; 11406 x = (nk_short) vertices[off+i].x; 11407 y = (nk_short) vertices[off+i].y; 11408 11409 if (next_move == i) { 11410 if (i != 0) 11411 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 11412 11413 /* now start the new one */ 11414 start_off = !(flags & 1); 11415 if (start_off) { 11416 /* if we start off with an off-curve point, then when we need to find a point on the curve */ 11417 /* where we can start, and we need to save some state for when we wraparound. */ 11418 scx = x; 11419 scy = y; 11420 if (!(vertices[off+i+1].type & 1)) { 11421 /* next point is also a curve point, so interpolate an on-point curve */ 11422 sx = (x + (nk_int) vertices[off+i+1].x) >> 1; 11423 sy = (y + (nk_int) vertices[off+i+1].y) >> 1; 11424 } else { 11425 /* otherwise just use the next point as our start point */ 11426 sx = (nk_int) vertices[off+i+1].x; 11427 sy = (nk_int) vertices[off+i+1].y; 11428 ++i; /* we're using point i+1 as the starting point, so skip it */ 11429 } 11430 } else { 11431 sx = x; 11432 sy = y; 11433 } 11434 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0); 11435 was_off = 0; 11436 next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2); 11437 ++j; 11438 } else { 11439 if (!(flags & 1)) 11440 { /* if it's a curve */ 11441 if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */ 11442 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); 11443 cx = x; 11444 cy = y; 11445 was_off = 1; 11446 } else { 11447 if (was_off) 11448 nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy); 11449 else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0); 11450 was_off = 0; 11451 } 11452 } 11453 } 11454 num_vertices = nk_tt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 11455 } else if (numberOfContours == -1) { 11456 /* Compound shapes. */ 11457 int more = 1; 11458 const nk_byte *comp = data + g + 10; 11459 num_vertices = 0; 11460 vertices = 0; 11461 11462 while (more) 11463 { 11464 nk_ushort flags, gidx; 11465 int comp_num_verts = 0, i; 11466 struct nk_tt_vertex *comp_verts = 0, *tmp = 0; 11467 float mtx[6] = {1,0,0,1,0,0}, m, n; 11468 11469 flags = (nk_ushort)nk_ttSHORT(comp); comp+=2; 11470 gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2; 11471 11472 if (flags & 2) { /* XY values */ 11473 if (flags & 1) { /* shorts */ 11474 mtx[4] = nk_ttSHORT(comp); comp+=2; 11475 mtx[5] = nk_ttSHORT(comp); comp+=2; 11476 } else { 11477 mtx[4] = nk_ttCHAR(comp); comp+=1; 11478 mtx[5] = nk_ttCHAR(comp); comp+=1; 11479 } 11480 } else { 11481 /* @TODO handle matching point */ 11482 NK_ASSERT(0); 11483 } 11484 if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */ 11485 mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11486 mtx[1] = mtx[2] = 0; 11487 } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */ 11488 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11489 mtx[1] = mtx[2] = 0; 11490 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11491 } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */ 11492 mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11493 mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11494 mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11495 mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; 11496 } 11497 11498 /* Find transformation scales. */ 11499 m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]); 11500 n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]); 11501 11502 /* Get indexed glyph. */ 11503 comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts); 11504 if (comp_num_verts > 0) 11505 { 11506 /* Transform vertices. */ 11507 for (i = 0; i < comp_num_verts; ++i) { 11508 struct nk_tt_vertex* v = &comp_verts[i]; 11509 short x,y; 11510 x=v->x; y=v->y; 11511 v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 11512 v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 11513 x=v->cx; y=v->cy; 11514 v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 11515 v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 11516 } 11517 /* Append vertices. */ 11518 tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0, 11519 (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex)); 11520 if (!tmp) { 11521 if (vertices) alloc->free(alloc->userdata, vertices); 11522 if (comp_verts) alloc->free(alloc->userdata, comp_verts); 11523 return 0; 11524 } 11525 if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex)); 11526 NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex)); 11527 if (vertices) alloc->free(alloc->userdata,vertices); 11528 vertices = tmp; 11529 alloc->free(alloc->userdata,comp_verts); 11530 num_vertices += comp_num_verts; 11531 } 11532 /* More components ? */ 11533 more = flags & (1<<5); 11534 } 11535 } else if (numberOfContours < 0) { 11536 /* @TODO other compound variations? */ 11537 NK_ASSERT(0); 11538 } else { 11539 /* numberOfCounters == 0, do nothing */ 11540 } 11541 *pvertices = vertices; 11542 return num_vertices; 11543} 11544NK_INTERN void 11545nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index, 11546 int *advanceWidth, int *leftSideBearing) 11547{ 11548 nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34); 11549 if (glyph_index < numOfLongHorMetrics) { 11550 if (advanceWidth) 11551 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index); 11552 if (leftSideBearing) 11553 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); 11554 } else { 11555 if (advanceWidth) 11556 *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); 11557 if (leftSideBearing) 11558 *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); 11559 } 11560} 11561NK_INTERN void 11562nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info, 11563 int *ascent, int *descent, int *lineGap) 11564{ 11565 if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4); 11566 if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6); 11567 if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8); 11568} 11569NK_INTERN float 11570nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height) 11571{ 11572 int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6); 11573 return (float) height / (float)fheight; 11574} 11575NK_INTERN float 11576nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels) 11577{ 11578 int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18); 11579 return pixels / (float)unitsPerEm; 11580} 11581 11582/*------------------------------------------------------------- 11583 * antialiasing software rasterizer 11584 * --------------------------------------------------------------*/ 11585NK_INTERN void 11586nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font, 11587 int glyph, float scale_x, float scale_y,float shift_x, float shift_y, 11588 int *ix0, int *iy0, int *ix1, int *iy1) 11589{ 11590 int x0,y0,x1,y1; 11591 if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { 11592 /* e.g. space character */ 11593 if (ix0) *ix0 = 0; 11594 if (iy0) *iy0 = 0; 11595 if (ix1) *ix1 = 0; 11596 if (iy1) *iy1 = 0; 11597 } else { 11598 /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */ 11599 if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x); 11600 if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y); 11601 if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x); 11602 if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y); 11603 } 11604} 11605NK_INTERN void 11606nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph, 11607 float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) 11608{ 11609 nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); 11610} 11611 11612/*------------------------------------------------------------- 11613 * Rasterizer 11614 * --------------------------------------------------------------*/ 11615NK_INTERN void* 11616nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size) 11617{ 11618 if (hh->first_free) { 11619 void *p = hh->first_free; 11620 hh->first_free = * (void **) p; 11621 return p; 11622 } else { 11623 if (hh->num_remaining_in_head_chunk == 0) { 11624 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); 11625 struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *) 11626 hh->alloc.alloc(hh->alloc.userdata, 0, 11627 sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count); 11628 if (c == 0) return 0; 11629 c->next = hh->head; 11630 hh->head = c; 11631 hh->num_remaining_in_head_chunk = count; 11632 } 11633 --hh->num_remaining_in_head_chunk; 11634 return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk; 11635 } 11636} 11637NK_INTERN void 11638nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p) 11639{ 11640 *(void **) p = hh->first_free; 11641 hh->first_free = p; 11642} 11643NK_INTERN void 11644nk_tt__hheap_cleanup(struct nk_tt__hheap *hh) 11645{ 11646 struct nk_tt__hheap_chunk *c = hh->head; 11647 while (c) { 11648 struct nk_tt__hheap_chunk *n = c->next; 11649 hh->alloc.free(hh->alloc.userdata, c); 11650 c = n; 11651 } 11652} 11653NK_INTERN struct nk_tt__active_edge* 11654nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e, 11655 int off_x, float start_point) 11656{ 11657 struct nk_tt__active_edge *z = (struct nk_tt__active_edge *) 11658 nk_tt__hheap_alloc(hh, sizeof(*z)); 11659 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 11660 /*STBTT_assert(e->y0 <= start_point); */ 11661 if (!z) return z; 11662 z->fdx = dxdy; 11663 z->fdy = (dxdy != 0) ? (1/dxdy): 0; 11664 z->fx = e->x0 + dxdy * (start_point - e->y0); 11665 z->fx -= (float)off_x; 11666 z->direction = e->invert ? 1.0f : -1.0f; 11667 z->sy = e->y0; 11668 z->ey = e->y1; 11669 z->next = 0; 11670 return z; 11671} 11672NK_INTERN void 11673nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e, 11674 float x0, float y0, float x1, float y1) 11675{ 11676 if (y0 == y1) return; 11677 NK_ASSERT(y0 < y1); 11678 NK_ASSERT(e->sy <= e->ey); 11679 if (y0 > e->ey) return; 11680 if (y1 < e->sy) return; 11681 if (y0 < e->sy) { 11682 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); 11683 y0 = e->sy; 11684 } 11685 if (y1 > e->ey) { 11686 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); 11687 y1 = e->ey; 11688 } 11689 11690 if (x0 == x) NK_ASSERT(x1 <= x+1); 11691 else if (x0 == x+1) NK_ASSERT(x1 >= x); 11692 else if (x0 <= x) NK_ASSERT(x1 <= x); 11693 else if (x0 >= x+1) NK_ASSERT(x1 >= x+1); 11694 else NK_ASSERT(x1 >= x && x1 <= x+1); 11695 11696 if (x0 <= x && x1 <= x) 11697 scanline[x] += e->direction * (y1-y0); 11698 else if (x0 >= x+1 && x1 >= x+1); 11699 else { 11700 NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); 11701 /* coverage = 1 - average x position */ 11702 scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f); 11703 } 11704} 11705NK_INTERN void 11706nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, 11707 struct nk_tt__active_edge *e, float y_top) 11708{ 11709 float y_bottom = y_top+1; 11710 while (e) 11711 { 11712 /* brute force every pixel */ 11713 /* compute intersection points with top & bottom */ 11714 NK_ASSERT(e->ey >= y_top); 11715 if (e->fdx == 0) { 11716 float x0 = e->fx; 11717 if (x0 < len) { 11718 if (x0 >= 0) { 11719 nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); 11720 nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); 11721 } else { 11722 nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); 11723 } 11724 } 11725 } else { 11726 float x0 = e->fx; 11727 float dx = e->fdx; 11728 float xb = x0 + dx; 11729 float x_top, x_bottom; 11730 float y0,y1; 11731 float dy = e->fdy; 11732 NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top); 11733 11734 /* compute endpoints of line segment clipped to this scanline (if the */ 11735 /* line segment starts on this scanline. x0 is the intersection of the */ 11736 /* line with y_top, but that may be off the line segment. */ 11737 if (e->sy > y_top) { 11738 x_top = x0 + dx * (e->sy - y_top); 11739 y0 = e->sy; 11740 } else { 11741 x_top = x0; 11742 y0 = y_top; 11743 } 11744 11745 if (e->ey < y_bottom) { 11746 x_bottom = x0 + dx * (e->ey - y_top); 11747 y1 = e->ey; 11748 } else { 11749 x_bottom = xb; 11750 y1 = y_bottom; 11751 } 11752 11753 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) 11754 { 11755 /* from here on, we don't have to range check x values */ 11756 if ((int) x_top == (int) x_bottom) { 11757 float height; 11758 /* simple case, only spans one pixel */ 11759 int x = (int) x_top; 11760 height = y1 - y0; 11761 NK_ASSERT(x >= 0 && x < len); 11762 scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height; 11763 scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */ 11764 } else { 11765 int x,x1,x2; 11766 float y_crossing, step, sign, area; 11767 /* covers 2+ pixels */ 11768 if (x_top > x_bottom) 11769 { 11770 /* flip scanline vertically; signed area is the same */ 11771 float t; 11772 y0 = y_bottom - (y0 - y_top); 11773 y1 = y_bottom - (y1 - y_top); 11774 t = y0; y0 = y1; y1 = t; 11775 t = x_bottom; x_bottom = x_top; x_top = t; 11776 dx = -dx; 11777 dy = -dy; 11778 t = x0; x0 = xb; xb = t; 11779 } 11780 11781 x1 = (int) x_top; 11782 x2 = (int) x_bottom; 11783 /* compute intersection with y axis at x1+1 */ 11784 y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top; 11785 11786 sign = e->direction; 11787 /* area of the rectangle covered from y0..y_crossing */ 11788 area = sign * (y_crossing-y0); 11789 /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */ 11790 scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f); 11791 11792 step = sign * dy; 11793 for (x = x1+1; x < x2; ++x) { 11794 scanline[x] += area + step/2; 11795 area += step; 11796 } 11797 y_crossing += (float)dy * (float)(x2 - (x1+1)); 11798 11799 scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing); 11800 scanline_fill[x2] += sign * (y1-y0); 11801 } 11802 } 11803 else 11804 { 11805 /* if edge goes outside of box we're drawing, we require */ 11806 /* clipping logic. since this does not match the intended use */ 11807 /* of this library, we use a different, very slow brute */ 11808 /* force implementation */ 11809 int x; 11810 for (x=0; x < len; ++x) 11811 { 11812 /* cases: */ 11813 /* */ 11814 /* there can be up to two intersections with the pixel. any intersection */ 11815 /* with left or right edges can be handled by splitting into two (or three) */ 11816 /* regions. intersections with top & bottom do not necessitate case-wise logic. */ 11817 /* */ 11818 /* the old way of doing this found the intersections with the left & right edges, */ 11819 /* then used some simple logic to produce up to three segments in sorted order */ 11820 /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */ 11821 /* across the x border, then the corresponding y position might not be distinct */ 11822 /* from the other y segment, and it might ignored as an empty segment. to avoid */ 11823 /* that, we need to explicitly produce segments based on x positions. */ 11824 11825 /* rename variables to clear pairs */ 11826 float ya = y_top; 11827 float x1 = (float) (x); 11828 float x2 = (float) (x+1); 11829 float x3 = xb; 11830 float y3 = y_bottom; 11831 float yb,y2; 11832 11833 yb = ((float)x - x0) / dx + y_top; 11834 y2 = ((float)x+1 - x0) / dx + y_top; 11835 11836 if (x0 < x1 && x3 > x2) { /* three segments descending down-right */ 11837 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11838 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2); 11839 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11840 } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */ 11841 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11842 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb); 11843 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11844 } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */ 11845 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11846 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11847 } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */ 11848 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); 11849 nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); 11850 } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */ 11851 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11852 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11853 } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */ 11854 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); 11855 nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 11856 } else { /* one segment */ 11857 nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3); 11858 } 11859 } 11860 } 11861 } 11862 e = e->next; 11863 } 11864} 11865NK_INTERN void 11866nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e, 11867 int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc) 11868{ 11869 /* directly AA rasterize edges w/o supersampling */ 11870 struct nk_tt__hheap hh; 11871 struct nk_tt__active_edge *active = 0; 11872 int y,j=0, i; 11873 float scanline_data[129], *scanline, *scanline2; 11874 11875 NK_UNUSED(vsubsample); 11876 nk_zero_struct(hh); 11877 hh.alloc = *alloc; 11878 11879 if (result->w > 64) 11880 scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float)); 11881 else scanline = scanline_data; 11882 11883 scanline2 = scanline + result->w; 11884 y = off_y; 11885 e[n].y0 = (float) (off_y + result->h) + 1; 11886 11887 while (j < result->h) 11888 { 11889 /* find center of pixel for this scanline */ 11890 float scan_y_top = (float)y + 0.0f; 11891 float scan_y_bottom = (float)y + 1.0f; 11892 struct nk_tt__active_edge **step = &active; 11893 11894 NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0])); 11895 NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0])); 11896 11897 /* update all active edges; */ 11898 /* remove all active edges that terminate before the top of this scanline */ 11899 while (*step) { 11900 struct nk_tt__active_edge * z = *step; 11901 if (z->ey <= scan_y_top) { 11902 *step = z->next; /* delete from list */ 11903 NK_ASSERT(z->direction); 11904 z->direction = 0; 11905 nk_tt__hheap_free(&hh, z); 11906 } else { 11907 step = &((*step)->next); /* advance through list */ 11908 } 11909 } 11910 11911 /* insert all edges that start before the bottom of this scanline */ 11912 while (e->y0 <= scan_y_bottom) { 11913 if (e->y0 != e->y1) { 11914 struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top); 11915 if (z != 0) { 11916 NK_ASSERT(z->ey >= scan_y_top); 11917 /* insert at front */ 11918 z->next = active; 11919 active = z; 11920 } 11921 } 11922 ++e; 11923 } 11924 11925 /* now process all active edges */ 11926 if (active) 11927 nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); 11928 11929 { 11930 float sum = 0; 11931 for (i=0; i < result->w; ++i) { 11932 float k; 11933 int m; 11934 sum += scanline2[i]; 11935 k = scanline[i] + sum; 11936 k = (float) NK_ABS(k) * 255.0f + 0.5f; 11937 m = (int) k; 11938 if (m > 255) m = 255; 11939 result->pixels[j*result->stride + i] = (unsigned char) m; 11940 } 11941 } 11942 /* advance all the edges */ 11943 step = &active; 11944 while (*step) { 11945 struct nk_tt__active_edge *z = *step; 11946 z->fx += z->fdx; /* advance to position for current scanline */ 11947 step = &((*step)->next); /* advance through list */ 11948 } 11949 ++y; 11950 ++j; 11951 } 11952 nk_tt__hheap_cleanup(&hh); 11953 if (scanline != scanline_data) 11954 alloc->free(alloc->userdata, scanline); 11955} 11956NK_INTERN void 11957nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n) 11958{ 11959 int i,j; 11960 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0) 11961 for (i=1; i < n; ++i) { 11962 struct nk_tt__edge t = p[i], *a = &t; 11963 j = i; 11964 while (j > 0) { 11965 struct nk_tt__edge *b = &p[j-1]; 11966 int c = NK_TT__COMPARE(a,b); 11967 if (!c) break; 11968 p[j] = p[j-1]; 11969 --j; 11970 } 11971 if (i != j) 11972 p[j] = t; 11973 } 11974} 11975NK_INTERN void 11976nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n) 11977{ 11978 /* threshold for transitioning to insertion sort */ 11979 while (n > 12) { 11980 struct nk_tt__edge t; 11981 int c01,c12,c,m,i,j; 11982 11983 /* compute median of three */ 11984 m = n >> 1; 11985 c01 = NK_TT__COMPARE(&p[0],&p[m]); 11986 c12 = NK_TT__COMPARE(&p[m],&p[n-1]); 11987 11988 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ 11989 if (c01 != c12) { 11990 /* otherwise, we'll need to swap something else to middle */ 11991 int z; 11992 c = NK_TT__COMPARE(&p[0],&p[n-1]); 11993 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ 11994 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ 11995 z = (c == c12) ? 0 : n-1; 11996 t = p[z]; 11997 p[z] = p[m]; 11998 p[m] = t; 11999 } 12000 12001 /* now p[m] is the median-of-three */ 12002 /* swap it to the beginning so it won't move around */ 12003 t = p[0]; 12004 p[0] = p[m]; 12005 p[m] = t; 12006 12007 /* partition loop */ 12008 i=1; 12009 j=n-1; 12010 for(;;) { 12011 /* handling of equality is crucial here */ 12012 /* for sentinels & efficiency with duplicates */ 12013 for (;;++i) { 12014 if (!NK_TT__COMPARE(&p[i], &p[0])) break; 12015 } 12016 for (;;--j) { 12017 if (!NK_TT__COMPARE(&p[0], &p[j])) break; 12018 } 12019 12020 /* make sure we haven't crossed */ 12021 if (i >= j) break; 12022 t = p[i]; 12023 p[i] = p[j]; 12024 p[j] = t; 12025 12026 ++i; 12027 --j; 12028 12029 } 12030 12031 /* recurse on smaller side, iterate on larger */ 12032 if (j < (n-i)) { 12033 nk_tt__sort_edges_quicksort(p,j); 12034 p = p+i; 12035 n = n-i; 12036 } else { 12037 nk_tt__sort_edges_quicksort(p+i, n-i); 12038 n = j; 12039 } 12040 } 12041} 12042NK_INTERN void 12043nk_tt__sort_edges(struct nk_tt__edge *p, int n) 12044{ 12045 nk_tt__sort_edges_quicksort(p, n); 12046 nk_tt__sort_edges_ins_sort(p, n); 12047} 12048NK_INTERN void 12049nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts, 12050 int *wcount, int windings, float scale_x, float scale_y, 12051 float shift_x, float shift_y, int off_x, int off_y, int invert, 12052 struct nk_allocator *alloc) 12053{ 12054 float y_scale_inv = invert ? -scale_y : scale_y; 12055 struct nk_tt__edge *e; 12056 int n,i,j,k,m; 12057 int vsubsample = 1; 12058 /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */ 12059 12060 /* now we have to blow out the windings into explicit edge lists */ 12061 n = 0; 12062 for (i=0; i < windings; ++i) 12063 n += wcount[i]; 12064 12065 e = (struct nk_tt__edge*) 12066 alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1))); 12067 if (e == 0) return; 12068 n = 0; 12069 12070 m=0; 12071 for (i=0; i < windings; ++i) 12072 { 12073 struct nk_tt__point *p = pts + m; 12074 m += wcount[i]; 12075 j = wcount[i]-1; 12076 for (k=0; k < wcount[i]; j=k++) { 12077 int a=k,b=j; 12078 /* skip the edge if horizontal */ 12079 if (p[j].y == p[k].y) 12080 continue; 12081 12082 /* add edge from j to k to the list */ 12083 e[n].invert = 0; 12084 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { 12085 e[n].invert = 1; 12086 a=j,b=k; 12087 } 12088 e[n].x0 = p[a].x * scale_x + shift_x; 12089 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample; 12090 e[n].x1 = p[b].x * scale_x + shift_x; 12091 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample; 12092 ++n; 12093 } 12094 } 12095 12096 /* now sort the edges by their highest point (should snap to integer, and then by x) */ 12097 /*STBTT_sort(e, n, sizeof(e[0]), nk_tt__edge_compare); */ 12098 nk_tt__sort_edges(e, n); 12099 /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */ 12100 nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc); 12101 alloc->free(alloc->userdata, e); 12102} 12103NK_INTERN void 12104nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y) 12105{ 12106 if (!points) return; /* during first pass, it's unallocated */ 12107 points[n].x = x; 12108 points[n].y = y; 12109} 12110NK_INTERN int 12111nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points, 12112 float x0, float y0, float x1, float y1, float x2, float y2, 12113 float objspace_flatness_squared, int n) 12114{ 12115 /* tesselate until threshold p is happy... 12116 * @TODO warped to compensate for non-linear stretching */ 12117 /* midpoint */ 12118 float mx = (x0 + 2*x1 + x2)/4; 12119 float my = (y0 + 2*y1 + y2)/4; 12120 /* versus directly drawn line */ 12121 float dx = (x0+x2)/2 - mx; 12122 float dy = (y0+y2)/2 - my; 12123 if (n > 16) /* 65536 segments on one curve better be enough! */ 12124 return 1; 12125 12126 /* half-pixel error allowed... need to be smaller if AA */ 12127 if (dx*dx+dy*dy > objspace_flatness_squared) { 12128 nk_tt__tesselate_curve(points, num_points, x0,y0, 12129 (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); 12130 nk_tt__tesselate_curve(points, num_points, mx,my, 12131 (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); 12132 } else { 12133 nk_tt__add_point(points, *num_points,x2,y2); 12134 *num_points = *num_points+1; 12135 } 12136 return 1; 12137} 12138NK_INTERN struct nk_tt__point* 12139nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts, 12140 float objspace_flatness, int **contour_lengths, int *num_contours, 12141 struct nk_allocator *alloc) 12142{ 12143 /* returns number of contours */ 12144 struct nk_tt__point *points=0; 12145 int num_points=0; 12146 float objspace_flatness_squared = objspace_flatness * objspace_flatness; 12147 int i; 12148 int n=0; 12149 int start=0; 12150 int pass; 12151 12152 /* count how many "moves" there are to get the contour count */ 12153 for (i=0; i < num_verts; ++i) 12154 if (vertices[i].type == NK_TT_vmove) ++n; 12155 12156 *num_contours = n; 12157 if (n == 0) return 0; 12158 12159 *contour_lengths = (int *) 12160 alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n)); 12161 if (*contour_lengths == 0) { 12162 *num_contours = 0; 12163 return 0; 12164 } 12165 12166 /* make two passes through the points so we don't need to realloc */ 12167 for (pass=0; pass < 2; ++pass) 12168 { 12169 float x=0,y=0; 12170 if (pass == 1) { 12171 points = (struct nk_tt__point *) 12172 alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0])); 12173 if (points == 0) goto error; 12174 } 12175 num_points = 0; 12176 n= -1; 12177 12178 for (i=0; i < num_verts; ++i) 12179 { 12180 switch (vertices[i].type) { 12181 case NK_TT_vmove: 12182 /* start the next contour */ 12183 if (n >= 0) 12184 (*contour_lengths)[n] = num_points - start; 12185 ++n; 12186 start = num_points; 12187 12188 x = vertices[i].x, y = vertices[i].y; 12189 nk_tt__add_point(points, num_points++, x,y); 12190 break; 12191 case NK_TT_vline: 12192 x = vertices[i].x, y = vertices[i].y; 12193 nk_tt__add_point(points, num_points++, x, y); 12194 break; 12195 case NK_TT_vcurve: 12196 nk_tt__tesselate_curve(points, &num_points, x,y, 12197 vertices[i].cx, vertices[i].cy, 12198 vertices[i].x, vertices[i].y, 12199 objspace_flatness_squared, 0); 12200 x = vertices[i].x, y = vertices[i].y; 12201 break; 12202 default: break; 12203 } 12204 } 12205 (*contour_lengths)[n] = num_points - start; 12206 } 12207 return points; 12208 12209error: 12210 alloc->free(alloc->userdata, points); 12211 alloc->free(alloc->userdata, *contour_lengths); 12212 *contour_lengths = 0; 12213 *num_contours = 0; 12214 return 0; 12215} 12216NK_INTERN void 12217nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels, 12218 struct nk_tt_vertex *vertices, int num_verts, 12219 float scale_x, float scale_y, float shift_x, float shift_y, 12220 int x_off, int y_off, int invert, struct nk_allocator *alloc) 12221{ 12222 float scale = scale_x > scale_y ? scale_y : scale_x; 12223 int winding_count, *winding_lengths; 12224 struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts, 12225 flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc); 12226 12227 NK_ASSERT(alloc); 12228 if (windings) { 12229 nk_tt__rasterize(result, windings, winding_lengths, winding_count, 12230 scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc); 12231 alloc->free(alloc->userdata, winding_lengths); 12232 alloc->free(alloc->userdata, windings); 12233 } 12234} 12235NK_INTERN void 12236nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output, 12237 int out_w, int out_h, int out_stride, float scale_x, float scale_y, 12238 float shift_x, float shift_y, int glyph, struct nk_allocator *alloc) 12239{ 12240 int ix0,iy0; 12241 struct nk_tt_vertex *vertices; 12242 int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices); 12243 struct nk_tt__bitmap gbm; 12244 12245 nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, 12246 shift_y, &ix0,&iy0,0,0); 12247 gbm.pixels = output; 12248 gbm.w = out_w; 12249 gbm.h = out_h; 12250 gbm.stride = out_stride; 12251 12252 if (gbm.w && gbm.h) 12253 nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, 12254 shift_x, shift_y, ix0,iy0, 1, alloc); 12255 alloc->free(alloc->userdata, vertices); 12256} 12257 12258/*------------------------------------------------------------- 12259 * Bitmap baking 12260 * --------------------------------------------------------------*/ 12261NK_INTERN int 12262nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels, 12263 int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc) 12264{ 12265 int num_nodes = pw - padding; 12266 struct nk_rp_context *context = (struct nk_rp_context *) 12267 alloc->alloc(alloc->userdata,0, sizeof(*context)); 12268 struct nk_rp_node *nodes = (struct nk_rp_node*) 12269 alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes)); 12270 12271 if (context == 0 || nodes == 0) { 12272 if (context != 0) alloc->free(alloc->userdata, context); 12273 if (nodes != 0) alloc->free(alloc->userdata, nodes); 12274 return 0; 12275 } 12276 12277 spc->width = pw; 12278 spc->height = ph; 12279 spc->pixels = pixels; 12280 spc->pack_info = context; 12281 spc->nodes = nodes; 12282 spc->padding = padding; 12283 spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw; 12284 spc->h_oversample = 1; 12285 spc->v_oversample = 1; 12286 12287 nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); 12288 if (pixels) 12289 NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */ 12290 return 1; 12291} 12292NK_INTERN void 12293nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc) 12294{ 12295 alloc->free(alloc->userdata, spc->nodes); 12296 alloc->free(alloc->userdata, spc->pack_info); 12297} 12298NK_INTERN void 12299nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc, 12300 unsigned int h_oversample, unsigned int v_oversample) 12301{ 12302 NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE); 12303 NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE); 12304 if (h_oversample <= NK_TT_MAX_OVERSAMPLE) 12305 spc->h_oversample = h_oversample; 12306 if (v_oversample <= NK_TT_MAX_OVERSAMPLE) 12307 spc->v_oversample = v_oversample; 12308} 12309NK_INTERN void 12310nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, 12311 int kernel_width) 12312{ 12313 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; 12314 int safe_w = w - kernel_width; 12315 int j; 12316 12317 for (j=0; j < h; ++j) 12318 { 12319 int i; 12320 unsigned int total; 12321 NK_MEMSET(buffer, 0, (nk_size)kernel_width); 12322 12323 total = 0; 12324 12325 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 12326 switch (kernel_width) { 12327 case 2: 12328 for (i=0; i <= safe_w; ++i) { 12329 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12330 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12331 pixels[i] = (unsigned char) (total / 2); 12332 } 12333 break; 12334 case 3: 12335 for (i=0; i <= safe_w; ++i) { 12336 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12337 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12338 pixels[i] = (unsigned char) (total / 3); 12339 } 12340 break; 12341 case 4: 12342 for (i=0; i <= safe_w; ++i) { 12343 total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK]; 12344 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12345 pixels[i] = (unsigned char) (total / 4); 12346 } 12347 break; 12348 case 5: 12349 for (i=0; i <= safe_w; ++i) { 12350 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12351 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12352 pixels[i] = (unsigned char) (total / 5); 12353 } 12354 break; 12355 default: 12356 for (i=0; i <= safe_w; ++i) { 12357 total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); 12358 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; 12359 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); 12360 } 12361 break; 12362 } 12363 12364 for (; i < w; ++i) { 12365 NK_ASSERT(pixels[i] == 0); 12366 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); 12367 pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); 12368 } 12369 pixels += stride_in_bytes; 12370 } 12371} 12372NK_INTERN void 12373nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, 12374 int kernel_width) 12375{ 12376 unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; 12377 int safe_h = h - kernel_width; 12378 int j; 12379 12380 for (j=0; j < w; ++j) 12381 { 12382 int i; 12383 unsigned int total; 12384 NK_MEMSET(buffer, 0, (nk_size)kernel_width); 12385 12386 total = 0; 12387 12388 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 12389 switch (kernel_width) { 12390 case 2: 12391 for (i=0; i <= safe_h; ++i) { 12392 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12393 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12394 pixels[i*stride_in_bytes] = (unsigned char) (total / 2); 12395 } 12396 break; 12397 case 3: 12398 for (i=0; i <= safe_h; ++i) { 12399 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12400 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12401 pixels[i*stride_in_bytes] = (unsigned char) (total / 3); 12402 } 12403 break; 12404 case 4: 12405 for (i=0; i <= safe_h; ++i) { 12406 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12407 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12408 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); 12409 } 12410 break; 12411 case 5: 12412 for (i=0; i <= safe_h; ++i) { 12413 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12414 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12415 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); 12416 } 12417 break; 12418 default: 12419 for (i=0; i <= safe_h; ++i) { 12420 total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); 12421 buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; 12422 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); 12423 } 12424 break; 12425 } 12426 12427 for (; i < h; ++i) { 12428 NK_ASSERT(pixels[i*stride_in_bytes] == 0); 12429 total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); 12430 pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); 12431 } 12432 pixels += 1; 12433 } 12434} 12435NK_INTERN float 12436nk_tt__oversample_shift(int oversample) 12437{ 12438 if (!oversample) 12439 return 0.0f; 12440 12441 /* The prefilter is a box filter of width "oversample", */ 12442 /* which shifts phase by (oversample - 1)/2 pixels in */ 12443 /* oversampled space. We want to shift in the opposite */ 12444 /* direction to counter this. */ 12445 return (float)-(oversample - 1) / (2.0f * (float)oversample); 12446} 12447NK_INTERN int 12448nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc, 12449 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, 12450 int num_ranges, struct nk_rp_rect *rects) 12451{ 12452 /* rects array must be big enough to accommodate all characters in the given ranges */ 12453 int i,j,k; 12454 k = 0; 12455 12456 for (i=0; i < num_ranges; ++i) { 12457 float fh = ranges[i].font_size; 12458 float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh): 12459 nk_tt_ScaleForMappingEmToPixels(info, -fh); 12460 ranges[i].h_oversample = (unsigned char) spc->h_oversample; 12461 ranges[i].v_oversample = (unsigned char) spc->v_oversample; 12462 for (j=0; j < ranges[i].num_chars; ++j) { 12463 int x0,y0,x1,y1; 12464 int codepoint = ranges[i].first_unicode_codepoint_in_range ? 12465 ranges[i].first_unicode_codepoint_in_range + j : 12466 ranges[i].array_of_unicode_codepoints[j]; 12467 12468 int glyph = nk_tt_FindGlyphIndex(info, codepoint); 12469 nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample, 12470 scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); 12471 rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1); 12472 rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1); 12473 ++k; 12474 } 12475 } 12476 return k; 12477} 12478NK_INTERN int 12479nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc, 12480 struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, 12481 int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc) 12482{ 12483 int i,j,k, return_value = 1; 12484 /* save current values */ 12485 int old_h_over = (int)spc->h_oversample; 12486 int old_v_over = (int)spc->v_oversample; 12487 /* rects array must be big enough to accommodate all characters in the given ranges */ 12488 12489 k = 0; 12490 for (i=0; i < num_ranges; ++i) 12491 { 12492 float fh = ranges[i].font_size; 12493 float recip_h,recip_v,sub_x,sub_y; 12494 float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh): 12495 nk_tt_ScaleForMappingEmToPixels(info, -fh); 12496 12497 spc->h_oversample = ranges[i].h_oversample; 12498 spc->v_oversample = ranges[i].v_oversample; 12499 12500 recip_h = 1.0f / (float)spc->h_oversample; 12501 recip_v = 1.0f / (float)spc->v_oversample; 12502 12503 sub_x = nk_tt__oversample_shift((int)spc->h_oversample); 12504 sub_y = nk_tt__oversample_shift((int)spc->v_oversample); 12505 12506 for (j=0; j < ranges[i].num_chars; ++j) 12507 { 12508 struct nk_rp_rect *r = &rects[k]; 12509 if (r->was_packed) 12510 { 12511 struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j]; 12512 int advance, lsb, x0,y0,x1,y1; 12513 int codepoint = ranges[i].first_unicode_codepoint_in_range ? 12514 ranges[i].first_unicode_codepoint_in_range + j : 12515 ranges[i].array_of_unicode_codepoints[j]; 12516 int glyph = nk_tt_FindGlyphIndex(info, codepoint); 12517 nk_rp_coord pad = (nk_rp_coord) spc->padding; 12518 12519 /* pad on left and top */ 12520 r->x = (nk_rp_coord)((int)r->x + (int)pad); 12521 r->y = (nk_rp_coord)((int)r->y + (int)pad); 12522 r->w = (nk_rp_coord)((int)r->w - (int)pad); 12523 r->h = (nk_rp_coord)((int)r->h - (int)pad); 12524 12525 nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb); 12526 nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample, 12527 (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1); 12528 nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, 12529 (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1), 12530 spc->stride_in_bytes, scale * (float)spc->h_oversample, 12531 scale * (float)spc->v_oversample, 0,0, glyph, alloc); 12532 12533 if (spc->h_oversample > 1) 12534 nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 12535 r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample); 12536 12537 if (spc->v_oversample > 1) 12538 nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 12539 r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample); 12540 12541 bc->x0 = (nk_ushort) r->x; 12542 bc->y0 = (nk_ushort) r->y; 12543 bc->x1 = (nk_ushort) (r->x + r->w); 12544 bc->y1 = (nk_ushort) (r->y + r->h); 12545 bc->xadvance = scale * (float)advance; 12546 bc->xoff = (float) x0 * recip_h + sub_x; 12547 bc->yoff = (float) y0 * recip_v + sub_y; 12548 bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x; 12549 bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y; 12550 } else { 12551 return_value = 0; /* if any fail, report failure */ 12552 } 12553 ++k; 12554 } 12555 } 12556 /* restore original values */ 12557 spc->h_oversample = (unsigned int)old_h_over; 12558 spc->v_oversample = (unsigned int)old_v_over; 12559 return return_value; 12560} 12561NK_INTERN void 12562nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph, 12563 int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q, 12564 int align_to_integer) 12565{ 12566 float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph; 12567 struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index); 12568 if (align_to_integer) { 12569 int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f); 12570 int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f); 12571 12572 float x = (float)tx; 12573 float y = (float)ty; 12574 12575 q->x0 = x; 12576 q->y0 = y; 12577 q->x1 = x + b->xoff2 - b->xoff; 12578 q->y1 = y + b->yoff2 - b->yoff; 12579 } else { 12580 q->x0 = *xpos + b->xoff; 12581 q->y0 = *ypos + b->yoff; 12582 q->x1 = *xpos + b->xoff2; 12583 q->y1 = *ypos + b->yoff2; 12584 } 12585 q->s0 = b->x0 * ipw; 12586 q->t0 = b->y0 * iph; 12587 q->s1 = b->x1 * ipw; 12588 q->t1 = b->y1 * iph; 12589 *xpos += b->xadvance; 12590} 12591 12592/* ------------------------------------------------------------- 12593 * 12594 * FONT BAKING 12595 * 12596 * --------------------------------------------------------------*/ 12597struct nk_font_bake_data { 12598 struct nk_tt_fontinfo info; 12599 struct nk_rp_rect *rects; 12600 struct nk_tt_pack_range *ranges; 12601 nk_rune range_count; 12602}; 12603 12604struct nk_font_baker { 12605 struct nk_allocator alloc; 12606 struct nk_tt_pack_context spc; 12607 struct nk_font_bake_data *build; 12608 struct nk_tt_packedchar *packed_chars; 12609 struct nk_rp_rect *rects; 12610 struct nk_tt_pack_range *ranges; 12611}; 12612 12613NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect); 12614NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range); 12615NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar); 12616NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data); 12617NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker); 12618 12619NK_INTERN int 12620nk_range_count(const nk_rune *range) 12621{ 12622 const nk_rune *iter = range; 12623 NK_ASSERT(range); 12624 if (!range) return 0; 12625 while (*(iter++) != 0); 12626 return (iter == range) ? 0 : (int)((iter - range)/2); 12627} 12628NK_INTERN int 12629nk_range_glyph_count(const nk_rune *range, int count) 12630{ 12631 int i = 0; 12632 int total_glyphs = 0; 12633 for (i = 0; i < count; ++i) { 12634 int diff; 12635 nk_rune f = range[(i*2)+0]; 12636 nk_rune t = range[(i*2)+1]; 12637 NK_ASSERT(t >= f); 12638 diff = (int)((t - f) + 1); 12639 total_glyphs += diff; 12640 } 12641 return total_glyphs; 12642} 12643NK_API const nk_rune* 12644nk_font_default_glyph_ranges(void) 12645{ 12646 NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0}; 12647 return ranges; 12648} 12649NK_API const nk_rune* 12650nk_font_chinese_glyph_ranges(void) 12651{ 12652 NK_STORAGE const nk_rune ranges[] = { 12653 0x0020, 0x00FF, 12654 0x3000, 0x30FF, 12655 0x31F0, 0x31FF, 12656 0xFF00, 0xFFEF, 12657 0x4e00, 0x9FAF, 12658 0 12659 }; 12660 return ranges; 12661} 12662NK_API const nk_rune* 12663nk_font_cyrillic_glyph_ranges(void) 12664{ 12665 NK_STORAGE const nk_rune ranges[] = { 12666 0x0020, 0x00FF, 12667 0x0400, 0x052F, 12668 0x2DE0, 0x2DFF, 12669 0xA640, 0xA69F, 12670 0 12671 }; 12672 return ranges; 12673} 12674NK_API const nk_rune* 12675nk_font_korean_glyph_ranges(void) 12676{ 12677 NK_STORAGE const nk_rune ranges[] = { 12678 0x0020, 0x00FF, 12679 0x3131, 0x3163, 12680 0xAC00, 0xD79D, 12681 0 12682 }; 12683 return ranges; 12684} 12685NK_INTERN void 12686nk_font_baker_memory(nk_size *temp, int *glyph_count, 12687 struct nk_font_config *config_list, int count) 12688{ 12689 int range_count = 0; 12690 int total_range_count = 0; 12691 struct nk_font_config *iter, *i; 12692 12693 NK_ASSERT(config_list); 12694 NK_ASSERT(glyph_count); 12695 if (!config_list) { 12696 *temp = 0; 12697 *glyph_count = 0; 12698 return; 12699 } 12700 *glyph_count = 0; 12701 for (iter = config_list; iter; iter = iter->next) { 12702 i = iter; 12703 do {if (!i->range) iter->range = nk_font_default_glyph_ranges(); 12704 range_count = nk_range_count(i->range); 12705 total_range_count += range_count; 12706 *glyph_count += nk_range_glyph_count(i->range, range_count); 12707 } while ((i = i->n) != iter); 12708 } 12709 *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect); 12710 *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range); 12711 *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar); 12712 *temp += (nk_size)count * sizeof(struct nk_font_bake_data); 12713 *temp += sizeof(struct nk_font_baker); 12714 *temp += nk_rect_align + nk_range_align + nk_char_align; 12715 *temp += nk_build_align + nk_baker_align; 12716} 12717NK_INTERN struct nk_font_baker* 12718nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc) 12719{ 12720 struct nk_font_baker *baker; 12721 if (!memory) return 0; 12722 /* setup baker inside a memory block */ 12723 baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align); 12724 baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align); 12725 baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align); 12726 baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align); 12727 baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align); 12728 baker->alloc = *alloc; 12729 return baker; 12730} 12731NK_INTERN int 12732nk_font_bake_pack(struct nk_font_baker *baker, 12733 nk_size *image_memory, int *width, int *height, struct nk_recti *custom, 12734 const struct nk_font_config *config_list, int count, 12735 struct nk_allocator *alloc) 12736{ 12737 NK_STORAGE const nk_size max_height = 1024 * 32; 12738 const struct nk_font_config *config_iter, *it; 12739 int total_glyph_count = 0; 12740 int total_range_count = 0; 12741 int range_count = 0; 12742 int i = 0; 12743 12744 NK_ASSERT(image_memory); 12745 NK_ASSERT(width); 12746 NK_ASSERT(height); 12747 NK_ASSERT(config_list); 12748 NK_ASSERT(count); 12749 NK_ASSERT(alloc); 12750 12751 if (!image_memory || !width || !height || !config_list || !count) return nk_false; 12752 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 12753 it = config_iter; 12754 do {range_count = nk_range_count(it->range); 12755 total_range_count += range_count; 12756 total_glyph_count += nk_range_glyph_count(it->range, range_count); 12757 } while ((it = it->n) != config_iter); 12758 } 12759 /* setup font baker from temporary memory */ 12760 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 12761 it = config_iter; 12762 do {if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)it->ttf_blob, 0)) 12763 return nk_false; 12764 } while ((it = it->n) != config_iter); 12765 } 12766 *height = 0; 12767 *width = (total_glyph_count > 1000) ? 1024 : 512; 12768 nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc); 12769 { 12770 int input_i = 0; 12771 int range_n = 0; 12772 int rect_n = 0; 12773 int char_n = 0; 12774 12775 if (custom) { 12776 /* pack custom user data first so it will be in the upper left corner*/ 12777 struct nk_rp_rect custom_space; 12778 nk_zero(&custom_space, sizeof(custom_space)); 12779 custom_space.w = (nk_rp_coord)(custom->w); 12780 custom_space.h = (nk_rp_coord)(custom->h); 12781 12782 nk_tt_PackSetOversampling(&baker->spc, 1, 1); 12783 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1); 12784 *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h)); 12785 12786 custom->x = (short)custom_space.x; 12787 custom->y = (short)custom_space.y; 12788 custom->w = (short)custom_space.w; 12789 custom->h = (short)custom_space.h; 12790 } 12791 12792 /* first font pass: pack all glyphs */ 12793 for (input_i = 0, config_iter = config_list; input_i < count && config_iter; 12794 config_iter = config_iter->next) { 12795 it = config_iter; 12796 do {int n = 0; 12797 int glyph_count; 12798 const nk_rune *in_range; 12799 const struct nk_font_config *cfg = it; 12800 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12801 12802 /* count glyphs + ranges in current font */ 12803 glyph_count = 0; range_count = 0; 12804 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) { 12805 glyph_count += (int)(in_range[1] - in_range[0]) + 1; 12806 range_count++; 12807 } 12808 12809 /* setup ranges */ 12810 tmp->ranges = baker->ranges + range_n; 12811 tmp->range_count = (nk_rune)range_count; 12812 range_n += range_count; 12813 for (i = 0; i < range_count; ++i) { 12814 in_range = &cfg->range[i * 2]; 12815 tmp->ranges[i].font_size = cfg->size; 12816 tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0]; 12817 tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1; 12818 tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n; 12819 char_n += tmp->ranges[i].num_chars; 12820 } 12821 12822 /* pack */ 12823 tmp->rects = baker->rects + rect_n; 12824 rect_n += glyph_count; 12825 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 12826 n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info, 12827 tmp->ranges, (int)tmp->range_count, tmp->rects); 12828 nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n); 12829 12830 /* texture height */ 12831 for (i = 0; i < n; ++i) { 12832 if (tmp->rects[i].was_packed) 12833 *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h); 12834 } 12835 } while ((it = it->n) != config_iter); 12836 } 12837 NK_ASSERT(rect_n == total_glyph_count); 12838 NK_ASSERT(char_n == total_glyph_count); 12839 NK_ASSERT(range_n == total_range_count); 12840 } 12841 *height = (int)nk_round_up_pow2((nk_uint)*height); 12842 *image_memory = (nk_size)(*width) * (nk_size)(*height); 12843 return nk_true; 12844} 12845NK_INTERN void 12846nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height, 12847 struct nk_font_glyph *glyphs, int glyphs_count, 12848 const struct nk_font_config *config_list, int font_count) 12849{ 12850 int input_i = 0; 12851 nk_rune glyph_n = 0; 12852 const struct nk_font_config *config_iter; 12853 const struct nk_font_config *it; 12854 12855 NK_ASSERT(image_memory); 12856 NK_ASSERT(width); 12857 NK_ASSERT(height); 12858 NK_ASSERT(config_list); 12859 NK_ASSERT(baker); 12860 NK_ASSERT(font_count); 12861 NK_ASSERT(glyphs_count); 12862 if (!image_memory || !width || !height || !config_list || 12863 !font_count || !glyphs || !glyphs_count) 12864 return; 12865 12866 /* second font pass: render glyphs */ 12867 nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height)); 12868 baker->spc.pixels = (unsigned char*)image_memory; 12869 baker->spc.height = (int)height; 12870 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 12871 config_iter = config_iter->next) { 12872 it = config_iter; 12873 do {const struct nk_font_config *cfg = it; 12874 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12875 nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 12876 nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, 12877 (int)tmp->range_count, tmp->rects, &baker->alloc); 12878 } while ((it = it->n) != config_iter); 12879 } nk_tt_PackEnd(&baker->spc, &baker->alloc); 12880 12881 /* third pass: setup font and glyphs */ 12882 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 12883 config_iter = config_iter->next) { 12884 it = config_iter; 12885 do {nk_size i = 0; 12886 int char_idx = 0; 12887 nk_rune glyph_count = 0; 12888 const struct nk_font_config *cfg = it; 12889 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 12890 struct nk_baked_font *dst_font = cfg->font; 12891 12892 float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size); 12893 int unscaled_ascent, unscaled_descent, unscaled_line_gap; 12894 nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent, 12895 &unscaled_line_gap); 12896 12897 /* fill baked font */ 12898 if (!cfg->merge_mode) { 12899 dst_font->ranges = cfg->range; 12900 dst_font->height = cfg->size; 12901 dst_font->ascent = ((float)unscaled_ascent * font_scale); 12902 dst_font->descent = ((float)unscaled_descent * font_scale); 12903 dst_font->glyph_offset = glyph_n; 12904 // Need to zero this, or it will carry over from a previous 12905 // bake, and cause a segfault when accessing glyphs[]. 12906 dst_font->glyph_count = 0; 12907 } 12908 12909 /* fill own baked font glyph array */ 12910 for (i = 0; i < tmp->range_count; ++i) { 12911 struct nk_tt_pack_range *range = &tmp->ranges[i]; 12912 for (char_idx = 0; char_idx < range->num_chars; char_idx++) 12913 { 12914 nk_rune codepoint = 0; 12915 float dummy_x = 0, dummy_y = 0; 12916 struct nk_tt_aligned_quad q; 12917 struct nk_font_glyph *glyph; 12918 12919 /* query glyph bounds from stb_truetype */ 12920 const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx]; 12921 if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue; 12922 codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx); 12923 nk_tt_GetPackedQuad(range->chardata_for_range, (int)width, 12924 (int)height, char_idx, &dummy_x, &dummy_y, &q, 0); 12925 12926 /* fill own glyph type with data */ 12927 glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count]; 12928 glyph->codepoint = codepoint; 12929 glyph->x0 = q.x0; glyph->y0 = q.y0; 12930 glyph->x1 = q.x1; glyph->y1 = q.y1; 12931 glyph->y0 += (dst_font->ascent + 0.5f); 12932 glyph->y1 += (dst_font->ascent + 0.5f); 12933 glyph->w = glyph->x1 - glyph->x0 + 0.5f; 12934 glyph->h = glyph->y1 - glyph->y0; 12935 12936 if (cfg->coord_type == NK_COORD_PIXEL) { 12937 glyph->u0 = q.s0 * (float)width; 12938 glyph->v0 = q.t0 * (float)height; 12939 glyph->u1 = q.s1 * (float)width; 12940 glyph->v1 = q.t1 * (float)height; 12941 } else { 12942 glyph->u0 = q.s0; 12943 glyph->v0 = q.t0; 12944 glyph->u1 = q.s1; 12945 glyph->v1 = q.t1; 12946 } 12947 glyph->xadvance = (pc->xadvance + cfg->spacing.x); 12948 if (cfg->pixel_snap) 12949 glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f); 12950 glyph_count++; 12951 } 12952 } 12953 dst_font->glyph_count += glyph_count; 12954 glyph_n += glyph_count; 12955 } while ((it = it->n) != config_iter); 12956 } 12957} 12958NK_INTERN void 12959nk_font_bake_custom_data(void *img_memory, int img_width, int img_height, 12960 struct nk_recti img_dst, const char *texture_data_mask, int tex_width, 12961 int tex_height, char white, char black) 12962{ 12963 nk_byte *pixels; 12964 int y = 0; 12965 int x = 0; 12966 int n = 0; 12967 12968 NK_ASSERT(img_memory); 12969 NK_ASSERT(img_width); 12970 NK_ASSERT(img_height); 12971 NK_ASSERT(texture_data_mask); 12972 NK_UNUSED(tex_height); 12973 if (!img_memory || !img_width || !img_height || !texture_data_mask) 12974 return; 12975 12976 pixels = (nk_byte*)img_memory; 12977 for (y = 0, n = 0; y < tex_height; ++y) { 12978 for (x = 0; x < tex_width; ++x, ++n) { 12979 const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width); 12980 const int off1 = off0 + 1 + tex_width; 12981 pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00; 12982 pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00; 12983 } 12984 } 12985} 12986NK_INTERN void 12987nk_font_bake_convert(void *out_memory, int img_width, int img_height, 12988 const void *in_memory) 12989{ 12990 int n = 0; 12991 nk_rune *dst; 12992 const nk_byte *src; 12993 12994 NK_ASSERT(out_memory); 12995 NK_ASSERT(in_memory); 12996 NK_ASSERT(img_width); 12997 NK_ASSERT(img_height); 12998 if (!out_memory || !in_memory || !img_height || !img_width) return; 12999 13000 dst = (nk_rune*)out_memory; 13001 src = (const nk_byte*)in_memory; 13002 for (n = (int)(img_width * img_height); n > 0; n--) 13003 *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF; 13004} 13005 13006/* ------------------------------------------------------------- 13007 * 13008 * FONT 13009 * 13010 * --------------------------------------------------------------*/ 13011NK_INTERN float 13012nk_font_text_width(nk_handle handle, float height, const char *text, int len) 13013{ 13014 nk_rune unicode; 13015 int text_len = 0; 13016 float text_width = 0; 13017 int glyph_len = 0; 13018 float scale = 0; 13019 13020 struct nk_font *font = (struct nk_font*)handle.ptr; 13021 NK_ASSERT(font); 13022 NK_ASSERT(font->glyphs); 13023 if (!font || !text || !len) 13024 return 0; 13025 13026 scale = height/font->info.height; 13027 glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len); 13028 if (!glyph_len) return 0; 13029 while (text_len <= (int)len && glyph_len) { 13030 const struct nk_font_glyph *g; 13031 if (unicode == NK_UTF_INVALID) break; 13032 13033 /* query currently drawn glyph information */ 13034 g = nk_font_find_glyph(font, unicode); 13035 text_width += g->xadvance * scale; 13036 13037 /* offset next glyph */ 13038 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len); 13039 text_len += glyph_len; 13040 } 13041 return text_width; 13042} 13043#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13044NK_INTERN void 13045nk_font_query_font_glyph(nk_handle handle, float height, 13046 struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 13047{ 13048 float scale; 13049 const struct nk_font_glyph *g; 13050 struct nk_font *font; 13051 13052 NK_ASSERT(glyph); 13053 NK_UNUSED(next_codepoint); 13054 13055 font = (struct nk_font*)handle.ptr; 13056 NK_ASSERT(font); 13057 NK_ASSERT(font->glyphs); 13058 if (!font || !glyph) 13059 return; 13060 13061 scale = height/font->info.height; 13062 g = nk_font_find_glyph(font, codepoint); 13063 glyph->width = (g->x1 - g->x0) * scale; 13064 glyph->height = (g->y1 - g->y0) * scale; 13065 glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); 13066 glyph->xadvance = (g->xadvance * scale); 13067 glyph->uv[0] = nk_vec2(g->u0, g->v0); 13068 glyph->uv[1] = nk_vec2(g->u1, g->v1); 13069} 13070#endif 13071NK_API const struct nk_font_glyph* 13072nk_font_find_glyph(struct nk_font *font, nk_rune unicode) 13073{ 13074 int i = 0; 13075 int count; 13076 int total_glyphs = 0; 13077 const struct nk_font_glyph *glyph = 0; 13078 const struct nk_font_config *iter = 0; 13079 13080 NK_ASSERT(font); 13081 NK_ASSERT(font->glyphs); 13082 NK_ASSERT(font->info.ranges); 13083 if (!font || !font->glyphs) return 0; 13084 13085 glyph = font->fallback; 13086 iter = font->config; 13087 do {count = nk_range_count(iter->range); 13088 for (i = 0; i < count; ++i) { 13089 nk_rune f = iter->range[(i*2)+0]; 13090 nk_rune t = iter->range[(i*2)+1]; 13091 int diff = (int)((t - f) + 1); 13092 if (unicode >= f && unicode <= t) 13093 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))]; 13094 total_glyphs += diff; 13095 } 13096 } while ((iter = iter->n) != font->config); 13097 return glyph; 13098} 13099NK_INTERN void 13100nk_font_init(struct nk_font *font, float pixel_height, 13101 nk_rune fallback_codepoint, struct nk_font_glyph *glyphs, 13102 const struct nk_baked_font *baked_font, nk_handle atlas) 13103{ 13104 struct nk_baked_font baked; 13105 NK_ASSERT(font); 13106 NK_ASSERT(glyphs); 13107 NK_ASSERT(baked_font); 13108 if (!font || !glyphs || !baked_font) 13109 return; 13110 13111 baked = *baked_font; 13112 font->fallback = 0; 13113 font->info = baked; 13114 font->scale = (float)pixel_height / (float)font->info.height; 13115 font->glyphs = &glyphs[baked_font->glyph_offset]; 13116 font->texture = atlas; 13117 font->fallback_codepoint = fallback_codepoint; 13118 font->fallback = nk_font_find_glyph(font, fallback_codepoint); 13119 13120 font->handle.height = font->info.height * font->scale; 13121 font->handle.width = nk_font_text_width; 13122 font->handle.userdata.ptr = font; 13123#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13124 font->handle.query = nk_font_query_font_glyph; 13125 font->handle.texture = font->texture; 13126#endif 13127} 13128 13129/* --------------------------------------------------------------------------- 13130 * 13131 * DEFAULT FONT 13132 * 13133 * ProggyClean.ttf 13134 * Copyright (c) 2004, 2005 Tristan Grimmer 13135 * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) 13136 * Download and more information at http://upperbounds.net 13137 *-----------------------------------------------------------------------------*/ 13138#ifdef __clang__ 13139#pragma clang diagnostic push 13140#pragma clang diagnostic ignored "-Woverlength-strings" 13141#elif defined(__GNUC__) || defined(__GNUG__) 13142#pragma GCC diagnostic push 13143#pragma GCC diagnostic ignored "-Woverlength-strings" 13144#endif 13145 13146#ifdef NK_INCLUDE_DEFAULT_FONT 13147 13148NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] = 13149 "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" 13150 "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#" 13151 "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#[email protected]<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL" 13152 "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#[email protected]'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N" 13153 "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+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N" 13154 "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)" 13155 "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" 13156 "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." 13157 "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" 13158 "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(,)" 13159 "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#" 13160 "'/###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" 13161 "_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" 13162 "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/" 13163 "/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" 13164 "%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&#" 13165 "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)(" 13166 "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" 13167 "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" 13168 "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^-" 13169 "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-" 13170 "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" 13171 "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%" 13172 "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]" 13173 "%(?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" 13174 "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:" 13175 "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(" 13176 "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<[email protected];x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<" 13177 "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'?" 13178 "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/;" 13179 ")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" 13180 "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(" 13181 "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" 13182 "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" 13183 "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<-" 13184 "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;[email protected]$m%#QvQS8U@)2Z+3K:AKM5i" 13185 "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7" 13186 ".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@@" 13187 "$&)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*" 13188 "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" 13189 "@-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&#" 13190 "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#" 13191 "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" 13192 "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" 13193 "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&#" 13194 "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" 13195 ":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+" 13196 "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*" 13197 "$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" 13198 ":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" 13199 "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" 13200 "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" 13201 "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" 13202 ":^#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@&]>" 13203 "_>@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%" 13204 "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;" 13205 "^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:" 13206 "+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%" 13207 "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-" 13208 "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*" 13209 "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" 13210 "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-" 13211 "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`" 13212 "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]%/" 13213 "+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" 13214 "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" 13215 "?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" 13216 "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" 13217 ">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'>" 13218 "[%$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" 13219 "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#" 13220 "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$" 13221 "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,)" 13222 "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" 13223 "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" 13224 "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" 13225 "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(#" 13226 ";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&>" 13227 "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#" 13228 "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" 13229 "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#" 13230 "/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-#" 13231 "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#" 13232 "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" 13233 "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" 13234 "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; 13235 13236#endif /* NK_INCLUDE_DEFAULT_FONT */ 13237 13238#define NK_CURSOR_DATA_W 90 13239#define NK_CURSOR_DATA_H 27 13240NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] = 13241{ 13242 "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" 13243 "..- -X.....X- X.X - X.X -X.....X - X.....X" 13244 "--- -XXX.XXX- X...X - X...X -X....X - X....X" 13245 "X - X.X - X.....X - X.....X -X...X - X...X" 13246 "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" 13247 "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" 13248 "X..X - X.X - X.X - X.X -XX X.X - X.X XX" 13249 "X...X - X.X - X.X - XX X.X XX - X.X - X.X " 13250 "X....X - X.X - 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......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " 13253 "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " 13254 "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " 13255 "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " 13256 "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " 13257 "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " 13258 "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " 13259 "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" 13260 "X.X X..X - -X.......X- X.......X - XX XX - " 13261 "XX X..X - - X.....X - X.....X - X.X X.X - " 13262 " X..X - X...X - X...X - X..X X..X - " 13263 " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " 13264 "------------ - X - X -X.....................X- " 13265 " ----------------------------------- X...XXXXXXXXXXXXX...X - " 13266 " - X..X X..X - " 13267 " - X.X X.X - " 13268 " - XX XX - " 13269}; 13270 13271#ifdef __clang__ 13272#pragma clang diagnostic pop 13273#elif defined(__GNUC__) || defined(__GNUG__) 13274#pragma GCC diagnostic pop 13275#endif 13276 13277NK_GLOBAL unsigned char *nk__barrier; 13278NK_GLOBAL unsigned char *nk__barrier2; 13279NK_GLOBAL unsigned char *nk__barrier3; 13280NK_GLOBAL unsigned char *nk__barrier4; 13281NK_GLOBAL unsigned char *nk__dout; 13282 13283NK_INTERN unsigned int 13284nk_decompress_length(unsigned char *input) 13285{ 13286 return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]); 13287} 13288NK_INTERN void 13289nk__match(unsigned char *data, unsigned int length) 13290{ 13291 /* INVERSE of memmove... write each byte before copying the next...*/ 13292 NK_ASSERT (nk__dout + length <= nk__barrier); 13293 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 13294 if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; } 13295 while (length--) *nk__dout++ = *data++; 13296} 13297NK_INTERN void 13298nk__lit(unsigned char *data, unsigned int length) 13299{ 13300 NK_ASSERT (nk__dout + length <= nk__barrier); 13301 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 13302 if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; } 13303 NK_MEMCPY(nk__dout, data, length); 13304 nk__dout += length; 13305} 13306NK_INTERN unsigned char* 13307nk_decompress_token(unsigned char *i) 13308{ 13309 #define nk__in2(x) ((i[x] << 8) + i[(x)+1]) 13310 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1)) 13311 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1)) 13312 13313 if (*i >= 0x20) { /* use fewer if's for cases that expand small */ 13314 if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2; 13315 else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3; 13316 else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); 13317 } else { /* more ifs for cases that expand large, since overhead is amortized */ 13318 if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4; 13319 else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5; 13320 else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1); 13321 else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1); 13322 else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5; 13323 else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6; 13324 } 13325 return i; 13326} 13327NK_INTERN unsigned int 13328nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) 13329{ 13330 const unsigned long ADLER_MOD = 65521; 13331 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; 13332 unsigned long blocklen, i; 13333 13334 blocklen = buflen % 5552; 13335 while (buflen) { 13336 for (i=0; i + 7 < blocklen; i += 8) { 13337 s1 += buffer[0]; s2 += s1; 13338 s1 += buffer[1]; s2 += s1; 13339 s1 += buffer[2]; s2 += s1; 13340 s1 += buffer[3]; s2 += s1; 13341 s1 += buffer[4]; s2 += s1; 13342 s1 += buffer[5]; s2 += s1; 13343 s1 += buffer[6]; s2 += s1; 13344 s1 += buffer[7]; s2 += s1; 13345 buffer += 8; 13346 } 13347 for (; i < blocklen; ++i) { 13348 s1 += *buffer++; s2 += s1; 13349 } 13350 13351 s1 %= ADLER_MOD; s2 %= ADLER_MOD; 13352 buflen -= (unsigned int)blocklen; 13353 blocklen = 5552; 13354 } 13355 return (unsigned int)(s2 << 16) + (unsigned int)s1; 13356} 13357NK_INTERN unsigned int 13358nk_decompress(unsigned char *output, unsigned char *i, unsigned int length) 13359{ 13360 unsigned int olen; 13361 if (nk__in4(0) != 0x57bC0000) return 0; 13362 if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */ 13363 olen = nk_decompress_length(i); 13364 nk__barrier2 = i; 13365 nk__barrier3 = i+length; 13366 nk__barrier = output + olen; 13367 nk__barrier4 = output; 13368 i += 16; 13369 13370 nk__dout = output; 13371 for (;;) { 13372 unsigned char *old_i = i; 13373 i = nk_decompress_token(i); 13374 if (i == old_i) { 13375 if (*i == 0x05 && i[1] == 0xfa) { 13376 NK_ASSERT(nk__dout == output + olen); 13377 if (nk__dout != output + olen) return 0; 13378 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2)) 13379 return 0; 13380 return olen; 13381 } else { 13382 NK_ASSERT(0); /* NOTREACHED */ 13383 return 0; 13384 } 13385 } 13386 NK_ASSERT(nk__dout <= output + olen); 13387 if (nk__dout > output + olen) 13388 return 0; 13389 } 13390} 13391NK_INTERN unsigned int 13392nk_decode_85_byte(char c) 13393{ 13394 return (unsigned int)((c >= '\\') ? c-36 : c-35); 13395} 13396NK_INTERN void 13397nk_decode_85(unsigned char* dst, const unsigned char* src) 13398{ 13399 while (*src) 13400 { 13401 unsigned int tmp = 13402 nk_decode_85_byte((char)src[0]) + 13403 85 * (nk_decode_85_byte((char)src[1]) + 13404 85 * (nk_decode_85_byte((char)src[2]) + 13405 85 * (nk_decode_85_byte((char)src[3]) + 13406 85 * nk_decode_85_byte((char)src[4])))); 13407 13408 /* we can't assume little-endianess. */ 13409 dst[0] = (unsigned char)((tmp >> 0) & 0xFF); 13410 dst[1] = (unsigned char)((tmp >> 8) & 0xFF); 13411 dst[2] = (unsigned char)((tmp >> 16) & 0xFF); 13412 dst[3] = (unsigned char)((tmp >> 24) & 0xFF); 13413 13414 src += 5; 13415 dst += 4; 13416 } 13417} 13418 13419/* ------------------------------------------------------------- 13420 * 13421 * FONT ATLAS 13422 * 13423 * --------------------------------------------------------------*/ 13424NK_API struct nk_font_config 13425nk_font_config(float pixel_height) 13426{ 13427 struct nk_font_config cfg; 13428 nk_zero_struct(cfg); 13429 cfg.ttf_blob = 0; 13430 cfg.ttf_size = 0; 13431 cfg.ttf_data_owned_by_atlas = 0; 13432 cfg.size = pixel_height; 13433 cfg.oversample_h = 3; 13434 cfg.oversample_v = 1; 13435 cfg.pixel_snap = 0; 13436 cfg.coord_type = NK_COORD_UV; 13437 cfg.spacing = nk_vec2(0,0); 13438 cfg.range = nk_font_default_glyph_ranges(); 13439 cfg.merge_mode = 0; 13440 cfg.fallback_glyph = '?'; 13441 cfg.font = 0; 13442 cfg.n = 0; 13443 return cfg; 13444} 13445#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 13446NK_API void 13447nk_font_atlas_init_default(struct nk_font_atlas *atlas) 13448{ 13449 NK_ASSERT(atlas); 13450 if (!atlas) return; 13451 nk_zero_struct(*atlas); 13452 atlas->temporary.userdata.ptr = 0; 13453 atlas->temporary.alloc = nk_malloc; 13454 atlas->temporary.free = nk_mfree; 13455 atlas->permanent.userdata.ptr = 0; 13456 atlas->permanent.alloc = nk_malloc; 13457 atlas->permanent.free = nk_mfree; 13458} 13459#endif 13460NK_API void 13461nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc) 13462{ 13463 NK_ASSERT(atlas); 13464 NK_ASSERT(alloc); 13465 if (!atlas || !alloc) return; 13466 nk_zero_struct(*atlas); 13467 atlas->permanent = *alloc; 13468 atlas->temporary = *alloc; 13469} 13470NK_API void 13471nk_font_atlas_init_custom(struct nk_font_atlas *atlas, 13472 struct nk_allocator *permanent, struct nk_allocator *temporary) 13473{ 13474 NK_ASSERT(atlas); 13475 NK_ASSERT(permanent); 13476 NK_ASSERT(temporary); 13477 if (!atlas || !permanent || !temporary) return; 13478 nk_zero_struct(*atlas); 13479 atlas->permanent = *permanent; 13480 atlas->temporary = *temporary; 13481} 13482NK_API void 13483nk_font_atlas_begin(struct nk_font_atlas *atlas) 13484{ 13485 NK_ASSERT(atlas); 13486 NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free); 13487 NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free); 13488 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free || 13489 !atlas->temporary.alloc || !atlas->temporary.free) return; 13490 if (atlas->glyphs) { 13491 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13492 atlas->glyphs = 0; 13493 } 13494 if (atlas->pixel) { 13495 atlas->permanent.free(atlas->permanent.userdata, atlas->pixel); 13496 atlas->pixel = 0; 13497 } 13498} 13499NK_API struct nk_font* 13500nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config) 13501{ 13502 struct nk_font *font = 0; 13503 struct nk_font_config *cfg; 13504 13505 NK_ASSERT(atlas); 13506 NK_ASSERT(atlas->permanent.alloc); 13507 NK_ASSERT(atlas->permanent.free); 13508 NK_ASSERT(atlas->temporary.alloc); 13509 NK_ASSERT(atlas->temporary.free); 13510 13511 NK_ASSERT(config); 13512 NK_ASSERT(config->ttf_blob); 13513 NK_ASSERT(config->ttf_size); 13514 NK_ASSERT(config->size > 0.0f); 13515 13516 if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f|| 13517 !atlas->permanent.alloc || !atlas->permanent.free || 13518 !atlas->temporary.alloc || !atlas->temporary.free) 13519 return 0; 13520 13521 /* allocate font config */ 13522 cfg = (struct nk_font_config*) 13523 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config)); 13524 NK_MEMCPY(cfg, config, sizeof(*config)); 13525 cfg->n = cfg; 13526 cfg->p = cfg; 13527 13528 if (!config->merge_mode) { 13529 /* insert font config into list */ 13530 if (!atlas->config) { 13531 atlas->config = cfg; 13532 cfg->next = 0; 13533 } else { 13534 struct nk_font_config *i = atlas->config; 13535 while (i->next) i = i->next; 13536 i->next = cfg; 13537 cfg->next = 0; 13538 } 13539 /* allocate new font */ 13540 font = (struct nk_font*) 13541 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font)); 13542 NK_ASSERT(font); 13543 nk_zero(font, sizeof(*font)); 13544 if (!font) return 0; 13545 font->config = cfg; 13546 13547 /* insert font into list */ 13548 if (!atlas->fonts) { 13549 atlas->fonts = font; 13550 font->next = 0; 13551 } else { 13552 struct nk_font *i = atlas->fonts; 13553 while (i->next) i = i->next; 13554 i->next = font; 13555 font->next = 0; 13556 } 13557 cfg->font = &font->info; 13558 } else { 13559 /* extend previously added font */ 13560 struct nk_font *f = 0; 13561 struct nk_font_config *c = 0; 13562 NK_ASSERT(atlas->font_num); 13563 f = atlas->fonts; 13564 c = f->config; 13565 cfg->font = &f->info; 13566 13567 cfg->n = c; 13568 cfg->p = c->p; 13569 c->p->n = cfg; 13570 c->p = cfg; 13571 } 13572 /* create own copy of .TTF font blob */ 13573 if (!config->ttf_data_owned_by_atlas) { 13574 cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size); 13575 NK_ASSERT(cfg->ttf_blob); 13576 if (!cfg->ttf_blob) { 13577 atlas->font_num++; 13578 return 0; 13579 } 13580 NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size); 13581 cfg->ttf_data_owned_by_atlas = 1; 13582 } 13583 atlas->font_num++; 13584 return font; 13585} 13586NK_API struct nk_font* 13587nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, 13588 nk_size size, float height, const struct nk_font_config *config) 13589{ 13590 struct nk_font_config cfg; 13591 NK_ASSERT(memory); 13592 NK_ASSERT(size); 13593 13594 NK_ASSERT(atlas); 13595 NK_ASSERT(atlas->temporary.alloc); 13596 NK_ASSERT(atlas->temporary.free); 13597 NK_ASSERT(atlas->permanent.alloc); 13598 NK_ASSERT(atlas->permanent.free); 13599 if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size || 13600 !atlas->permanent.alloc || !atlas->permanent.free) 13601 return 0; 13602 13603 cfg = (config) ? *config: nk_font_config(height); 13604 cfg.ttf_blob = memory; 13605 cfg.ttf_size = size; 13606 cfg.size = height; 13607 cfg.ttf_data_owned_by_atlas = 0; 13608 return nk_font_atlas_add(atlas, &cfg); 13609} 13610#ifdef NK_INCLUDE_STANDARD_IO 13611NK_API struct nk_font* 13612nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, 13613 float height, const struct nk_font_config *config) 13614{ 13615 nk_size size; 13616 char *memory; 13617 struct nk_font_config cfg; 13618 13619 NK_ASSERT(atlas); 13620 NK_ASSERT(atlas->temporary.alloc); 13621 NK_ASSERT(atlas->temporary.free); 13622 NK_ASSERT(atlas->permanent.alloc); 13623 NK_ASSERT(atlas->permanent.free); 13624 13625 if (!atlas || !file_path) return 0; 13626 memory = nk_file_load(file_path, &size, &atlas->permanent); 13627 if (!memory) return 0; 13628 13629 cfg = (config) ? *config: nk_font_config(height); 13630 cfg.ttf_blob = memory; 13631 cfg.ttf_size = size; 13632 cfg.size = height; 13633 cfg.ttf_data_owned_by_atlas = 1; 13634 return nk_font_atlas_add(atlas, &cfg); 13635} 13636#endif 13637NK_API struct nk_font* 13638nk_font_atlas_add_compressed(struct nk_font_atlas *atlas, 13639 void *compressed_data, nk_size compressed_size, float height, 13640 const struct nk_font_config *config) 13641{ 13642 unsigned int decompressed_size; 13643 void *decompressed_data; 13644 struct nk_font_config cfg; 13645 13646 NK_ASSERT(atlas); 13647 NK_ASSERT(atlas->temporary.alloc); 13648 NK_ASSERT(atlas->temporary.free); 13649 NK_ASSERT(atlas->permanent.alloc); 13650 NK_ASSERT(atlas->permanent.free); 13651 13652 NK_ASSERT(compressed_data); 13653 NK_ASSERT(compressed_size); 13654 if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free || 13655 !atlas->permanent.alloc || !atlas->permanent.free) 13656 return 0; 13657 13658 decompressed_size = nk_decompress_length((unsigned char*)compressed_data); 13659 decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size); 13660 NK_ASSERT(decompressed_data); 13661 if (!decompressed_data) return 0; 13662 nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data, 13663 (unsigned int)compressed_size); 13664 13665 cfg = (config) ? *config: nk_font_config(height); 13666 cfg.ttf_blob = decompressed_data; 13667 cfg.ttf_size = decompressed_size; 13668 cfg.size = height; 13669 cfg.ttf_data_owned_by_atlas = 1; 13670 return nk_font_atlas_add(atlas, &cfg); 13671} 13672NK_API struct nk_font* 13673nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas, 13674 const char *data_base85, float height, const struct nk_font_config *config) 13675{ 13676 int compressed_size; 13677 void *compressed_data; 13678 struct nk_font *font; 13679 13680 NK_ASSERT(atlas); 13681 NK_ASSERT(atlas->temporary.alloc); 13682 NK_ASSERT(atlas->temporary.free); 13683 NK_ASSERT(atlas->permanent.alloc); 13684 NK_ASSERT(atlas->permanent.free); 13685 13686 NK_ASSERT(data_base85); 13687 if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free || 13688 !atlas->permanent.alloc || !atlas->permanent.free) 13689 return 0; 13690 13691 compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4; 13692 compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size); 13693 NK_ASSERT(compressed_data); 13694 if (!compressed_data) return 0; 13695 nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85); 13696 font = nk_font_atlas_add_compressed(atlas, compressed_data, 13697 (nk_size)compressed_size, height, config); 13698 atlas->temporary.free(atlas->temporary.userdata, compressed_data); 13699 return font; 13700} 13701 13702#ifdef NK_INCLUDE_DEFAULT_FONT 13703NK_API struct nk_font* 13704nk_font_atlas_add_default(struct nk_font_atlas *atlas, 13705 float pixel_height, const struct nk_font_config *config) 13706{ 13707 NK_ASSERT(atlas); 13708 NK_ASSERT(atlas->temporary.alloc); 13709 NK_ASSERT(atlas->temporary.free); 13710 NK_ASSERT(atlas->permanent.alloc); 13711 NK_ASSERT(atlas->permanent.free); 13712 return nk_font_atlas_add_compressed_base85(atlas, 13713 nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config); 13714} 13715#endif 13716NK_API const void* 13717nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height, 13718 enum nk_font_atlas_format fmt) 13719{ 13720 int i = 0; 13721 void *tmp = 0; 13722 nk_size tmp_size, img_size; 13723 struct nk_font *font_iter; 13724 struct nk_font_baker *baker; 13725 13726 NK_ASSERT(atlas); 13727 NK_ASSERT(atlas->temporary.alloc); 13728 NK_ASSERT(atlas->temporary.free); 13729 NK_ASSERT(atlas->permanent.alloc); 13730 NK_ASSERT(atlas->permanent.free); 13731 13732 NK_ASSERT(width); 13733 NK_ASSERT(height); 13734 if (!atlas || !width || !height || 13735 !atlas->temporary.alloc || !atlas->temporary.free || 13736 !atlas->permanent.alloc || !atlas->permanent.free) 13737 return 0; 13738 13739#ifdef NK_INCLUDE_DEFAULT_FONT 13740 /* no font added so just use default font */ 13741 if (!atlas->font_num) 13742 atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0); 13743#endif 13744 NK_ASSERT(atlas->font_num); 13745 if (!atlas->font_num) return 0; 13746 13747 /* allocate temporary baker memory required for the baking process */ 13748 nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num); 13749 tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size); 13750 NK_ASSERT(tmp); 13751 if (!tmp) goto failed; 13752 13753 /* allocate glyph memory for all fonts */ 13754 baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary); 13755 atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc( 13756 atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count); 13757 NK_ASSERT(atlas->glyphs); 13758 if (!atlas->glyphs) 13759 goto failed; 13760 13761 /* pack all glyphs into a tight fit space */ 13762 atlas->custom.w = (NK_CURSOR_DATA_W*2)+1; 13763 atlas->custom.h = NK_CURSOR_DATA_H + 1; 13764 if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom, 13765 atlas->config, atlas->font_num, &atlas->temporary)) 13766 goto failed; 13767 13768 /* allocate memory for the baked image font atlas */ 13769 atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size); 13770 NK_ASSERT(atlas->pixel); 13771 if (!atlas->pixel) 13772 goto failed; 13773 13774 /* bake glyphs and custom white pixel into image */ 13775 nk_font_bake(baker, atlas->pixel, *width, *height, 13776 atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num); 13777 nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom, 13778 nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X'); 13779 13780 if (fmt == NK_FONT_ATLAS_RGBA32) { 13781 /* convert alpha8 image into rgba32 image */ 13782 void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0, 13783 (nk_size)(*width * *height * 4)); 13784 NK_ASSERT(img_rgba); 13785 if (!img_rgba) goto failed; 13786 nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel); 13787 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13788 atlas->pixel = img_rgba; 13789 } 13790 atlas->tex_width = *width; 13791 atlas->tex_height = *height; 13792 13793 /* initialize each font */ 13794 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 13795 struct nk_font *font = font_iter; 13796 struct nk_font_config *config = font->config; 13797 nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs, 13798 config->font, nk_handle_ptr(0)); 13799 } 13800 13801 /* initialize each cursor */ 13802 {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = { 13803 /* Pos Size Offset */ 13804 {{ 0, 3}, {12,19}, { 0, 0}}, 13805 {{13, 0}, { 7,16}, { 4, 8}}, 13806 {{31, 0}, {23,23}, {11,11}}, 13807 {{21, 0}, { 9, 23}, { 5,11}}, 13808 {{55,18}, {23, 9}, {11, 5}}, 13809 {{73, 0}, {17,17}, { 9, 9}}, 13810 {{55, 0}, {17,17}, { 9, 9}} 13811 }; 13812 for (i = 0; i < NK_CURSOR_COUNT; ++i) { 13813 struct nk_cursor *cursor = &atlas->cursors[i]; 13814 cursor->img.w = (unsigned short)*width; 13815 cursor->img.h = (unsigned short)*height; 13816 cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x); 13817 cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y); 13818 cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x; 13819 cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y; 13820 cursor->size = nk_cursor_data[i][1]; 13821 cursor->offset = nk_cursor_data[i][2]; 13822 }} 13823 /* free temporary memory */ 13824 atlas->temporary.free(atlas->temporary.userdata, tmp); 13825 return atlas->pixel; 13826 13827failed: 13828 /* error so cleanup all memory */ 13829 if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp); 13830 if (atlas->glyphs) { 13831 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13832 atlas->glyphs = 0; 13833 } 13834 if (atlas->pixel) { 13835 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13836 atlas->pixel = 0; 13837 } 13838 return 0; 13839} 13840NK_API void 13841nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, 13842 struct nk_draw_null_texture *null) 13843{ 13844 int i = 0; 13845 struct nk_font *font_iter; 13846 NK_ASSERT(atlas); 13847 if (!atlas) { 13848 if (!null) return; 13849 null->texture = texture; 13850 null->uv = nk_vec2(0.5f,0.5f); 13851 } 13852 if (null) { 13853 null->texture = texture; 13854 null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; 13855 null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; 13856 } 13857 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 13858 font_iter->texture = texture; 13859#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 13860 font_iter->handle.texture = texture; 13861#endif 13862 } 13863 for (i = 0; i < NK_CURSOR_COUNT; ++i) 13864 atlas->cursors[i].img.handle = texture; 13865 13866 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 13867 atlas->pixel = 0; 13868 atlas->tex_width = 0; 13869 atlas->tex_height = 0; 13870 atlas->custom.x = 0; 13871 atlas->custom.y = 0; 13872 atlas->custom.w = 0; 13873 atlas->custom.h = 0; 13874} 13875NK_API void 13876nk_font_atlas_cleanup(struct nk_font_atlas *atlas) 13877{ 13878 NK_ASSERT(atlas); 13879 NK_ASSERT(atlas->temporary.alloc); 13880 NK_ASSERT(atlas->temporary.free); 13881 NK_ASSERT(atlas->permanent.alloc); 13882 NK_ASSERT(atlas->permanent.free); 13883 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 13884 if (atlas->config) { 13885 struct nk_font_config *iter; 13886 for (iter = atlas->config; iter; iter = iter->next) { 13887 struct nk_font_config *i; 13888 for (i = iter->n; i != iter; i = i->n) { 13889 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 13890 i->ttf_blob = 0; 13891 } 13892 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 13893 iter->ttf_blob = 0; 13894 } 13895 } 13896} 13897NK_API void 13898nk_font_atlas_clear(struct nk_font_atlas *atlas) 13899{ 13900 NK_ASSERT(atlas); 13901 NK_ASSERT(atlas->temporary.alloc); 13902 NK_ASSERT(atlas->temporary.free); 13903 NK_ASSERT(atlas->permanent.alloc); 13904 NK_ASSERT(atlas->permanent.free); 13905 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 13906 13907 if (atlas->config) { 13908 struct nk_font_config *iter, *next; 13909 for (iter = atlas->config; iter; iter = next) { 13910 struct nk_font_config *i, *n; 13911 for (i = iter->n; i != iter; i = n) { 13912 n = i->n; 13913 if (i->ttf_blob) 13914 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 13915 atlas->permanent.free(atlas->permanent.userdata, i); 13916 } 13917 next = iter->next; 13918 if (i->ttf_blob) 13919 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 13920 atlas->permanent.free(atlas->permanent.userdata, iter); 13921 } 13922 atlas->config = 0; 13923 } 13924 if (atlas->fonts) { 13925 struct nk_font *iter, *next; 13926 for (iter = atlas->fonts; iter; iter = next) { 13927 next = iter->next; 13928 atlas->permanent.free(atlas->permanent.userdata, iter); 13929 } 13930 atlas->fonts = 0; 13931 } 13932 if (atlas->glyphs) 13933 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 13934 nk_zero_struct(*atlas); 13935} 13936#endif 13937 13938 13939 13940 13941 13942/* =============================================================== 13943 * 13944 * INPUT 13945 * 13946 * ===============================================================*/ 13947NK_API void 13948nk_input_begin(struct nk_context *ctx) 13949{ 13950 int i; 13951 struct nk_input *in; 13952 NK_ASSERT(ctx); 13953 if (!ctx) return; 13954 in = &ctx->input; 13955 for (i = 0; i < NK_BUTTON_MAX; ++i) 13956 in->mouse.buttons[i].clicked = 0; 13957 13958 in->keyboard.text_len = 0; 13959 in->mouse.scroll_delta = nk_vec2(0,0); 13960 in->mouse.prev.x = in->mouse.pos.x; 13961 in->mouse.prev.y = in->mouse.pos.y; 13962 in->mouse.delta.x = 0; 13963 in->mouse.delta.y = 0; 13964 for (i = 0; i < NK_KEY_MAX; i++) 13965 in->keyboard.keys[i].clicked = 0; 13966} 13967NK_API void 13968nk_input_end(struct nk_context *ctx) 13969{ 13970 struct nk_input *in; 13971 NK_ASSERT(ctx); 13972 if (!ctx) return; 13973 in = &ctx->input; 13974 if (in->mouse.grab) 13975 in->mouse.grab = 0; 13976 if (in->mouse.ungrab) { 13977 in->mouse.grabbed = 0; 13978 in->mouse.ungrab = 0; 13979 in->mouse.grab = 0; 13980 } 13981} 13982NK_API void 13983nk_input_motion(struct nk_context *ctx, int x, int y) 13984{ 13985 struct nk_input *in; 13986 NK_ASSERT(ctx); 13987 if (!ctx) return; 13988 in = &ctx->input; 13989 in->mouse.pos.x = (float)x; 13990 in->mouse.pos.y = (float)y; 13991 in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x; 13992 in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y; 13993} 13994NK_API void 13995nk_input_key(struct nk_context *ctx, enum nk_keys key, int down) 13996{ 13997 struct nk_input *in; 13998 NK_ASSERT(ctx); 13999 if (!ctx) return; 14000 in = &ctx->input; 14001#ifdef NK_KEYSTATE_BASED_INPUT 14002 if (in->keyboard.keys[key].down != down) 14003 in->keyboard.keys[key].clicked++; 14004#else 14005 in->keyboard.keys[key].clicked++; 14006#endif 14007 in->keyboard.keys[key].down = down; 14008} 14009NK_API void 14010nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down) 14011{ 14012 struct nk_mouse_button *btn; 14013 struct nk_input *in; 14014 NK_ASSERT(ctx); 14015 if (!ctx) return; 14016 in = &ctx->input; 14017 if (in->mouse.buttons[id].down == down) return; 14018 14019 btn = &in->mouse.buttons[id]; 14020 btn->clicked_pos.x = (float)x; 14021 btn->clicked_pos.y = (float)y; 14022 btn->down = down; 14023 btn->clicked++; 14024} 14025NK_API void 14026nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val) 14027{ 14028 NK_ASSERT(ctx); 14029 if (!ctx) return; 14030 ctx->input.mouse.scroll_delta.x += val.x; 14031 ctx->input.mouse.scroll_delta.y += val.y; 14032} 14033NK_API void 14034nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph) 14035{ 14036 int len = 0; 14037 nk_rune unicode; 14038 struct nk_input *in; 14039 14040 NK_ASSERT(ctx); 14041 if (!ctx) return; 14042 in = &ctx->input; 14043 14044 len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE); 14045 if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) { 14046 nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len], 14047 NK_INPUT_MAX - in->keyboard.text_len); 14048 in->keyboard.text_len += len; 14049 } 14050} 14051NK_API void 14052nk_input_char(struct nk_context *ctx, char c) 14053{ 14054 nk_glyph glyph; 14055 NK_ASSERT(ctx); 14056 if (!ctx) return; 14057 glyph[0] = c; 14058 nk_input_glyph(ctx, glyph); 14059} 14060NK_API void 14061nk_input_unicode(struct nk_context *ctx, nk_rune unicode) 14062{ 14063 nk_glyph rune; 14064 NK_ASSERT(ctx); 14065 if (!ctx) return; 14066 nk_utf_encode(unicode, rune, NK_UTF_SIZE); 14067 nk_input_glyph(ctx, rune); 14068} 14069NK_API int 14070nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id) 14071{ 14072 const struct nk_mouse_button *btn; 14073 if (!i) return nk_false; 14074 btn = &i->mouse.buttons[id]; 14075 return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false; 14076} 14077NK_API int 14078nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 14079 struct nk_rect b) 14080{ 14081 const struct nk_mouse_button *btn; 14082 if (!i) return nk_false; 14083 btn = &i->mouse.buttons[id]; 14084 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) 14085 return nk_false; 14086 return nk_true; 14087} 14088NK_API int 14089nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 14090 struct nk_rect b, int down) 14091{ 14092 const struct nk_mouse_button *btn; 14093 if (!i) return nk_false; 14094 btn = &i->mouse.buttons[id]; 14095 return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down); 14096} 14097NK_API int 14098nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 14099 struct nk_rect b) 14100{ 14101 const struct nk_mouse_button *btn; 14102 if (!i) return nk_false; 14103 btn = &i->mouse.buttons[id]; 14104 return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) && 14105 btn->clicked) ? nk_true : nk_false; 14106} 14107NK_API int 14108nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 14109 struct nk_rect b, int down) 14110{ 14111 const struct nk_mouse_button *btn; 14112 if (!i) return nk_false; 14113 btn = &i->mouse.buttons[id]; 14114 return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) && 14115 btn->clicked) ? nk_true : nk_false; 14116} 14117NK_API int 14118nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b) 14119{ 14120 int i, down = 0; 14121 for (i = 0; i < NK_BUTTON_MAX; ++i) 14122 down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b); 14123 return down; 14124} 14125NK_API int 14126nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect) 14127{ 14128 if (!i) return nk_false; 14129 return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h); 14130} 14131NK_API int 14132nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect) 14133{ 14134 if (!i) return nk_false; 14135 return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h); 14136} 14137NK_API int 14138nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect) 14139{ 14140 if (!i) return nk_false; 14141 if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false; 14142 return nk_input_is_mouse_click_in_rect(i, id, rect); 14143} 14144NK_API int 14145nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id) 14146{ 14147 if (!i) return nk_false; 14148 return i->mouse.buttons[id].down; 14149} 14150NK_API int 14151nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id) 14152{ 14153 const struct nk_mouse_button *b; 14154 if (!i) return nk_false; 14155 b = &i->mouse.buttons[id]; 14156 if (b->down && b->clicked) 14157 return nk_true; 14158 return nk_false; 14159} 14160NK_API int 14161nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id) 14162{ 14163 if (!i) return nk_false; 14164 return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked); 14165} 14166NK_API int 14167nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key) 14168{ 14169 const struct nk_key *k; 14170 if (!i) return nk_false; 14171 k = &i->keyboard.keys[key]; 14172 if ((k->down && k->clicked) || (!k->down && k->clicked >= 2)) 14173 return nk_true; 14174 return nk_false; 14175} 14176NK_API int 14177nk_input_is_key_released(const struct nk_input *i, enum nk_keys key) 14178{ 14179 const struct nk_key *k; 14180 if (!i) return nk_false; 14181 k = &i->keyboard.keys[key]; 14182 if ((!k->down && k->clicked) || (k->down && k->clicked >= 2)) 14183 return nk_true; 14184 return nk_false; 14185} 14186NK_API int 14187nk_input_is_key_down(const struct nk_input *i, enum nk_keys key) 14188{ 14189 const struct nk_key *k; 14190 if (!i) return nk_false; 14191 k = &i->keyboard.keys[key]; 14192 if (k->down) return nk_true; 14193 return nk_false; 14194} 14195 14196 14197 14198 14199 14200/* =============================================================== 14201 * 14202 * STYLE 14203 * 14204 * ===============================================================*/ 14205NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);} 14206#define NK_COLOR_MAP(NK_COLOR)\ 14207 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \ 14208 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \ 14209 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \ 14210 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \ 14211 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \ 14212 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \ 14213 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \ 14214 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \ 14215 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ 14216 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ 14217 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ 14218 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ 14219 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ 14220 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ 14221 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ 14222 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ 14223 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ 14224 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ 14225 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ 14226 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ 14227 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ 14228 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \ 14229 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \ 14230 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \ 14231 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ 14232 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \ 14233 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \ 14234 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) 14235 14236NK_GLOBAL const struct nk_color 14237nk_default_color_style[NK_COLOR_COUNT] = { 14238#define NK_COLOR(a,b,c,d,e) {b,c,d,e}, 14239 NK_COLOR_MAP(NK_COLOR) 14240#undef NK_COLOR 14241}; 14242NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = { 14243#define NK_COLOR(a,b,c,d,e) #a, 14244 NK_COLOR_MAP(NK_COLOR) 14245#undef NK_COLOR 14246}; 14247 14248NK_API const char* 14249nk_style_get_color_by_name(enum nk_style_colors c) 14250{ 14251 return nk_color_names[c]; 14252} 14253NK_API struct nk_style_item 14254nk_style_item_image(struct nk_image img) 14255{ 14256 struct nk_style_item i; 14257 i.type = NK_STYLE_ITEM_IMAGE; 14258 i.data.image = img; 14259 return i; 14260} 14261NK_API struct nk_style_item 14262nk_style_item_color(struct nk_color col) 14263{ 14264 struct nk_style_item i; 14265 i.type = NK_STYLE_ITEM_COLOR; 14266 i.data.color = col; 14267 return i; 14268} 14269NK_API struct nk_style_item 14270nk_style_item_hide(void) 14271{ 14272 struct nk_style_item i; 14273 i.type = NK_STYLE_ITEM_COLOR; 14274 i.data.color = nk_rgba(0,0,0,0); 14275 return i; 14276} 14277NK_API void 14278nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) 14279{ 14280 struct nk_style *style; 14281 struct nk_style_text *text; 14282 struct nk_style_button *button; 14283 struct nk_style_toggle *toggle; 14284 struct nk_style_selectable *select; 14285 struct nk_style_slider *slider; 14286 struct nk_style_progress *prog; 14287 struct nk_style_scrollbar *scroll; 14288 struct nk_style_edit *edit; 14289 struct nk_style_property *property; 14290 struct nk_style_combo *combo; 14291 struct nk_style_chart *chart; 14292 struct nk_style_tab *tab; 14293 struct nk_style_window *win; 14294 14295 NK_ASSERT(ctx); 14296 if (!ctx) return; 14297 style = &ctx->style; 14298 table = (!table) ? nk_default_color_style: table; 14299 14300 /* default text */ 14301 text = &style->text; 14302 text->color = table[NK_COLOR_TEXT]; 14303 text->padding = nk_vec2(0,0); 14304 14305 /* default button */ 14306 button = &style->button; 14307 nk_zero_struct(*button); 14308 button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]); 14309 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 14310 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 14311 button->border_color = table[NK_COLOR_BORDER]; 14312 button->text_background = table[NK_COLOR_BUTTON]; 14313 button->text_normal = table[NK_COLOR_TEXT]; 14314 button->text_hover = table[NK_COLOR_TEXT]; 14315 button->text_active = table[NK_COLOR_TEXT]; 14316 button->padding = nk_vec2(2.0f,2.0f); 14317 button->image_padding = nk_vec2(0.0f,0.0f); 14318 button->touch_padding = nk_vec2(0.0f, 0.0f); 14319 button->userdata = nk_handle_ptr(0); 14320 button->text_alignment = NK_TEXT_CENTERED; 14321 button->border = 1.0f; 14322 button->rounding = 4.0f; 14323 button->draw_begin = 0; 14324 button->draw_end = 0; 14325 14326 /* contextual button */ 14327 button = &style->contextual_button; 14328 nk_zero_struct(*button); 14329 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14330 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 14331 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 14332 button->border_color = table[NK_COLOR_WINDOW]; 14333 button->text_background = table[NK_COLOR_WINDOW]; 14334 button->text_normal = table[NK_COLOR_TEXT]; 14335 button->text_hover = table[NK_COLOR_TEXT]; 14336 button->text_active = table[NK_COLOR_TEXT]; 14337 button->padding = nk_vec2(2.0f,2.0f); 14338 button->touch_padding = nk_vec2(0.0f,0.0f); 14339 button->userdata = nk_handle_ptr(0); 14340 button->text_alignment = NK_TEXT_CENTERED; 14341 button->border = 0.0f; 14342 button->rounding = 0.0f; 14343 button->draw_begin = 0; 14344 button->draw_end = 0; 14345 14346 /* menu button */ 14347 button = &style->menu_button; 14348 nk_zero_struct(*button); 14349 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14350 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 14351 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 14352 button->border_color = table[NK_COLOR_WINDOW]; 14353 button->text_background = table[NK_COLOR_WINDOW]; 14354 button->text_normal = table[NK_COLOR_TEXT]; 14355 button->text_hover = table[NK_COLOR_TEXT]; 14356 button->text_active = table[NK_COLOR_TEXT]; 14357 button->padding = nk_vec2(2.0f,2.0f); 14358 button->touch_padding = nk_vec2(0.0f,0.0f); 14359 button->userdata = nk_handle_ptr(0); 14360 button->text_alignment = NK_TEXT_CENTERED; 14361 button->border = 0.0f; 14362 button->rounding = 1.0f; 14363 button->draw_begin = 0; 14364 button->draw_end = 0; 14365 14366 /* checkbox toggle */ 14367 toggle = &style->checkbox; 14368 nk_zero_struct(*toggle); 14369 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 14370 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14371 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14372 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14373 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14374 toggle->userdata = nk_handle_ptr(0); 14375 toggle->text_background = table[NK_COLOR_WINDOW]; 14376 toggle->text_normal = table[NK_COLOR_TEXT]; 14377 toggle->text_hover = table[NK_COLOR_TEXT]; 14378 toggle->text_active = table[NK_COLOR_TEXT]; 14379 toggle->padding = nk_vec2(2.0f, 2.0f); 14380 toggle->touch_padding = nk_vec2(0,0); 14381 toggle->border_color = nk_rgba(0,0,0,0); 14382 toggle->border = 0.0f; 14383 toggle->spacing = 4; 14384 14385 /* option toggle */ 14386 toggle = &style->option; 14387 nk_zero_struct(*toggle); 14388 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 14389 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14390 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 14391 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14392 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 14393 toggle->userdata = nk_handle_ptr(0); 14394 toggle->text_background = table[NK_COLOR_WINDOW]; 14395 toggle->text_normal = table[NK_COLOR_TEXT]; 14396 toggle->text_hover = table[NK_COLOR_TEXT]; 14397 toggle->text_active = table[NK_COLOR_TEXT]; 14398 toggle->padding = nk_vec2(3.0f, 3.0f); 14399 toggle->touch_padding = nk_vec2(0,0); 14400 toggle->border_color = nk_rgba(0,0,0,0); 14401 toggle->border = 0.0f; 14402 toggle->spacing = 4; 14403 14404 /* selectable */ 14405 select = &style->selectable; 14406 nk_zero_struct(*select); 14407 select->normal = nk_style_item_color(table[NK_COLOR_SELECT]); 14408 select->hover = nk_style_item_color(table[NK_COLOR_SELECT]); 14409 select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]); 14410 select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14411 select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14412 select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 14413 select->text_normal = table[NK_COLOR_TEXT]; 14414 select->text_hover = table[NK_COLOR_TEXT]; 14415 select->text_pressed = table[NK_COLOR_TEXT]; 14416 select->text_normal_active = table[NK_COLOR_TEXT]; 14417 select->text_hover_active = table[NK_COLOR_TEXT]; 14418 select->text_pressed_active = table[NK_COLOR_TEXT]; 14419 select->padding = nk_vec2(2.0f,2.0f); 14420 select->image_padding = nk_vec2(2.0f,2.0f); 14421 select->touch_padding = nk_vec2(0,0); 14422 select->userdata = nk_handle_ptr(0); 14423 select->rounding = 0.0f; 14424 select->draw_begin = 0; 14425 select->draw_end = 0; 14426 14427 /* slider */ 14428 slider = &style->slider; 14429 nk_zero_struct(*slider); 14430 slider->normal = nk_style_item_hide(); 14431 slider->hover = nk_style_item_hide(); 14432 slider->active = nk_style_item_hide(); 14433 slider->bar_normal = table[NK_COLOR_SLIDER]; 14434 slider->bar_hover = table[NK_COLOR_SLIDER]; 14435 slider->bar_active = table[NK_COLOR_SLIDER]; 14436 slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR]; 14437 slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 14438 slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 14439 slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 14440 slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT; 14441 slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT; 14442 slider->cursor_size = nk_vec2(16,16); 14443 slider->padding = nk_vec2(2,2); 14444 slider->spacing = nk_vec2(2,2); 14445 slider->userdata = nk_handle_ptr(0); 14446 slider->show_buttons = nk_false; 14447 slider->bar_height = 8; 14448 slider->rounding = 0; 14449 slider->draw_begin = 0; 14450 slider->draw_end = 0; 14451 14452 /* slider buttons */ 14453 button = &style->slider.inc_button; 14454 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 14455 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 14456 button->active = nk_style_item_color(nk_rgb(44,44,44)); 14457 button->border_color = nk_rgb(65,65,65); 14458 button->text_background = nk_rgb(40,40,40); 14459 button->text_normal = nk_rgb(175,175,175); 14460 button->text_hover = nk_rgb(175,175,175); 14461 button->text_active = nk_rgb(175,175,175); 14462 button->padding = nk_vec2(8.0f,8.0f); 14463 button->touch_padding = nk_vec2(0.0f,0.0f); 14464 button->userdata = nk_handle_ptr(0); 14465 button->text_alignment = NK_TEXT_CENTERED; 14466 button->border = 1.0f; 14467 button->rounding = 0.0f; 14468 button->draw_begin = 0; 14469 button->draw_end = 0; 14470 style->slider.dec_button = style->slider.inc_button; 14471 14472 /* progressbar */ 14473 prog = &style->progress; 14474 nk_zero_struct(*prog); 14475 prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]); 14476 prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]); 14477 prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]); 14478 prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 14479 prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 14480 prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 14481 prog->border_color = nk_rgba(0,0,0,0); 14482 prog->cursor_border_color = nk_rgba(0,0,0,0); 14483 prog->userdata = nk_handle_ptr(0); 14484 prog->padding = nk_vec2(4,4); 14485 prog->rounding = 0; 14486 prog->border = 0; 14487 prog->cursor_rounding = 0; 14488 prog->cursor_border = 0; 14489 prog->draw_begin = 0; 14490 prog->draw_end = 0; 14491 14492 /* scrollbars */ 14493 scroll = &style->scrollh; 14494 nk_zero_struct(*scroll); 14495 scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14496 scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14497 scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 14498 scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]); 14499 scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]); 14500 scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]); 14501 scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID; 14502 scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID; 14503 scroll->userdata = nk_handle_ptr(0); 14504 scroll->border_color = table[NK_COLOR_SCROLLBAR]; 14505 scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR]; 14506 scroll->padding = nk_vec2(0,0); 14507 scroll->show_buttons = nk_false; 14508 scroll->border = 0; 14509 scroll->rounding = 0; 14510 scroll->border_cursor = 0; 14511 scroll->rounding_cursor = 0; 14512 scroll->draw_begin = 0; 14513 scroll->draw_end = 0; 14514 style->scrollv = style->scrollh; 14515 14516 /* scrollbars buttons */ 14517 button = &style->scrollh.inc_button; 14518 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 14519 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 14520 button->active = nk_style_item_color(nk_rgb(44,44,44)); 14521 button->border_color = nk_rgb(65,65,65); 14522 button->text_background = nk_rgb(40,40,40); 14523 button->text_normal = nk_rgb(175,175,175); 14524 button->text_hover = nk_rgb(175,175,175); 14525 button->text_active = nk_rgb(175,175,175); 14526 button->padding = nk_vec2(4.0f,4.0f); 14527 button->touch_padding = nk_vec2(0.0f,0.0f); 14528 button->userdata = nk_handle_ptr(0); 14529 button->text_alignment = NK_TEXT_CENTERED; 14530 button->border = 1.0f; 14531 button->rounding = 0.0f; 14532 button->draw_begin = 0; 14533 button->draw_end = 0; 14534 style->scrollh.dec_button = style->scrollh.inc_button; 14535 style->scrollv.inc_button = style->scrollh.inc_button; 14536 style->scrollv.dec_button = style->scrollh.inc_button; 14537 14538 /* edit */ 14539 edit = &style->edit; 14540 nk_zero_struct(*edit); 14541 edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]); 14542 edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]); 14543 edit->active = nk_style_item_color(table[NK_COLOR_EDIT]); 14544 edit->cursor_normal = table[NK_COLOR_TEXT]; 14545 edit->cursor_hover = table[NK_COLOR_TEXT]; 14546 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 14547 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 14548 edit->border_color = table[NK_COLOR_BORDER]; 14549 edit->text_normal = table[NK_COLOR_TEXT]; 14550 edit->text_hover = table[NK_COLOR_TEXT]; 14551 edit->text_active = table[NK_COLOR_TEXT]; 14552 edit->selected_normal = table[NK_COLOR_TEXT]; 14553 edit->selected_hover = table[NK_COLOR_TEXT]; 14554 edit->selected_text_normal = table[NK_COLOR_EDIT]; 14555 edit->selected_text_hover = table[NK_COLOR_EDIT]; 14556 edit->scrollbar_size = nk_vec2(10,10); 14557 edit->scrollbar = style->scrollv; 14558 edit->padding = nk_vec2(4,4); 14559 edit->row_padding = 2; 14560 edit->cursor_size = 4; 14561 edit->border = 1; 14562 edit->rounding = 0; 14563 14564 /* property */ 14565 property = &style->property; 14566 nk_zero_struct(*property); 14567 property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14568 property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14569 property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14570 property->border_color = table[NK_COLOR_BORDER]; 14571 property->label_normal = table[NK_COLOR_TEXT]; 14572 property->label_hover = table[NK_COLOR_TEXT]; 14573 property->label_active = table[NK_COLOR_TEXT]; 14574 property->sym_left = NK_SYMBOL_TRIANGLE_LEFT; 14575 property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT; 14576 property->userdata = nk_handle_ptr(0); 14577 property->padding = nk_vec2(4,4); 14578 property->border = 1; 14579 property->rounding = 10; 14580 property->draw_begin = 0; 14581 property->draw_end = 0; 14582 14583 /* property buttons */ 14584 button = &style->property.dec_button; 14585 nk_zero_struct(*button); 14586 button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14587 button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14588 button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14589 button->border_color = nk_rgba(0,0,0,0); 14590 button->text_background = table[NK_COLOR_PROPERTY]; 14591 button->text_normal = table[NK_COLOR_TEXT]; 14592 button->text_hover = table[NK_COLOR_TEXT]; 14593 button->text_active = table[NK_COLOR_TEXT]; 14594 button->padding = nk_vec2(0.0f,0.0f); 14595 button->touch_padding = nk_vec2(0.0f,0.0f); 14596 button->userdata = nk_handle_ptr(0); 14597 button->text_alignment = NK_TEXT_CENTERED; 14598 button->border = 0.0f; 14599 button->rounding = 0.0f; 14600 button->draw_begin = 0; 14601 button->draw_end = 0; 14602 style->property.inc_button = style->property.dec_button; 14603 14604 /* property edit */ 14605 edit = &style->property.edit; 14606 nk_zero_struct(*edit); 14607 edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14608 edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14609 edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 14610 edit->border_color = nk_rgba(0,0,0,0); 14611 edit->cursor_normal = table[NK_COLOR_TEXT]; 14612 edit->cursor_hover = table[NK_COLOR_TEXT]; 14613 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 14614 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 14615 edit->text_normal = table[NK_COLOR_TEXT]; 14616 edit->text_hover = table[NK_COLOR_TEXT]; 14617 edit->text_active = table[NK_COLOR_TEXT]; 14618 edit->selected_normal = table[NK_COLOR_TEXT]; 14619 edit->selected_hover = table[NK_COLOR_TEXT]; 14620 edit->selected_text_normal = table[NK_COLOR_EDIT]; 14621 edit->selected_text_hover = table[NK_COLOR_EDIT]; 14622 edit->padding = nk_vec2(0,0); 14623 edit->cursor_size = 8; 14624 edit->border = 0; 14625 edit->rounding = 0; 14626 14627 /* chart */ 14628 chart = &style->chart; 14629 nk_zero_struct(*chart); 14630 chart->background = nk_style_item_color(table[NK_COLOR_CHART]); 14631 chart->border_color = table[NK_COLOR_BORDER]; 14632 chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT]; 14633 chart->color = table[NK_COLOR_CHART_COLOR]; 14634 chart->padding = nk_vec2(4,4); 14635 chart->border = 0; 14636 chart->rounding = 0; 14637 14638 /* combo */ 14639 combo = &style->combo; 14640 combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 14641 combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 14642 combo->active = nk_style_item_color(table[NK_COLOR_COMBO]); 14643 combo->border_color = table[NK_COLOR_BORDER]; 14644 combo->label_normal = table[NK_COLOR_TEXT]; 14645 combo->label_hover = table[NK_COLOR_TEXT]; 14646 combo->label_active = table[NK_COLOR_TEXT]; 14647 combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN; 14648 combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN; 14649 combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN; 14650 combo->content_padding = nk_vec2(4,4); 14651 combo->button_padding = nk_vec2(0,4); 14652 combo->spacing = nk_vec2(4,0); 14653 combo->border = 1; 14654 combo->rounding = 0; 14655 14656 /* combo button */ 14657 button = &style->combo.button; 14658 nk_zero_struct(*button); 14659 button->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 14660 button->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 14661 button->active = nk_style_item_color(table[NK_COLOR_COMBO]); 14662 button->border_color = nk_rgba(0,0,0,0); 14663 button->text_background = table[NK_COLOR_COMBO]; 14664 button->text_normal = table[NK_COLOR_TEXT]; 14665 button->text_hover = table[NK_COLOR_TEXT]; 14666 button->text_active = table[NK_COLOR_TEXT]; 14667 button->padding = nk_vec2(2.0f,2.0f); 14668 button->touch_padding = nk_vec2(0.0f,0.0f); 14669 button->userdata = nk_handle_ptr(0); 14670 button->text_alignment = NK_TEXT_CENTERED; 14671 button->border = 0.0f; 14672 button->rounding = 0.0f; 14673 button->draw_begin = 0; 14674 button->draw_end = 0; 14675 14676 /* tab */ 14677 tab = &style->tab; 14678 tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14679 tab->border_color = table[NK_COLOR_BORDER]; 14680 tab->text = table[NK_COLOR_TEXT]; 14681 tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT; 14682 tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN; 14683 tab->padding = nk_vec2(4,4); 14684 tab->spacing = nk_vec2(4,4); 14685 tab->indent = 10.0f; 14686 tab->border = 1; 14687 tab->rounding = 0; 14688 14689 /* tab button */ 14690 button = &style->tab.tab_minimize_button; 14691 nk_zero_struct(*button); 14692 button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14693 button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14694 button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 14695 button->border_color = nk_rgba(0,0,0,0); 14696 button->text_background = table[NK_COLOR_TAB_HEADER]; 14697 button->text_normal = table[NK_COLOR_TEXT]; 14698 button->text_hover = table[NK_COLOR_TEXT]; 14699 button->text_active = table[NK_COLOR_TEXT]; 14700 button->padding = nk_vec2(2.0f,2.0f); 14701 button->touch_padding = nk_vec2(0.0f,0.0f); 14702 button->userdata = nk_handle_ptr(0); 14703 button->text_alignment = NK_TEXT_CENTERED; 14704 button->border = 0.0f; 14705 button->rounding = 0.0f; 14706 button->draw_begin = 0; 14707 button->draw_end = 0; 14708 style->tab.tab_maximize_button =*button; 14709 14710 /* node button */ 14711 button = &style->tab.node_minimize_button; 14712 nk_zero_struct(*button); 14713 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 14714 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 14715 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 14716 button->border_color = nk_rgba(0,0,0,0); 14717 button->text_background = table[NK_COLOR_TAB_HEADER]; 14718 button->text_normal = table[NK_COLOR_TEXT]; 14719 button->text_hover = table[NK_COLOR_TEXT]; 14720 button->text_active = table[NK_COLOR_TEXT]; 14721 button->padding = nk_vec2(2.0f,2.0f); 14722 button->touch_padding = nk_vec2(0.0f,0.0f); 14723 button->userdata = nk_handle_ptr(0); 14724 button->text_alignment = NK_TEXT_CENTERED; 14725 button->border = 0.0f; 14726 button->rounding = 0.0f; 14727 button->draw_begin = 0; 14728 button->draw_end = 0; 14729 style->tab.node_maximize_button =*button; 14730 14731 /* window header */ 14732 win = &style->window; 14733 win->header.align = NK_HEADER_RIGHT; 14734 win->header.close_symbol = NK_SYMBOL_X; 14735 win->header.minimize_symbol = NK_SYMBOL_MINUS; 14736 win->header.maximize_symbol = NK_SYMBOL_PLUS; 14737 win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14738 win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14739 win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]); 14740 win->header.label_normal = table[NK_COLOR_TEXT]; 14741 win->header.label_hover = table[NK_COLOR_TEXT]; 14742 win->header.label_active = table[NK_COLOR_TEXT]; 14743 win->header.label_padding = nk_vec2(4,4); 14744 win->header.padding = nk_vec2(4,4); 14745 win->header.spacing = nk_vec2(0,0); 14746 14747 /* window header close button */ 14748 button = &style->window.header.close_button; 14749 nk_zero_struct(*button); 14750 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14751 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14752 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 14753 button->border_color = nk_rgba(0,0,0,0); 14754 button->text_background = table[NK_COLOR_HEADER]; 14755 button->text_normal = table[NK_COLOR_TEXT]; 14756 button->text_hover = table[NK_COLOR_TEXT]; 14757 button->text_active = table[NK_COLOR_TEXT]; 14758 button->padding = nk_vec2(0.0f,0.0f); 14759 button->touch_padding = nk_vec2(0.0f,0.0f); 14760 button->userdata = nk_handle_ptr(0); 14761 button->text_alignment = NK_TEXT_CENTERED; 14762 button->border = 0.0f; 14763 button->rounding = 0.0f; 14764 button->draw_begin = 0; 14765 button->draw_end = 0; 14766 14767 /* window header minimize button */ 14768 button = &style->window.header.minimize_button; 14769 nk_zero_struct(*button); 14770 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 14771 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 14772 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 14773 button->border_color = nk_rgba(0,0,0,0); 14774 button->text_background = table[NK_COLOR_HEADER]; 14775 button->text_normal = table[NK_COLOR_TEXT]; 14776 button->text_hover = table[NK_COLOR_TEXT]; 14777 button->text_active = table[NK_COLOR_TEXT]; 14778 button->padding = nk_vec2(0.0f,0.0f); 14779 button->touch_padding = nk_vec2(0.0f,0.0f); 14780 button->userdata = nk_handle_ptr(0); 14781 button->text_alignment = NK_TEXT_CENTERED; 14782 button->border = 0.0f; 14783 button->rounding = 0.0f; 14784 button->draw_begin = 0; 14785 button->draw_end = 0; 14786 14787 /* window */ 14788 win->background = table[NK_COLOR_WINDOW]; 14789 win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]); 14790 win->border_color = table[NK_COLOR_BORDER]; 14791 win->popup_border_color = table[NK_COLOR_BORDER]; 14792 win->combo_border_color = table[NK_COLOR_BORDER]; 14793 win->contextual_border_color = table[NK_COLOR_BORDER]; 14794 win->menu_border_color = table[NK_COLOR_BORDER]; 14795 win->group_border_color = table[NK_COLOR_BORDER]; 14796 win->tooltip_border_color = table[NK_COLOR_BORDER]; 14797 win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]); 14798 14799 win->rounding = 0.0f; 14800 win->spacing = nk_vec2(4,4); 14801 win->scrollbar_size = nk_vec2(10,10); 14802 win->min_size = nk_vec2(64,64); 14803 14804 win->combo_border = 1.0f; 14805 win->contextual_border = 1.0f; 14806 win->menu_border = 1.0f; 14807 win->group_border = 1.0f; 14808 win->tooltip_border = 1.0f; 14809 win->popup_border = 1.0f; 14810 win->border = 2.0f; 14811 win->min_row_height_padding = 8; 14812 14813 win->padding = nk_vec2(4,4); 14814 win->group_padding = nk_vec2(4,4); 14815 win->popup_padding = nk_vec2(4,4); 14816 win->combo_padding = nk_vec2(4,4); 14817 win->contextual_padding = nk_vec2(4,4); 14818 win->menu_padding = nk_vec2(4,4); 14819 win->tooltip_padding = nk_vec2(4,4); 14820} 14821NK_API void 14822nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font) 14823{ 14824 struct nk_style *style; 14825 NK_ASSERT(ctx); 14826 14827 if (!ctx) return; 14828 style = &ctx->style; 14829 style->font = font; 14830 ctx->stacks.fonts.head = 0; 14831 if (ctx->current) 14832 nk_layout_reset_min_row_height(ctx); 14833} 14834NK_API int 14835nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font) 14836{ 14837 struct nk_config_stack_user_font *font_stack; 14838 struct nk_config_stack_user_font_element *element; 14839 14840 NK_ASSERT(ctx); 14841 if (!ctx) return 0; 14842 14843 font_stack = &ctx->stacks.fonts; 14844 NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements)); 14845 if (font_stack->head >= (int)NK_LEN(font_stack->elements)) 14846 return 0; 14847 14848 element = &font_stack->elements[font_stack->head++]; 14849 element->address = &ctx->style.font; 14850 element->old_value = ctx->style.font; 14851 ctx->style.font = font; 14852 return 1; 14853} 14854NK_API int 14855nk_style_pop_font(struct nk_context *ctx) 14856{ 14857 struct nk_config_stack_user_font *font_stack; 14858 struct nk_config_stack_user_font_element *element; 14859 14860 NK_ASSERT(ctx); 14861 if (!ctx) return 0; 14862 14863 font_stack = &ctx->stacks.fonts; 14864 NK_ASSERT(font_stack->head > 0); 14865 if (font_stack->head < 1) 14866 return 0; 14867 14868 element = &font_stack->elements[--font_stack->head]; 14869 *element->address = element->old_value; 14870 return 1; 14871} 14872#define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \ 14873nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\ 14874{\ 14875 struct nk_config_stack_##type * type_stack;\ 14876 struct nk_config_stack_##type##_element *element;\ 14877 NK_ASSERT(ctx);\ 14878 if (!ctx) return 0;\ 14879 type_stack = &ctx->stacks.stack;\ 14880 NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\ 14881 if (type_stack->head >= (int)NK_LEN(type_stack->elements))\ 14882 return 0;\ 14883 element = &type_stack->elements[type_stack->head++];\ 14884 element->address = address;\ 14885 element->old_value = *address;\ 14886 *address = value;\ 14887 return 1;\ 14888} 14889#define NK_STYLE_POP_IMPLEMENATION(type, stack) \ 14890nk_style_pop_##type(struct nk_context *ctx)\ 14891{\ 14892 struct nk_config_stack_##type *type_stack;\ 14893 struct nk_config_stack_##type##_element *element;\ 14894 NK_ASSERT(ctx);\ 14895 if (!ctx) return 0;\ 14896 type_stack = &ctx->stacks.stack;\ 14897 NK_ASSERT(type_stack->head > 0);\ 14898 if (type_stack->head < 1)\ 14899 return 0;\ 14900 element = &type_stack->elements[--type_stack->head];\ 14901 *element->address = element->old_value;\ 14902 return 1;\ 14903} 14904NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items) 14905NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats) 14906NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors) 14907NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags) 14908NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors) 14909 14910NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items) 14911NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats) 14912NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors) 14913NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags) 14914NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors) 14915 14916NK_API int 14917nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c) 14918{ 14919 struct nk_style *style; 14920 NK_ASSERT(ctx); 14921 if (!ctx) return 0; 14922 style = &ctx->style; 14923 if (style->cursors[c]) { 14924 style->cursor_active = style->cursors[c]; 14925 return 1; 14926 } 14927 return 0; 14928} 14929NK_API void 14930nk_style_show_cursor(struct nk_context *ctx) 14931{ 14932 ctx->style.cursor_visible = nk_true; 14933} 14934NK_API void 14935nk_style_hide_cursor(struct nk_context *ctx) 14936{ 14937 ctx->style.cursor_visible = nk_false; 14938} 14939NK_API void 14940nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor, 14941 const struct nk_cursor *c) 14942{ 14943 struct nk_style *style; 14944 NK_ASSERT(ctx); 14945 if (!ctx) return; 14946 style = &ctx->style; 14947 style->cursors[cursor] = c; 14948} 14949NK_API void 14950nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors) 14951{ 14952 int i = 0; 14953 struct nk_style *style; 14954 NK_ASSERT(ctx); 14955 if (!ctx) return; 14956 style = &ctx->style; 14957 for (i = 0; i < NK_CURSOR_COUNT; ++i) 14958 style->cursors[i] = &cursors[i]; 14959 style->cursor_visible = nk_true; 14960} 14961 14962 14963 14964 14965 14966/* ============================================================== 14967 * 14968 * CONTEXT 14969 * 14970 * ===============================================================*/ 14971NK_INTERN void 14972nk_setup(struct nk_context *ctx, const struct nk_user_font *font) 14973{ 14974 NK_ASSERT(ctx); 14975 if (!ctx) return; 14976 nk_zero_struct(*ctx); 14977 nk_style_default(ctx); 14978 ctx->seq = 1; 14979 if (font) ctx->style.font = font; 14980#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 14981 nk_draw_list_init(&ctx->draw_list); 14982#endif 14983} 14984#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 14985NK_API int 14986nk_init_default(struct nk_context *ctx, const struct nk_user_font *font) 14987{ 14988 struct nk_allocator alloc; 14989 alloc.userdata.ptr = 0; 14990 alloc.alloc = nk_malloc; 14991 alloc.free = nk_mfree; 14992 return nk_init(ctx, &alloc, font); 14993} 14994#endif 14995NK_API int 14996nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, 14997 const struct nk_user_font *font) 14998{ 14999 NK_ASSERT(memory); 15000 if (!memory) return 0; 15001 nk_setup(ctx, font); 15002 nk_buffer_init_fixed(&ctx->memory, memory, size); 15003 ctx->use_pool = nk_false; 15004 return 1; 15005} 15006NK_API int 15007nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, 15008 struct nk_buffer *pool, const struct nk_user_font *font) 15009{ 15010 NK_ASSERT(cmds); 15011 NK_ASSERT(pool); 15012 if (!cmds || !pool) return 0; 15013 15014 nk_setup(ctx, font); 15015 ctx->memory = *cmds; 15016 if (pool->type == NK_BUFFER_FIXED) { 15017 /* take memory from buffer and alloc fixed pool */ 15018 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size); 15019 } else { 15020 /* create dynamic pool from buffer allocator */ 15021 struct nk_allocator *alloc = &pool->pool; 15022 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 15023 } 15024 ctx->use_pool = nk_true; 15025 return 1; 15026} 15027NK_API int 15028nk_init(struct nk_context *ctx, struct nk_allocator *alloc, 15029 const struct nk_user_font *font) 15030{ 15031 NK_ASSERT(alloc); 15032 if (!alloc) return 0; 15033 nk_setup(ctx, font); 15034 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE); 15035 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 15036 ctx->use_pool = nk_true; 15037 return 1; 15038} 15039#ifdef NK_INCLUDE_COMMAND_USERDATA 15040NK_API void 15041nk_set_user_data(struct nk_context *ctx, nk_handle handle) 15042{ 15043 if (!ctx) return; 15044 ctx->userdata = handle; 15045 if (ctx->current) 15046 ctx->current->buffer.userdata = handle; 15047} 15048#endif 15049NK_API void 15050nk_free(struct nk_context *ctx) 15051{ 15052 NK_ASSERT(ctx); 15053 if (!ctx) return; 15054 nk_buffer_free(&ctx->memory); 15055 if (ctx->use_pool) 15056 nk_pool_free(&ctx->pool); 15057 15058 nk_zero(&ctx->input, sizeof(ctx->input)); 15059 nk_zero(&ctx->style, sizeof(ctx->style)); 15060 nk_zero(&ctx->memory, sizeof(ctx->memory)); 15061 15062 ctx->seq = 0; 15063 ctx->build = 0; 15064 ctx->begin = 0; 15065 ctx->end = 0; 15066 ctx->active = 0; 15067 ctx->current = 0; 15068 ctx->freelist = 0; 15069 ctx->count = 0; 15070} 15071NK_API void 15072nk_clear(struct nk_context *ctx) 15073{ 15074 struct nk_window *iter; 15075 struct nk_window *next; 15076 NK_ASSERT(ctx); 15077 15078 if (!ctx) return; 15079 if (ctx->use_pool) 15080 nk_buffer_clear(&ctx->memory); 15081 else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); 15082 15083 ctx->build = 0; 15084 ctx->memory.calls = 0; 15085 ctx->last_widget_state = 0; 15086 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 15087 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); 15088 15089 /* garbage collector */ 15090 iter = ctx->begin; 15091 while (iter) { 15092 /* make sure valid minimized windows do not get removed */ 15093 if ((iter->flags & NK_WINDOW_MINIMIZED) && 15094 !(iter->flags & NK_WINDOW_CLOSED) && 15095 iter->seq == ctx->seq) { 15096 iter = iter->next; 15097 continue; 15098 } 15099 /* remove hotness from hidden or closed windows*/ 15100 if (((iter->flags & NK_WINDOW_HIDDEN) || 15101 (iter->flags & NK_WINDOW_CLOSED)) && 15102 iter == ctx->active) { 15103 ctx->active = iter->prev; 15104 ctx->end = iter->prev; 15105 if (!ctx->end) 15106 ctx->begin = 0; 15107 if (ctx->active) 15108 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM; 15109 } 15110 /* free unused popup windows */ 15111 if (iter->popup.win && iter->popup.win->seq != ctx->seq) { 15112 nk_free_window(ctx, iter->popup.win); 15113 iter->popup.win = 0; 15114 } 15115 /* remove unused window state tables */ 15116 {struct nk_table *n, *it = iter->tables; 15117 while (it) { 15118 n = it->next; 15119 if (it->seq != ctx->seq) { 15120 nk_remove_table(iter, it); 15121 nk_zero(it, sizeof(union nk_page_data)); 15122 nk_free_table(ctx, it); 15123 if (it == iter->tables) 15124 iter->tables = n; 15125 } it = n; 15126 }} 15127 /* window itself is not used anymore so free */ 15128 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { 15129 next = iter->next; 15130 nk_remove_window(ctx, iter); 15131 nk_free_window(ctx, iter); 15132 iter = next; 15133 } else iter = iter->next; 15134 } 15135 ctx->seq++; 15136} 15137NK_LIB void 15138nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 15139{ 15140 NK_ASSERT(ctx); 15141 NK_ASSERT(buffer); 15142 if (!ctx || !buffer) return; 15143 buffer->begin = ctx->memory.allocated; 15144 buffer->end = buffer->begin; 15145 buffer->last = buffer->begin; 15146 buffer->clip = nk_null_rect; 15147} 15148NK_LIB void 15149nk_start(struct nk_context *ctx, struct nk_window *win) 15150{ 15151 NK_ASSERT(ctx); 15152 NK_ASSERT(win); 15153 nk_start_buffer(ctx, &win->buffer); 15154} 15155NK_LIB void 15156nk_start_popup(struct nk_context *ctx, struct nk_window *win) 15157{ 15158 struct nk_popup_buffer *buf; 15159 NK_ASSERT(ctx); 15160 NK_ASSERT(win); 15161 if (!ctx || !win) return; 15162 15163 /* save buffer fill state for popup */ 15164 buf = &win->popup.buf; 15165 buf->begin = win->buffer.end; 15166 buf->end = win->buffer.end; 15167 buf->parent = win->buffer.last; 15168 buf->last = buf->begin; 15169 buf->active = nk_true; 15170} 15171NK_LIB void 15172nk_finish_popup(struct nk_context *ctx, struct nk_window *win) 15173{ 15174 struct nk_popup_buffer *buf; 15175 NK_ASSERT(ctx); 15176 NK_ASSERT(win); 15177 if (!ctx || !win) return; 15178 15179 buf = &win->popup.buf; 15180 buf->last = win->buffer.last; 15181 buf->end = win->buffer.end; 15182} 15183NK_LIB void 15184nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 15185{ 15186 NK_ASSERT(ctx); 15187 NK_ASSERT(buffer); 15188 if (!ctx || !buffer) return; 15189 buffer->end = ctx->memory.allocated; 15190} 15191NK_LIB void 15192nk_finish(struct nk_context *ctx, struct nk_window *win) 15193{ 15194 struct nk_popup_buffer *buf; 15195 struct nk_command *parent_last; 15196 void *memory; 15197 15198 NK_ASSERT(ctx); 15199 NK_ASSERT(win); 15200 if (!ctx || !win) return; 15201 nk_finish_buffer(ctx, &win->buffer); 15202 if (!win->popup.buf.active) return; 15203 15204 buf = &win->popup.buf; 15205 memory = ctx->memory.memory.ptr; 15206 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent); 15207 parent_last->next = buf->end; 15208} 15209NK_LIB void 15210nk_build(struct nk_context *ctx) 15211{ 15212 struct nk_window *it = 0; 15213 struct nk_command *cmd = 0; 15214 nk_byte *buffer = 0; 15215 15216 /* draw cursor overlay */ 15217 if (!ctx->style.cursor_active) 15218 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 15219 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) { 15220 struct nk_rect mouse_bounds; 15221 const struct nk_cursor *cursor = ctx->style.cursor_active; 15222 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF); 15223 nk_start_buffer(ctx, &ctx->overlay); 15224 15225 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x; 15226 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y; 15227 mouse_bounds.w = cursor->size.x; 15228 mouse_bounds.h = cursor->size.y; 15229 15230 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white); 15231 nk_finish_buffer(ctx, &ctx->overlay); 15232 } 15233 /* build one big draw command list out of all window buffers */ 15234 it = ctx->begin; 15235 buffer = (nk_byte*)ctx->memory.memory.ptr; 15236 while (it != 0) { 15237 struct nk_window *next = it->next; 15238 if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)|| 15239 it->seq != ctx->seq) 15240 goto cont; 15241 15242 cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last); 15243 while (next && ((next->buffer.last == next->buffer.begin) || 15244 (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq)) 15245 next = next->next; /* skip empty command buffers */ 15246 15247 if (next) cmd->next = next->buffer.begin; 15248 cont: it = next; 15249 } 15250 /* append all popup draw commands into lists */ 15251 it = ctx->begin; 15252 while (it != 0) { 15253 struct nk_window *next = it->next; 15254 struct nk_popup_buffer *buf; 15255 if (!it->popup.buf.active) 15256 goto skip; 15257 15258 buf = &it->popup.buf; 15259 cmd->next = buf->begin; 15260 cmd = nk_ptr_add(struct nk_command, buffer, buf->last); 15261 buf->active = nk_false; 15262 skip: it = next; 15263 } 15264 if (cmd) { 15265 /* append overlay commands */ 15266 if (ctx->overlay.end != ctx->overlay.begin) 15267 cmd->next = ctx->overlay.begin; 15268 else cmd->next = ctx->memory.allocated; 15269 } 15270} 15271NK_API const struct nk_command* 15272nk__begin(struct nk_context *ctx) 15273{ 15274 struct nk_window *iter; 15275 nk_byte *buffer; 15276 NK_ASSERT(ctx); 15277 if (!ctx) return 0; 15278 if (!ctx->count) return 0; 15279 15280 buffer = (nk_byte*)ctx->memory.memory.ptr; 15281 if (!ctx->build) { 15282 nk_build(ctx); 15283 ctx->build = nk_true; 15284 } 15285 iter = ctx->begin; 15286 while (iter && ((iter->buffer.begin == iter->buffer.end) || 15287 (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq)) 15288 iter = iter->next; 15289 if (!iter) return 0; 15290 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin); 15291} 15292 15293NK_API const struct nk_command* 15294nk__next(struct nk_context *ctx, const struct nk_command *cmd) 15295{ 15296 nk_byte *buffer; 15297 const struct nk_command *next; 15298 NK_ASSERT(ctx); 15299 if (!ctx || !cmd || !ctx->count) return 0; 15300 if (cmd->next >= ctx->memory.allocated) return 0; 15301 buffer = (nk_byte*)ctx->memory.memory.ptr; 15302 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next); 15303 return next; 15304} 15305 15306 15307 15308 15309 15310 15311/* =============================================================== 15312 * 15313 * POOL 15314 * 15315 * ===============================================================*/ 15316NK_LIB void 15317nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, 15318 unsigned int capacity) 15319{ 15320 nk_zero(pool, sizeof(*pool)); 15321 pool->alloc = *alloc; 15322 pool->capacity = capacity; 15323 pool->type = NK_BUFFER_DYNAMIC; 15324 pool->pages = 0; 15325} 15326NK_LIB void 15327nk_pool_free(struct nk_pool *pool) 15328{ 15329 struct nk_page *iter = pool->pages; 15330 if (!pool) return; 15331 if (pool->type == NK_BUFFER_FIXED) return; 15332 while (iter) { 15333 struct nk_page *next = iter->next; 15334 pool->alloc.free(pool->alloc.userdata, iter); 15335 iter = next; 15336 } 15337} 15338NK_LIB void 15339nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size) 15340{ 15341 nk_zero(pool, sizeof(*pool)); 15342 NK_ASSERT(size >= sizeof(struct nk_page)); 15343 if (size < sizeof(struct nk_page)) return; 15344 pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element); 15345 pool->pages = (struct nk_page*)memory; 15346 pool->type = NK_BUFFER_FIXED; 15347 pool->size = size; 15348} 15349NK_LIB struct nk_page_element* 15350nk_pool_alloc(struct nk_pool *pool) 15351{ 15352 if (!pool->pages || pool->pages->size >= pool->capacity) { 15353 /* allocate new page */ 15354 struct nk_page *page; 15355 if (pool->type == NK_BUFFER_FIXED) { 15356 NK_ASSERT(pool->pages); 15357 if (!pool->pages) return 0; 15358 NK_ASSERT(pool->pages->size < pool->capacity); 15359 return 0; 15360 } else { 15361 nk_size size = sizeof(struct nk_page); 15362 size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data); 15363 page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size); 15364 page->next = pool->pages; 15365 pool->pages = page; 15366 page->size = 0; 15367 } 15368 } return &pool->pages->win[pool->pages->size++]; 15369} 15370 15371 15372 15373 15374 15375/* =============================================================== 15376 * 15377 * PAGE ELEMENT 15378 * 15379 * ===============================================================*/ 15380NK_LIB struct nk_page_element* 15381nk_create_page_element(struct nk_context *ctx) 15382{ 15383 struct nk_page_element *elem; 15384 if (ctx->freelist) { 15385 /* unlink page element from free list */ 15386 elem = ctx->freelist; 15387 ctx->freelist = elem->next; 15388 } else if (ctx->use_pool) { 15389 /* allocate page element from memory pool */ 15390 elem = nk_pool_alloc(&ctx->pool); 15391 NK_ASSERT(elem); 15392 if (!elem) return 0; 15393 } else { 15394 /* allocate new page element from back of fixed size memory buffer */ 15395 NK_STORAGE const nk_size size = sizeof(struct nk_page_element); 15396 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element); 15397 elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align); 15398 NK_ASSERT(elem); 15399 if (!elem) return 0; 15400 } 15401 nk_zero_struct(*elem); 15402 elem->next = 0; 15403 elem->prev = 0; 15404 return elem; 15405} 15406NK_LIB void 15407nk_link_page_element_into_freelist(struct nk_context *ctx, 15408 struct nk_page_element *elem) 15409{ 15410 /* link table into freelist */ 15411 if (!ctx->freelist) { 15412 ctx->freelist = elem; 15413 } else { 15414 elem->next = ctx->freelist; 15415 ctx->freelist = elem; 15416 } 15417} 15418NK_LIB void 15419nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem) 15420{ 15421 /* we have a pool so just add to free list */ 15422 if (ctx->use_pool) { 15423 nk_link_page_element_into_freelist(ctx, elem); 15424 return; 15425 } 15426 /* if possible remove last element from back of fixed memory buffer */ 15427 {void *elem_end = (void*)(elem + 1); 15428 void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size; 15429 if (elem_end == buffer_end) 15430 ctx->memory.size -= sizeof(struct nk_page_element); 15431 else nk_link_page_element_into_freelist(ctx, elem);} 15432} 15433 15434 15435 15436 15437 15438/* =============================================================== 15439 * 15440 * TABLE 15441 * 15442 * ===============================================================*/ 15443NK_LIB struct nk_table* 15444nk_create_table(struct nk_context *ctx) 15445{ 15446 struct nk_page_element *elem; 15447 elem = nk_create_page_element(ctx); 15448 if (!elem) return 0; 15449 nk_zero_struct(*elem); 15450 return &elem->data.tbl; 15451} 15452NK_LIB void 15453nk_free_table(struct nk_context *ctx, struct nk_table *tbl) 15454{ 15455 union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl); 15456 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 15457 nk_free_page_element(ctx, pe); 15458} 15459NK_LIB void 15460nk_push_table(struct nk_window *win, struct nk_table *tbl) 15461{ 15462 if (!win->tables) { 15463 win->tables = tbl; 15464 tbl->next = 0; 15465 tbl->prev = 0; 15466 tbl->size = 0; 15467 win->table_count = 1; 15468 return; 15469 } 15470 win->tables->prev = tbl; 15471 tbl->next = win->tables; 15472 tbl->prev = 0; 15473 tbl->size = 0; 15474 win->tables = tbl; 15475 win->table_count++; 15476} 15477NK_LIB void 15478nk_remove_table(struct nk_window *win, struct nk_table *tbl) 15479{ 15480 if (win->tables == tbl) 15481 win->tables = tbl->next; 15482 if (tbl->next) 15483 tbl->next->prev = tbl->prev; 15484 if (tbl->prev) 15485 tbl->prev->next = tbl->next; 15486 tbl->next = 0; 15487 tbl->prev = 0; 15488} 15489NK_LIB nk_uint* 15490nk_add_value(struct nk_context *ctx, struct nk_window *win, 15491 nk_hash name, nk_uint value) 15492{ 15493 NK_ASSERT(ctx); 15494 NK_ASSERT(win); 15495 if (!win || !ctx) return 0; 15496 if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) { 15497 struct nk_table *tbl = nk_create_table(ctx); 15498 NK_ASSERT(tbl); 15499 if (!tbl) return 0; 15500 nk_push_table(win, tbl); 15501 } 15502 win->tables->seq = win->seq; 15503 win->tables->keys[win->tables->size] = name; 15504 win->tables->values[win->tables->size] = value; 15505 return &win->tables->values[win->tables->size++]; 15506} 15507NK_LIB nk_uint* 15508nk_find_value(struct nk_window *win, nk_hash name) 15509{ 15510 struct nk_table *iter = win->tables; 15511 while (iter) { 15512 unsigned int i = 0; 15513 unsigned int size = iter->size; 15514 for (i = 0; i < size; ++i) { 15515 if (iter->keys[i] == name) { 15516 iter->seq = win->seq; 15517 return &iter->values[i]; 15518 } 15519 } size = NK_VALUE_PAGE_CAPACITY; 15520 iter = iter->next; 15521 } 15522 return 0; 15523} 15524 15525 15526 15527 15528 15529/* =============================================================== 15530 * 15531 * PANEL 15532 * 15533 * ===============================================================*/ 15534NK_LIB void* 15535nk_create_panel(struct nk_context *ctx) 15536{ 15537 struct nk_page_element *elem; 15538 elem = nk_create_page_element(ctx); 15539 if (!elem) return 0; 15540 nk_zero_struct(*elem); 15541 return &elem->data.pan; 15542} 15543NK_LIB void 15544nk_free_panel(struct nk_context *ctx, struct nk_panel *pan) 15545{ 15546 union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan); 15547 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 15548 nk_free_page_element(ctx, pe); 15549} 15550NK_LIB int 15551nk_panel_has_header(nk_flags flags, const char *title) 15552{ 15553 int active = 0; 15554 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); 15555 active = active || (flags & NK_WINDOW_TITLE); 15556 active = active && !(flags & NK_WINDOW_HIDDEN) && title; 15557 return active; 15558} 15559NK_LIB struct nk_vec2 15560nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type) 15561{ 15562 switch (type) { 15563 default: 15564 case NK_PANEL_WINDOW: return style->window.padding; 15565 case NK_PANEL_GROUP: return style->window.group_padding; 15566 case NK_PANEL_POPUP: return style->window.popup_padding; 15567 case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding; 15568 case NK_PANEL_COMBO: return style->window.combo_padding; 15569 case NK_PANEL_MENU: return style->window.menu_padding; 15570 case NK_PANEL_TOOLTIP: return style->window.menu_padding;} 15571} 15572NK_LIB float 15573nk_panel_get_border(const struct nk_style *style, nk_flags flags, 15574 enum nk_panel_type type) 15575{ 15576 if (flags & NK_WINDOW_BORDER) { 15577 switch (type) { 15578 default: 15579 case NK_PANEL_WINDOW: return style->window.border; 15580 case NK_PANEL_GROUP: return style->window.group_border; 15581 case NK_PANEL_POPUP: return style->window.popup_border; 15582 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border; 15583 case NK_PANEL_COMBO: return style->window.combo_border; 15584 case NK_PANEL_MENU: return style->window.menu_border; 15585 case NK_PANEL_TOOLTIP: return style->window.menu_border; 15586 }} else return 0; 15587} 15588NK_LIB struct nk_color 15589nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type) 15590{ 15591 switch (type) { 15592 default: 15593 case NK_PANEL_WINDOW: return style->window.border_color; 15594 case NK_PANEL_GROUP: return style->window.group_border_color; 15595 case NK_PANEL_POPUP: return style->window.popup_border_color; 15596 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color; 15597 case NK_PANEL_COMBO: return style->window.combo_border_color; 15598 case NK_PANEL_MENU: return style->window.menu_border_color; 15599 case NK_PANEL_TOOLTIP: return style->window.menu_border_color;} 15600} 15601NK_LIB int 15602nk_panel_is_sub(enum nk_panel_type type) 15603{ 15604 return (type & NK_PANEL_SET_SUB)?1:0; 15605} 15606NK_LIB int 15607nk_panel_is_nonblock(enum nk_panel_type type) 15608{ 15609 return (type & NK_PANEL_SET_NONBLOCK)?1:0; 15610} 15611NK_LIB int 15612nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type) 15613{ 15614 struct nk_input *in; 15615 struct nk_window *win; 15616 struct nk_panel *layout; 15617 struct nk_command_buffer *out; 15618 const struct nk_style *style; 15619 const struct nk_user_font *font; 15620 15621 struct nk_vec2 scrollbar_size; 15622 struct nk_vec2 panel_padding; 15623 15624 NK_ASSERT(ctx); 15625 NK_ASSERT(ctx->current); 15626 NK_ASSERT(ctx->current->layout); 15627 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 15628 nk_zero(ctx->current->layout, sizeof(*ctx->current->layout)); 15629 if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) { 15630 nk_zero(ctx->current->layout, sizeof(struct nk_panel)); 15631 ctx->current->layout->type = panel_type; 15632 return 0; 15633 } 15634 /* pull state into local stack */ 15635 style = &ctx->style; 15636 font = style->font; 15637 win = ctx->current; 15638 layout = win->layout; 15639 out = &win->buffer; 15640 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input; 15641#ifdef NK_INCLUDE_COMMAND_USERDATA 15642 win->buffer.userdata = ctx->userdata; 15643#endif 15644 /* pull style configuration into local stack */ 15645 scrollbar_size = style->window.scrollbar_size; 15646 panel_padding = nk_panel_get_padding(style, panel_type); 15647 15648 /* window movement */ 15649 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { 15650 int left_mouse_down; 15651 int left_mouse_clicked; 15652 int left_mouse_click_in_cursor; 15653 15654 /* calculate draggable window space */ 15655 struct nk_rect header; 15656 header.x = win->bounds.x; 15657 header.y = win->bounds.y; 15658 header.w = win->bounds.w; 15659 if (nk_panel_has_header(win->flags, title)) { 15660 header.h = font->height + 2.0f * style->window.header.padding.y; 15661 header.h += 2.0f * style->window.header.label_padding.y; 15662 } else header.h = panel_padding.y; 15663 15664 /* window movement by dragging */ 15665 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 15666 left_mouse_clicked = (int)in->mouse.buttons[NK_BUTTON_LEFT].clicked; 15667 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 15668 NK_BUTTON_LEFT, header, nk_true); 15669 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 15670 win->bounds.x = win->bounds.x + in->mouse.delta.x; 15671 win->bounds.y = win->bounds.y + in->mouse.delta.y; 15672 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; 15673 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; 15674 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE]; 15675 } 15676 } 15677 15678 /* setup panel */ 15679 layout->type = panel_type; 15680 layout->flags = win->flags; 15681 layout->bounds = win->bounds; 15682 layout->bounds.x += panel_padding.x; 15683 layout->bounds.w -= 2*panel_padding.x; 15684 if (win->flags & NK_WINDOW_BORDER) { 15685 layout->border = nk_panel_get_border(style, win->flags, panel_type); 15686 layout->bounds = nk_shrink_rect(layout->bounds, layout->border); 15687 } else layout->border = 0; 15688 layout->at_y = layout->bounds.y; 15689 layout->at_x = layout->bounds.x; 15690 layout->max_x = 0; 15691 layout->header_height = 0; 15692 layout->footer_height = 0; 15693 nk_layout_reset_min_row_height(ctx); 15694 layout->row.index = 0; 15695 layout->row.columns = 0; 15696 layout->row.ratio = 0; 15697 layout->row.item_width = 0; 15698 layout->row.tree_depth = 0; 15699 layout->row.height = panel_padding.y; 15700 layout->has_scrolling = nk_true; 15701 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) 15702 layout->bounds.w -= scrollbar_size.x; 15703 if (!nk_panel_is_nonblock(panel_type)) { 15704 layout->footer_height = 0; 15705 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE) 15706 layout->footer_height = scrollbar_size.y; 15707 layout->bounds.h -= layout->footer_height; 15708 } 15709 15710 /* panel header */ 15711 if (nk_panel_has_header(win->flags, title)) 15712 { 15713 struct nk_text text; 15714 struct nk_rect header; 15715 const struct nk_style_item *background = 0; 15716 15717 /* calculate header bounds */ 15718 header.x = win->bounds.x; 15719 header.y = win->bounds.y; 15720 header.w = win->bounds.w; 15721 header.h = font->height + 2.0f * style->window.header.padding.y; 15722 header.h += (2.0f * style->window.header.label_padding.y); 15723 15724 /* shrink panel by header */ 15725 layout->header_height = header.h; 15726 layout->bounds.y += header.h; 15727 layout->bounds.h -= header.h; 15728 layout->at_y += header.h; 15729 15730 /* select correct header background and text color */ 15731 if (ctx->active == win) { 15732 background = &style->window.header.active; 15733 text.text = style->window.header.label_active; 15734 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) { 15735 background = &style->window.header.hover; 15736 text.text = style->window.header.label_hover; 15737 } else { 15738 background = &style->window.header.normal; 15739 text.text = style->window.header.label_normal; 15740 } 15741 15742 /* draw header background */ 15743 header.h += 1.0f; 15744 if (background->type == NK_STYLE_ITEM_IMAGE) { 15745 text.background = nk_rgba(0,0,0,0); 15746 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 15747 } else { 15748 text.background = background->data.color; 15749 nk_fill_rect(out, header, 0, background->data.color); 15750 } 15751 15752 /* window close button */ 15753 {struct nk_rect button; 15754 button.y = header.y + style->window.header.padding.y; 15755 button.h = header.h - 2 * style->window.header.padding.y; 15756 button.w = button.h; 15757 if (win->flags & NK_WINDOW_CLOSABLE) { 15758 nk_flags ws = 0; 15759 if (style->window.header.align == NK_HEADER_RIGHT) { 15760 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); 15761 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; 15762 } else { 15763 button.x = header.x + style->window.header.padding.x; 15764 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 15765 } 15766 15767 if (nk_do_button_symbol(&ws, &win->buffer, button, 15768 style->window.header.close_symbol, NK_BUTTON_DEFAULT, 15769 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 15770 { 15771 layout->flags |= NK_WINDOW_HIDDEN; 15772 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED; 15773 } 15774 } 15775 15776 /* window minimize button */ 15777 if (win->flags & NK_WINDOW_MINIMIZABLE) { 15778 nk_flags ws = 0; 15779 if (style->window.header.align == NK_HEADER_RIGHT) { 15780 button.x = (header.w + header.x) - button.w; 15781 if (!(win->flags & NK_WINDOW_CLOSABLE)) { 15782 button.x -= style->window.header.padding.x; 15783 header.w -= style->window.header.padding.x; 15784 } 15785 header.w -= button.w + style->window.header.spacing.x; 15786 } else { 15787 button.x = header.x; 15788 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 15789 } 15790 if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)? 15791 style->window.header.maximize_symbol: style->window.header.minimize_symbol, 15792 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 15793 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ? 15794 layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED: 15795 layout->flags | NK_WINDOW_MINIMIZED; 15796 }} 15797 15798 {/* window header title */ 15799 int text_len = nk_strlen(title); 15800 struct nk_rect label = {0,0,0,0}; 15801 float t = font->width(font->userdata, font->height, title, text_len); 15802 text.padding = nk_vec2(0,0); 15803 15804 label.x = header.x + style->window.header.padding.x; 15805 label.x += style->window.header.label_padding.x; 15806 label.y = header.y + style->window.header.label_padding.y; 15807 label.h = font->height + 2 * style->window.header.label_padding.y; 15808 label.w = t + 2 * style->window.header.spacing.x; 15809 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x); 15810 nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);} 15811 } 15812 15813 /* draw window background */ 15814 if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) { 15815 struct nk_rect body; 15816 body.x = win->bounds.x; 15817 body.w = win->bounds.w; 15818 body.y = (win->bounds.y + layout->header_height); 15819 body.h = (win->bounds.h - layout->header_height); 15820 if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE) 15821 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white); 15822 else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color); 15823 } 15824 15825 /* set clipping rectangle */ 15826 {struct nk_rect clip; 15827 layout->clip = layout->bounds; 15828 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, 15829 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); 15830 nk_push_scissor(out, clip); 15831 layout->clip = clip;} 15832 return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED); 15833} 15834NK_LIB void 15835nk_panel_end(struct nk_context *ctx) 15836{ 15837 struct nk_input *in; 15838 struct nk_window *window; 15839 struct nk_panel *layout; 15840 const struct nk_style *style; 15841 struct nk_command_buffer *out; 15842 15843 struct nk_vec2 scrollbar_size; 15844 struct nk_vec2 panel_padding; 15845 15846 NK_ASSERT(ctx); 15847 NK_ASSERT(ctx->current); 15848 NK_ASSERT(ctx->current->layout); 15849 if (!ctx || !ctx->current || !ctx->current->layout) 15850 return; 15851 15852 window = ctx->current; 15853 layout = window->layout; 15854 style = &ctx->style; 15855 out = &window->buffer; 15856 in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input; 15857 if (!nk_panel_is_sub(layout->type)) 15858 nk_push_scissor(out, nk_null_rect); 15859 15860 /* cache configuration data */ 15861 scrollbar_size = style->window.scrollbar_size; 15862 panel_padding = nk_panel_get_padding(style, layout->type); 15863 15864 /* update the current cursor Y-position to point over the last added widget */ 15865 layout->at_y += layout->row.height; 15866 15867 /* dynamic panels */ 15868 if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED)) 15869 { 15870 /* update panel height to fit dynamic growth */ 15871 struct nk_rect empty_space; 15872 if (layout->at_y < (layout->bounds.y + layout->bounds.h)) 15873 layout->bounds.h = layout->at_y - layout->bounds.y; 15874 15875 /* fill top empty space */ 15876 empty_space.x = window->bounds.x; 15877 empty_space.y = layout->bounds.y; 15878 empty_space.h = panel_padding.y; 15879 empty_space.w = window->bounds.w; 15880 nk_fill_rect(out, empty_space, 0, style->window.background); 15881 15882 /* fill left empty space */ 15883 empty_space.x = window->bounds.x; 15884 empty_space.y = layout->bounds.y; 15885 empty_space.w = panel_padding.x + layout->border; 15886 empty_space.h = layout->bounds.h; 15887 nk_fill_rect(out, empty_space, 0, style->window.background); 15888 15889 /* fill right empty space */ 15890 empty_space.x = layout->bounds.x + layout->bounds.w; 15891 empty_space.y = layout->bounds.y; 15892 empty_space.w = panel_padding.x + layout->border; 15893 empty_space.h = layout->bounds.h; 15894 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) 15895 empty_space.w += scrollbar_size.x; 15896 nk_fill_rect(out, empty_space, 0, style->window.background); 15897 15898 /* fill bottom empty space */ 15899 if (layout->footer_height > 0) { 15900 empty_space.x = window->bounds.x; 15901 empty_space.y = layout->bounds.y + layout->bounds.h; 15902 empty_space.w = window->bounds.w; 15903 empty_space.h = layout->footer_height; 15904 nk_fill_rect(out, empty_space, 0, style->window.background); 15905 } 15906 } 15907 15908 /* scrollbars */ 15909 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) && 15910 !(layout->flags & NK_WINDOW_MINIMIZED) && 15911 window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT) 15912 { 15913 struct nk_rect scroll; 15914 int scroll_has_scrolling; 15915 float scroll_target; 15916 float scroll_offset; 15917 float scroll_step; 15918 float scroll_inc; 15919 15920 /* mouse wheel scrolling */ 15921 if (nk_panel_is_sub(layout->type)) 15922 { 15923 /* sub-window mouse wheel scrolling */ 15924 struct nk_window *root_window = window; 15925 struct nk_panel *root_panel = window->layout; 15926 while (root_panel->parent) 15927 root_panel = root_panel->parent; 15928 while (root_window->parent) 15929 root_window = root_window->parent; 15930 15931 /* only allow scrolling if parent window is active */ 15932 scroll_has_scrolling = 0; 15933 if ((root_window == ctx->active) && layout->has_scrolling) { 15934 /* and panel is being hovered and inside clip rect*/ 15935 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) && 15936 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h, 15937 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h)) 15938 { 15939 /* deactivate all parent scrolling */ 15940 root_panel = window->layout; 15941 while (root_panel->parent) { 15942 root_panel->has_scrolling = nk_false; 15943 root_panel = root_panel->parent; 15944 } 15945 root_panel->has_scrolling = nk_false; 15946 scroll_has_scrolling = nk_true; 15947 } 15948 } 15949 } else if (!nk_panel_is_sub(layout->type)) { 15950 /* window mouse wheel scrolling */ 15951 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling; 15952 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling) 15953 window->scrolled = nk_true; 15954 else window->scrolled = nk_false; 15955 } else scroll_has_scrolling = nk_false; 15956 15957 { 15958 /* vertical scrollbar */ 15959 nk_flags state = 0; 15960 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 15961 scroll.y = layout->bounds.y; 15962 scroll.w = scrollbar_size.x; 15963 scroll.h = layout->bounds.h; 15964 15965 scroll_offset = (float)*layout->offset_y; 15966 scroll_step = scroll.h * 0.10f; 15967 scroll_inc = scroll.h * 0.01f; 15968 scroll_target = (float)(int)(layout->at_y - scroll.y); 15969 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling, 15970 scroll_offset, scroll_target, scroll_step, scroll_inc, 15971 &ctx->style.scrollv, in, style->font); 15972 *layout->offset_y = (nk_uint)scroll_offset; 15973 if (in && scroll_has_scrolling) 15974 in->mouse.scroll_delta.y = 0; 15975 } 15976 { 15977 /* horizontal scrollbar */ 15978 nk_flags state = 0; 15979 scroll.x = layout->bounds.x; 15980 scroll.y = layout->bounds.y + layout->bounds.h; 15981 scroll.w = layout->bounds.w; 15982 scroll.h = scrollbar_size.y; 15983 15984 scroll_offset = (float)*layout->offset_x; 15985 scroll_target = (float)(int)(layout->max_x - scroll.x); 15986 scroll_step = layout->max_x * 0.05f; 15987 scroll_inc = layout->max_x * 0.005f; 15988 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling, 15989 scroll_offset, scroll_target, scroll_step, scroll_inc, 15990 &ctx->style.scrollh, in, style->font); 15991 *layout->offset_x = (nk_uint)scroll_offset; 15992 } 15993 } 15994 15995 /* hide scroll if no user input */ 15996 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) { 15997 int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0; 15998 int is_window_hovered = nk_window_is_hovered(ctx); 15999 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 16000 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active)) 16001 window->scrollbar_hiding_timer += ctx->delta_time_seconds; 16002 else window->scrollbar_hiding_timer = 0; 16003 } else window->scrollbar_hiding_timer = 0; 16004 16005 /* window border */ 16006 if (layout->flags & NK_WINDOW_BORDER) 16007 { 16008 struct nk_color border_color = nk_panel_get_border_color(style, layout->type); 16009 const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) 16010 ? (style->window.border + window->bounds.y + layout->header_height) 16011 : ((layout->flags & NK_WINDOW_DYNAMIC) 16012 ? (layout->bounds.y + layout->bounds.h + layout->footer_height) 16013 : (window->bounds.y + window->bounds.h)); 16014 struct nk_rect b = window->bounds; 16015 b.h = padding_y - window->bounds.y; 16016 nk_stroke_rect(out, b, 0, layout->border, border_color); 16017 } 16018 16019 /* scaler */ 16020 if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED)) 16021 { 16022 /* calculate scaler bounds */ 16023 struct nk_rect scaler; 16024 scaler.w = scrollbar_size.x; 16025 scaler.h = scrollbar_size.y; 16026 scaler.y = layout->bounds.y + layout->bounds.h; 16027 if (layout->flags & NK_WINDOW_SCALE_LEFT) 16028 scaler.x = layout->bounds.x - panel_padding.x * 0.5f; 16029 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 16030 if (layout->flags & NK_WINDOW_NO_SCROLLBAR) 16031 scaler.x -= scaler.w; 16032 16033 /* draw scaler */ 16034 {const struct nk_style_item *item = &style->window.scaler; 16035 if (item->type == NK_STYLE_ITEM_IMAGE) 16036 nk_draw_image(out, scaler, &item->data.image, nk_white); 16037 else { 16038 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 16039 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x, 16040 scaler.y + scaler.h, scaler.x + scaler.w, 16041 scaler.y + scaler.h, item->data.color); 16042 } else { 16043 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w, 16044 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color); 16045 } 16046 }} 16047 16048 /* do window scaling */ 16049 if (!(window->flags & NK_WINDOW_ROM)) { 16050 struct nk_vec2 window_size = style->window.min_size; 16051 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 16052 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in, 16053 NK_BUTTON_LEFT, scaler, nk_true); 16054 16055 if (left_mouse_down && left_mouse_click_in_scaler) { 16056 float delta_x = in->mouse.delta.x; 16057 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 16058 delta_x = -delta_x; 16059 window->bounds.x += in->mouse.delta.x; 16060 } 16061 /* dragging in x-direction */ 16062 if (window->bounds.w + delta_x >= window_size.x) { 16063 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) { 16064 window->bounds.w = window->bounds.w + delta_x; 16065 scaler.x += in->mouse.delta.x; 16066 } 16067 } 16068 /* dragging in y-direction (only possible if static window) */ 16069 if (!(layout->flags & NK_WINDOW_DYNAMIC)) { 16070 if (window_size.y < window->bounds.h + in->mouse.delta.y) { 16071 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) { 16072 window->bounds.h = window->bounds.h + in->mouse.delta.y; 16073 scaler.y += in->mouse.delta.y; 16074 } 16075 } 16076 } 16077 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT]; 16078 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f; 16079 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f; 16080 } 16081 } 16082 } 16083 if (!nk_panel_is_sub(layout->type)) { 16084 /* window is hidden so clear command buffer */ 16085 if (layout->flags & NK_WINDOW_HIDDEN) 16086 nk_command_buffer_reset(&window->buffer); 16087 /* window is visible and not tab */ 16088 else nk_finish(ctx, window); 16089 } 16090 16091 /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */ 16092 if (layout->flags & NK_WINDOW_REMOVE_ROM) { 16093 layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 16094 layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 16095 } 16096 window->flags = layout->flags; 16097 16098 /* property garbage collector */ 16099 if (window->property.active && window->property.old != window->property.seq && 16100 window->property.active == window->property.prev) { 16101 nk_zero(&window->property, sizeof(window->property)); 16102 } else { 16103 window->property.old = window->property.seq; 16104 window->property.prev = window->property.active; 16105 window->property.seq = 0; 16106 } 16107 /* edit garbage collector */ 16108 if (window->edit.active && window->edit.old != window->edit.seq && 16109 window->edit.active == window->edit.prev) { 16110 nk_zero(&window->edit, sizeof(window->edit)); 16111 } else { 16112 window->edit.old = window->edit.seq; 16113 window->edit.prev = window->edit.active; 16114 window->edit.seq = 0; 16115 } 16116 /* contextual garbage collector */ 16117 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) { 16118 window->popup.con_count = 0; 16119 window->popup.con_old = 0; 16120 window->popup.active_con = 0; 16121 } else { 16122 window->popup.con_old = window->popup.con_count; 16123 window->popup.con_count = 0; 16124 } 16125 window->popup.combo_count = 0; 16126 /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */ 16127 NK_ASSERT(!layout->row.tree_depth); 16128} 16129 16130 16131 16132 16133 16134/* =============================================================== 16135 * 16136 * WINDOW 16137 * 16138 * ===============================================================*/ 16139NK_LIB void* 16140nk_create_window(struct nk_context *ctx) 16141{ 16142 struct nk_page_element *elem; 16143 elem = nk_create_page_element(ctx); 16144 if (!elem) return 0; 16145 elem->data.win.seq = ctx->seq; 16146 return &elem->data.win; 16147} 16148NK_LIB void 16149nk_free_window(struct nk_context *ctx, struct nk_window *win) 16150{ 16151 /* unlink windows from list */ 16152 struct nk_table *it = win->tables; 16153 if (win->popup.win) { 16154 nk_free_window(ctx, win->popup.win); 16155 win->popup.win = 0; 16156 } 16157 win->next = 0; 16158 win->prev = 0; 16159 16160 while (it) { 16161 /*free window state tables */ 16162 struct nk_table *n = it->next; 16163 nk_remove_table(win, it); 16164 nk_free_table(ctx, it); 16165 if (it == win->tables) 16166 win->tables = n; 16167 it = n; 16168 } 16169 16170 /* link windows into freelist */ 16171 {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win); 16172 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 16173 nk_free_page_element(ctx, pe);} 16174} 16175NK_LIB struct nk_window* 16176nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name) 16177{ 16178 struct nk_window *iter; 16179 iter = ctx->begin; 16180 while (iter) { 16181 NK_ASSERT(iter != iter->next); 16182 if (iter->name == hash) { 16183 int max_len = nk_strlen(iter->name_string); 16184 if (!nk_stricmpn(iter->name_string, name, max_len)) 16185 return iter; 16186 } 16187 iter = iter->next; 16188 } 16189 return 0; 16190} 16191NK_LIB void 16192nk_insert_window(struct nk_context *ctx, struct nk_window *win, 16193 enum nk_window_insert_location loc) 16194{ 16195 const struct nk_window *iter; 16196 NK_ASSERT(ctx); 16197 NK_ASSERT(win); 16198 if (!win || !ctx) return; 16199 16200 iter = ctx->begin; 16201 while (iter) { 16202 NK_ASSERT(iter != iter->next); 16203 NK_ASSERT(iter != win); 16204 if (iter == win) return; 16205 iter = iter->next; 16206 } 16207 16208 if (!ctx->begin) { 16209 win->next = 0; 16210 win->prev = 0; 16211 ctx->begin = win; 16212 ctx->end = win; 16213 ctx->count = 1; 16214 return; 16215 } 16216 if (loc == NK_INSERT_BACK) { 16217 struct nk_window *end; 16218 end = ctx->end; 16219 end->flags |= NK_WINDOW_ROM; 16220 end->next = win; 16221 win->prev = ctx->end; 16222 win->next = 0; 16223 ctx->end = win; 16224 ctx->active = ctx->end; 16225 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 16226 } else { 16227 /*ctx->end->flags |= NK_WINDOW_ROM;*/ 16228 ctx->begin->prev = win; 16229 win->next = ctx->begin; 16230 win->prev = 0; 16231 ctx->begin = win; 16232 ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM; 16233 } 16234 ctx->count++; 16235} 16236NK_LIB void 16237nk_remove_window(struct nk_context *ctx, struct nk_window *win) 16238{ 16239 if (win == ctx->begin || win == ctx->end) { 16240 if (win == ctx->begin) { 16241 ctx->begin = win->next; 16242 if (win->next) 16243 win->next->prev = 0; 16244 } 16245 if (win == ctx->end) { 16246 ctx->end = win->prev; 16247 if (win->prev) 16248 win->prev->next = 0; 16249 } 16250 } else { 16251 if (win->next) 16252 win->next->prev = win->prev; 16253 if (win->prev) 16254 win->prev->next = win->next; 16255 } 16256 if (win == ctx->active || !ctx->active) { 16257 ctx->active = ctx->end; 16258 if (ctx->end) 16259 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 16260 } 16261 win->next = 0; 16262 win->prev = 0; 16263 ctx->count--; 16264} 16265NK_API int 16266nk_begin(struct nk_context *ctx, const char *title, 16267 struct nk_rect bounds, nk_flags flags) 16268{ 16269 return nk_begin_titled(ctx, title, title, bounds, flags); 16270} 16271NK_API int 16272nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, 16273 struct nk_rect bounds, nk_flags flags) 16274{ 16275 struct nk_window *win; 16276 struct nk_style *style; 16277 nk_hash name_hash; 16278 int name_len; 16279 int ret = 0; 16280 16281 NK_ASSERT(ctx); 16282 NK_ASSERT(name); 16283 NK_ASSERT(title); 16284 NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font"); 16285 NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call"); 16286 if (!ctx || ctx->current || !title || !name) 16287 return 0; 16288 16289 /* find or create window */ 16290 style = &ctx->style; 16291 name_len = (int)nk_strlen(name); 16292 name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE); 16293 win = nk_find_window(ctx, name_hash, name); 16294 if (!win) { 16295 /* create new window */ 16296 nk_size name_length = (nk_size)name_len; 16297 win = (struct nk_window*)nk_create_window(ctx); 16298 NK_ASSERT(win); 16299 if (!win) return 0; 16300 16301 if (flags & NK_WINDOW_BACKGROUND) 16302 nk_insert_window(ctx, win, NK_INSERT_FRONT); 16303 else nk_insert_window(ctx, win, NK_INSERT_BACK); 16304 nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON); 16305 16306 win->flags = flags; 16307 win->bounds = bounds; 16308 win->name = name_hash; 16309 name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); 16310 NK_MEMCPY(win->name_string, name, name_length); 16311 win->name_string[name_length] = 0; 16312 win->popup.win = 0; 16313 if (!ctx->active) 16314 ctx->active = win; 16315 } else { 16316 /* update window */ 16317 win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1); 16318 win->flags |= flags; 16319 if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE))) 16320 win->bounds = bounds; 16321 /* If this assert triggers you either: 16322 * 16323 * I.) Have more than one window with the same name or 16324 * II.) You forgot to actually draw the window. 16325 * More specific you did not call `nk_clear` (nk_clear will be 16326 * automatically called for you if you are using one of the 16327 * provided demo backends). */ 16328 NK_ASSERT(win->seq != ctx->seq); 16329 win->seq = ctx->seq; 16330 if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) { 16331 ctx->active = win; 16332 ctx->end = win; 16333 } 16334 } 16335 if (win->flags & NK_WINDOW_HIDDEN) { 16336 ctx->current = win; 16337 win->layout = 0; 16338 return 0; 16339 } else nk_start(ctx, win); 16340 16341 /* window overlapping */ 16342 if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT)) 16343 { 16344 int inpanel, ishovered; 16345 struct nk_window *iter = win; 16346 float h = ctx->style.font->height + 2.0f * style->window.header.padding.y + 16347 (2.0f * style->window.header.label_padding.y); 16348 struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))? 16349 win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h); 16350 16351 /* activate window if hovered and no other window is overlapping this window */ 16352 inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true); 16353 inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked; 16354 ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds); 16355 if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) { 16356 iter = win->next; 16357 while (iter) { 16358 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 16359 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 16360 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16361 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 16362 (!(iter->flags & NK_WINDOW_HIDDEN))) 16363 break; 16364 16365 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 16366 NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16367 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 16368 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 16369 break; 16370 iter = iter->next; 16371 } 16372 } 16373 16374 /* activate window if clicked */ 16375 if (iter && inpanel && (win != ctx->end)) { 16376 iter = win->next; 16377 while (iter) { 16378 /* try to find a panel with higher priority in the same position */ 16379 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 16380 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 16381 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y, 16382 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 16383 !(iter->flags & NK_WINDOW_HIDDEN)) 16384 break; 16385 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 16386 NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 16387 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 16388 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 16389 break; 16390 iter = iter->next; 16391 } 16392 } 16393 if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) { 16394 win->flags |= (nk_flags)NK_WINDOW_ROM; 16395 iter->flags &= ~(nk_flags)NK_WINDOW_ROM; 16396 ctx->active = iter; 16397 if (!(iter->flags & NK_WINDOW_BACKGROUND)) { 16398 /* current window is active in that position so transfer to top 16399 * at the highest priority in stack */ 16400 nk_remove_window(ctx, iter); 16401 nk_insert_window(ctx, iter, NK_INSERT_BACK); 16402 } 16403 } else { 16404 if (!iter && ctx->end != win) { 16405 if (!(win->flags & NK_WINDOW_BACKGROUND)) { 16406 /* current window is active in that position so transfer to top 16407 * at the highest priority in stack */ 16408 nk_remove_window(ctx, win); 16409 nk_insert_window(ctx, win, NK_INSERT_BACK); 16410 } 16411 win->flags &= ~(nk_flags)NK_WINDOW_ROM; 16412 ctx->active = win; 16413 } 16414 if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND)) 16415 win->flags |= NK_WINDOW_ROM; 16416 } 16417 } 16418 win->layout = (struct nk_panel*)nk_create_panel(ctx); 16419 ctx->current = win; 16420 ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); 16421 win->layout->offset_x = &win->scrollbar.x; 16422 win->layout->offset_y = &win->scrollbar.y; 16423 return ret; 16424} 16425NK_API void 16426nk_end(struct nk_context *ctx) 16427{ 16428 struct nk_panel *layout; 16429 NK_ASSERT(ctx); 16430 NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`"); 16431 if (!ctx || !ctx->current) 16432 return; 16433 16434 layout = ctx->current->layout; 16435 if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) { 16436 ctx->current = 0; 16437 return; 16438 } 16439 nk_panel_end(ctx); 16440 nk_free_panel(ctx, ctx->current->layout); 16441 ctx->current = 0; 16442} 16443NK_API struct nk_rect 16444nk_window_get_bounds(const struct nk_context *ctx) 16445{ 16446 NK_ASSERT(ctx); 16447 NK_ASSERT(ctx->current); 16448 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 16449 return ctx->current->bounds; 16450} 16451NK_API struct nk_vec2 16452nk_window_get_position(const struct nk_context *ctx) 16453{ 16454 NK_ASSERT(ctx); 16455 NK_ASSERT(ctx->current); 16456 if (!ctx || !ctx->current) return nk_vec2(0,0); 16457 return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y); 16458} 16459NK_API struct nk_vec2 16460nk_window_get_size(const struct nk_context *ctx) 16461{ 16462 NK_ASSERT(ctx); 16463 NK_ASSERT(ctx->current); 16464 if (!ctx || !ctx->current) return nk_vec2(0,0); 16465 return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h); 16466} 16467NK_API float 16468nk_window_get_width(const struct nk_context *ctx) 16469{ 16470 NK_ASSERT(ctx); 16471 NK_ASSERT(ctx->current); 16472 if (!ctx || !ctx->current) return 0; 16473 return ctx->current->bounds.w; 16474} 16475NK_API float 16476nk_window_get_height(const struct nk_context *ctx) 16477{ 16478 NK_ASSERT(ctx); 16479 NK_ASSERT(ctx->current); 16480 if (!ctx || !ctx->current) return 0; 16481 return ctx->current->bounds.h; 16482} 16483NK_API struct nk_rect 16484nk_window_get_content_region(struct nk_context *ctx) 16485{ 16486 NK_ASSERT(ctx); 16487 NK_ASSERT(ctx->current); 16488 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 16489 return ctx->current->layout->clip; 16490} 16491NK_API struct nk_vec2 16492nk_window_get_content_region_min(struct nk_context *ctx) 16493{ 16494 NK_ASSERT(ctx); 16495 NK_ASSERT(ctx->current); 16496 NK_ASSERT(ctx->current->layout); 16497 if (!ctx || !ctx->current) return nk_vec2(0,0); 16498 return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y); 16499} 16500NK_API struct nk_vec2 16501nk_window_get_content_region_max(struct nk_context *ctx) 16502{ 16503 NK_ASSERT(ctx); 16504 NK_ASSERT(ctx->current); 16505 NK_ASSERT(ctx->current->layout); 16506 if (!ctx || !ctx->current) return nk_vec2(0,0); 16507 return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w, 16508 ctx->current->layout->clip.y + ctx->current->layout->clip.h); 16509} 16510NK_API struct nk_vec2 16511nk_window_get_content_region_size(struct nk_context *ctx) 16512{ 16513 NK_ASSERT(ctx); 16514 NK_ASSERT(ctx->current); 16515 NK_ASSERT(ctx->current->layout); 16516 if (!ctx || !ctx->current) return nk_vec2(0,0); 16517 return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h); 16518} 16519NK_API struct nk_command_buffer* 16520nk_window_get_canvas(struct nk_context *ctx) 16521{ 16522 NK_ASSERT(ctx); 16523 NK_ASSERT(ctx->current); 16524 NK_ASSERT(ctx->current->layout); 16525 if (!ctx || !ctx->current) return 0; 16526 return &ctx->current->buffer; 16527} 16528NK_API struct nk_panel* 16529nk_window_get_panel(struct nk_context *ctx) 16530{ 16531 NK_ASSERT(ctx); 16532 NK_ASSERT(ctx->current); 16533 if (!ctx || !ctx->current) return 0; 16534 return ctx->current->layout; 16535} 16536NK_API void 16537nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) 16538{ 16539 struct nk_window *win; 16540 NK_ASSERT(ctx); 16541 NK_ASSERT(ctx->current); 16542 if (!ctx || !ctx->current) 16543 return ; 16544 win = ctx->current; 16545 if (offset_x) 16546 *offset_x = win->scrollbar.x; 16547 if (offset_y) 16548 *offset_y = win->scrollbar.y; 16549} 16550NK_API int 16551nk_window_has_focus(const struct nk_context *ctx) 16552{ 16553 NK_ASSERT(ctx); 16554 NK_ASSERT(ctx->current); 16555 NK_ASSERT(ctx->current->layout); 16556 if (!ctx || !ctx->current) return 0; 16557 return ctx->current == ctx->active; 16558} 16559NK_API int 16560nk_window_is_hovered(struct nk_context *ctx) 16561{ 16562 NK_ASSERT(ctx); 16563 NK_ASSERT(ctx->current); 16564 if (!ctx || !ctx->current) return 0; 16565 if(ctx->current->flags & NK_WINDOW_HIDDEN) 16566 return 0; 16567 return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds); 16568} 16569NK_API int 16570nk_window_is_any_hovered(struct nk_context *ctx) 16571{ 16572 struct nk_window *iter; 16573 NK_ASSERT(ctx); 16574 if (!ctx) return 0; 16575 iter = ctx->begin; 16576 while (iter) { 16577 /* check if window is being hovered */ 16578 if(!(iter->flags & NK_WINDOW_HIDDEN)) { 16579 /* check if window popup is being hovered */ 16580 if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) 16581 return 1; 16582 16583 if (iter->flags & NK_WINDOW_MINIMIZED) { 16584 struct nk_rect header = iter->bounds; 16585 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; 16586 if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) 16587 return 1; 16588 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { 16589 return 1; 16590 } 16591 } 16592 iter = iter->next; 16593 } 16594 return 0; 16595} 16596NK_API int 16597nk_item_is_any_active(struct nk_context *ctx) 16598{ 16599 int any_hovered = nk_window_is_any_hovered(ctx); 16600 int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 16601 return any_hovered || any_active; 16602} 16603NK_API int 16604nk_window_is_collapsed(struct nk_context *ctx, const char *name) 16605{ 16606 int title_len; 16607 nk_hash title_hash; 16608 struct nk_window *win; 16609 NK_ASSERT(ctx); 16610 if (!ctx) return 0; 16611 16612 title_len = (int)nk_strlen(name); 16613 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16614 win = nk_find_window(ctx, title_hash, name); 16615 if (!win) return 0; 16616 return win->flags & NK_WINDOW_MINIMIZED; 16617} 16618NK_API int 16619nk_window_is_closed(struct nk_context *ctx, const char *name) 16620{ 16621 int title_len; 16622 nk_hash title_hash; 16623 struct nk_window *win; 16624 NK_ASSERT(ctx); 16625 if (!ctx) return 1; 16626 16627 title_len = (int)nk_strlen(name); 16628 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16629 win = nk_find_window(ctx, title_hash, name); 16630 if (!win) return 1; 16631 return (win->flags & NK_WINDOW_CLOSED); 16632} 16633NK_API int 16634nk_window_is_hidden(struct nk_context *ctx, const char *name) 16635{ 16636 int title_len; 16637 nk_hash title_hash; 16638 struct nk_window *win; 16639 NK_ASSERT(ctx); 16640 if (!ctx) return 1; 16641 16642 title_len = (int)nk_strlen(name); 16643 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16644 win = nk_find_window(ctx, title_hash, name); 16645 if (!win) return 1; 16646 return (win->flags & NK_WINDOW_HIDDEN); 16647} 16648NK_API int 16649nk_window_is_active(struct nk_context *ctx, const char *name) 16650{ 16651 int title_len; 16652 nk_hash title_hash; 16653 struct nk_window *win; 16654 NK_ASSERT(ctx); 16655 if (!ctx) return 0; 16656 16657 title_len = (int)nk_strlen(name); 16658 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16659 win = nk_find_window(ctx, title_hash, name); 16660 if (!win) return 0; 16661 return win == ctx->active; 16662} 16663NK_API struct nk_window* 16664nk_window_find(struct nk_context *ctx, const char *name) 16665{ 16666 int title_len; 16667 nk_hash title_hash; 16668 title_len = (int)nk_strlen(name); 16669 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16670 return nk_find_window(ctx, title_hash, name); 16671} 16672NK_API void 16673nk_window_close(struct nk_context *ctx, const char *name) 16674{ 16675 struct nk_window *win; 16676 NK_ASSERT(ctx); 16677 if (!ctx) return; 16678 win = nk_window_find(ctx, name); 16679 if (!win) return; 16680 NK_ASSERT(ctx->current != win && "You cannot close a currently active window"); 16681 if (ctx->current == win) return; 16682 win->flags |= NK_WINDOW_HIDDEN; 16683 win->flags |= NK_WINDOW_CLOSED; 16684} 16685NK_API void 16686nk_window_set_bounds(struct nk_context *ctx, 16687 const char *name, struct nk_rect bounds) 16688{ 16689 struct nk_window *win; 16690 NK_ASSERT(ctx); 16691 if (!ctx) return; 16692 win = nk_window_find(ctx, name); 16693 if (!win) return; 16694 NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window"); 16695 win->bounds = bounds; 16696} 16697NK_API void 16698nk_window_set_position(struct nk_context *ctx, 16699 const char *name, struct nk_vec2 pos) 16700{ 16701 struct nk_window *win = nk_window_find(ctx, name); 16702 if (!win) return; 16703 win->bounds.x = pos.x; 16704 win->bounds.y = pos.y; 16705} 16706NK_API void 16707nk_window_set_size(struct nk_context *ctx, 16708 const char *name, struct nk_vec2 size) 16709{ 16710 struct nk_window *win = nk_window_find(ctx, name); 16711 if (!win) return; 16712 win->bounds.w = size.x; 16713 win->bounds.h = size.y; 16714} 16715NK_API void 16716nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) 16717{ 16718 struct nk_window *win; 16719 NK_ASSERT(ctx); 16720 NK_ASSERT(ctx->current); 16721 if (!ctx || !ctx->current) 16722 return; 16723 win = ctx->current; 16724 win->scrollbar.x = offset_x; 16725 win->scrollbar.y = offset_y; 16726} 16727NK_API void 16728nk_window_collapse(struct nk_context *ctx, const char *name, 16729 enum nk_collapse_states c) 16730{ 16731 int title_len; 16732 nk_hash title_hash; 16733 struct nk_window *win; 16734 NK_ASSERT(ctx); 16735 if (!ctx) return; 16736 16737 title_len = (int)nk_strlen(name); 16738 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16739 win = nk_find_window(ctx, title_hash, name); 16740 if (!win) return; 16741 if (c == NK_MINIMIZED) 16742 win->flags |= NK_WINDOW_MINIMIZED; 16743 else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED; 16744} 16745NK_API void 16746nk_window_collapse_if(struct nk_context *ctx, const char *name, 16747 enum nk_collapse_states c, int cond) 16748{ 16749 NK_ASSERT(ctx); 16750 if (!ctx || !cond) return; 16751 nk_window_collapse(ctx, name, c); 16752} 16753NK_API void 16754nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s) 16755{ 16756 int title_len; 16757 nk_hash title_hash; 16758 struct nk_window *win; 16759 NK_ASSERT(ctx); 16760 if (!ctx) return; 16761 16762 title_len = (int)nk_strlen(name); 16763 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16764 win = nk_find_window(ctx, title_hash, name); 16765 if (!win) return; 16766 if (s == NK_HIDDEN) { 16767 win->flags |= NK_WINDOW_HIDDEN; 16768 } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN; 16769} 16770NK_API void 16771nk_window_show_if(struct nk_context *ctx, const char *name, 16772 enum nk_show_states s, int cond) 16773{ 16774 NK_ASSERT(ctx); 16775 if (!ctx || !cond) return; 16776 nk_window_show(ctx, name, s); 16777} 16778 16779NK_API void 16780nk_window_set_focus(struct nk_context *ctx, const char *name) 16781{ 16782 int title_len; 16783 nk_hash title_hash; 16784 struct nk_window *win; 16785 NK_ASSERT(ctx); 16786 if (!ctx) return; 16787 16788 title_len = (int)nk_strlen(name); 16789 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 16790 win = nk_find_window(ctx, title_hash, name); 16791 if (win && ctx->end != win) { 16792 nk_remove_window(ctx, win); 16793 nk_insert_window(ctx, win, NK_INSERT_BACK); 16794 } 16795 ctx->active = win; 16796} 16797 16798 16799 16800 16801/* =============================================================== 16802 * 16803 * POPUP 16804 * 16805 * ===============================================================*/ 16806NK_API int 16807nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type, 16808 const char *title, nk_flags flags, struct nk_rect rect) 16809{ 16810 struct nk_window *popup; 16811 struct nk_window *win; 16812 struct nk_panel *panel; 16813 16814 int title_len; 16815 nk_hash title_hash; 16816 nk_size allocated; 16817 16818 NK_ASSERT(ctx); 16819 NK_ASSERT(title); 16820 NK_ASSERT(ctx->current); 16821 NK_ASSERT(ctx->current->layout); 16822 if (!ctx || !ctx->current || !ctx->current->layout) 16823 return 0; 16824 16825 win = ctx->current; 16826 panel = win->layout; 16827 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups"); 16828 (void)panel; 16829 title_len = (int)nk_strlen(title); 16830 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP); 16831 16832 popup = win->popup.win; 16833 if (!popup) { 16834 popup = (struct nk_window*)nk_create_window(ctx); 16835 popup->parent = win; 16836 win->popup.win = popup; 16837 win->popup.active = 0; 16838 win->popup.type = NK_PANEL_POPUP; 16839 } 16840 16841 /* make sure we have correct popup */ 16842 if (win->popup.name != title_hash) { 16843 if (!win->popup.active) { 16844 nk_zero(popup, sizeof(*popup)); 16845 win->popup.name = title_hash; 16846 win->popup.active = 1; 16847 win->popup.type = NK_PANEL_POPUP; 16848 } else return 0; 16849 } 16850 16851 /* popup position is local to window */ 16852 ctx->current = popup; 16853 rect.x += win->layout->clip.x; 16854 rect.y += win->layout->clip.y; 16855 16856 /* setup popup data */ 16857 popup->parent = win; 16858 popup->bounds = rect; 16859 popup->seq = ctx->seq; 16860 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 16861 popup->flags = flags; 16862 popup->flags |= NK_WINDOW_BORDER; 16863 if (type == NK_POPUP_DYNAMIC) 16864 popup->flags |= NK_WINDOW_DYNAMIC; 16865 16866 popup->buffer = win->buffer; 16867 nk_start_popup(ctx, win); 16868 allocated = ctx->memory.allocated; 16869 nk_push_scissor(&popup->buffer, nk_null_rect); 16870 16871 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) { 16872 /* popup is running therefore invalidate parent panels */ 16873 struct nk_panel *root; 16874 root = win->layout; 16875 while (root) { 16876 root->flags |= NK_WINDOW_ROM; 16877 root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 16878 root = root->parent; 16879 } 16880 win->popup.active = 1; 16881 popup->layout->offset_x = &popup->scrollbar.x; 16882 popup->layout->offset_y = &popup->scrollbar.y; 16883 popup->layout->parent = win->layout; 16884 return 1; 16885 } else { 16886 /* popup was closed/is invalid so cleanup */ 16887 struct nk_panel *root; 16888 root = win->layout; 16889 while (root) { 16890 root->flags |= NK_WINDOW_REMOVE_ROM; 16891 root = root->parent; 16892 } 16893 win->popup.buf.active = 0; 16894 win->popup.active = 0; 16895 ctx->memory.allocated = allocated; 16896 ctx->current = win; 16897 nk_free_panel(ctx, popup->layout); 16898 popup->layout = 0; 16899 return 0; 16900 } 16901} 16902NK_LIB int 16903nk_nonblock_begin(struct nk_context *ctx, 16904 nk_flags flags, struct nk_rect body, struct nk_rect header, 16905 enum nk_panel_type panel_type) 16906{ 16907 struct nk_window *popup; 16908 struct nk_window *win; 16909 struct nk_panel *panel; 16910 int is_active = nk_true; 16911 16912 NK_ASSERT(ctx); 16913 NK_ASSERT(ctx->current); 16914 NK_ASSERT(ctx->current->layout); 16915 if (!ctx || !ctx->current || !ctx->current->layout) 16916 return 0; 16917 16918 /* popups cannot have popups */ 16919 win = ctx->current; 16920 panel = win->layout; 16921 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); 16922 (void)panel; 16923 popup = win->popup.win; 16924 if (!popup) { 16925 /* create window for nonblocking popup */ 16926 popup = (struct nk_window*)nk_create_window(ctx); 16927 popup->parent = win; 16928 win->popup.win = popup; 16929 win->popup.type = panel_type; 16930 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON); 16931 } else { 16932 /* close the popup if user pressed outside or in the header */ 16933 int pressed, in_body, in_header; 16934#ifdef NK_BUTTON_TRIGGER_ON_RELEASE 16935 pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT); 16936#else 16937 pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 16938#endif 16939 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 16940 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); 16941 if (pressed && (!in_body || in_header)) 16942 is_active = nk_false; 16943 } 16944 win->popup.header = header; 16945 16946 if (!is_active) { 16947 /* remove read only mode from all parent panels */ 16948 struct nk_panel *root = win->layout; 16949 while (root) { 16950 root->flags |= NK_WINDOW_REMOVE_ROM; 16951 root = root->parent; 16952 } 16953 return is_active; 16954 } 16955 popup->bounds = body; 16956 popup->parent = win; 16957 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 16958 popup->flags = flags; 16959 popup->flags |= NK_WINDOW_BORDER; 16960 popup->flags |= NK_WINDOW_DYNAMIC; 16961 popup->seq = ctx->seq; 16962 win->popup.active = 1; 16963 NK_ASSERT(popup->layout); 16964 16965 nk_start_popup(ctx, win); 16966 popup->buffer = win->buffer; 16967 nk_push_scissor(&popup->buffer, nk_null_rect); 16968 ctx->current = popup; 16969 16970 nk_panel_begin(ctx, 0, panel_type); 16971 win->buffer = popup->buffer; 16972 popup->layout->parent = win->layout; 16973 popup->layout->offset_x = &popup->scrollbar.x; 16974 popup->layout->offset_y = &popup->scrollbar.y; 16975 16976 /* set read only mode to all parent panels */ 16977 {struct nk_panel *root; 16978 root = win->layout; 16979 while (root) { 16980 root->flags |= NK_WINDOW_ROM; 16981 root = root->parent; 16982 }} 16983 return is_active; 16984} 16985NK_API void 16986nk_popup_close(struct nk_context *ctx) 16987{ 16988 struct nk_window *popup; 16989 NK_ASSERT(ctx); 16990 if (!ctx || !ctx->current) return; 16991 16992 popup = ctx->current; 16993 NK_ASSERT(popup->parent); 16994 NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP); 16995 popup->flags |= NK_WINDOW_HIDDEN; 16996} 16997NK_API void 16998nk_popup_end(struct nk_context *ctx) 16999{ 17000 struct nk_window *win; 17001 struct nk_window *popup; 17002 17003 NK_ASSERT(ctx); 17004 NK_ASSERT(ctx->current); 17005 NK_ASSERT(ctx->current->layout); 17006 if (!ctx || !ctx->current || !ctx->current->layout) 17007 return; 17008 17009 popup = ctx->current; 17010 if (!popup->parent) return; 17011 win = popup->parent; 17012 if (popup->flags & NK_WINDOW_HIDDEN) { 17013 struct nk_panel *root; 17014 root = win->layout; 17015 while (root) { 17016 root->flags |= NK_WINDOW_REMOVE_ROM; 17017 root = root->parent; 17018 } 17019 win->popup.active = 0; 17020 } 17021 nk_push_scissor(&popup->buffer, nk_null_rect); 17022 nk_end(ctx); 17023 17024 win->buffer = popup->buffer; 17025 nk_finish_popup(ctx, win); 17026 ctx->current = win; 17027 nk_push_scissor(&win->buffer, win->layout->clip); 17028} 17029NK_API void 17030nk_popup_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) 17031{ 17032 struct nk_window *popup; 17033 17034 NK_ASSERT(ctx); 17035 NK_ASSERT(ctx->current); 17036 NK_ASSERT(ctx->current->layout); 17037 if (!ctx || !ctx->current || !ctx->current->layout) 17038 return; 17039 17040 popup = ctx->current; 17041 if (offset_x) 17042 *offset_x = popup->scrollbar.x; 17043 if (offset_y) 17044 *offset_y = popup->scrollbar.y; 17045} 17046NK_API void 17047nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) 17048{ 17049 struct nk_window *popup; 17050 17051 NK_ASSERT(ctx); 17052 NK_ASSERT(ctx->current); 17053 NK_ASSERT(ctx->current->layout); 17054 if (!ctx || !ctx->current || !ctx->current->layout) 17055 return; 17056 17057 popup = ctx->current; 17058 popup->scrollbar.x = offset_x; 17059 popup->scrollbar.y = offset_y; 17060} 17061 17062 17063 17064 17065/* ============================================================== 17066 * 17067 * CONTEXTUAL 17068 * 17069 * ===============================================================*/ 17070NK_API int 17071nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size, 17072 struct nk_rect trigger_bounds) 17073{ 17074 struct nk_window *win; 17075 struct nk_window *popup; 17076 struct nk_rect body; 17077 17078 NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0}; 17079 int is_clicked = 0; 17080 int is_open = 0; 17081 int ret = 0; 17082 17083 NK_ASSERT(ctx); 17084 NK_ASSERT(ctx->current); 17085 NK_ASSERT(ctx->current->layout); 17086 if (!ctx || !ctx->current || !ctx->current->layout) 17087 return 0; 17088 17089 win = ctx->current; 17090 ++win->popup.con_count; 17091 if (ctx->current != ctx->active) 17092 return 0; 17093 17094 /* check if currently active contextual is active */ 17095 popup = win->popup.win; 17096 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL); 17097 is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds); 17098 if (win->popup.active_con && win->popup.con_count != win->popup.active_con) 17099 return 0; 17100 if (!is_open && win->popup.active_con) 17101 win->popup.active_con = 0; 17102 if ((!is_open && !is_clicked)) 17103 return 0; 17104 17105 /* calculate contextual position on click */ 17106 win->popup.active_con = win->popup.con_count; 17107 if (is_clicked) { 17108 body.x = ctx->input.mouse.pos.x; 17109 body.y = ctx->input.mouse.pos.y; 17110 } else { 17111 body.x = popup->bounds.x; 17112 body.y = popup->bounds.y; 17113 } 17114 body.w = size.x; 17115 body.h = size.y; 17116 17117 /* start nonblocking contextual popup */ 17118 ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body, 17119 null_rect, NK_PANEL_CONTEXTUAL); 17120 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL; 17121 else { 17122 win->popup.active_con = 0; 17123 win->popup.type = NK_PANEL_NONE; 17124 if (win->popup.win) 17125 win->popup.win->flags = 0; 17126 } 17127 return ret; 17128} 17129NK_API int 17130nk_contextual_item_text(struct nk_context *ctx, const char *text, int len, 17131 nk_flags alignment) 17132{ 17133 struct nk_window *win; 17134 const struct nk_input *in; 17135 const struct nk_style *style; 17136 17137 struct nk_rect bounds; 17138 enum nk_widget_layout_states state; 17139 17140 NK_ASSERT(ctx); 17141 NK_ASSERT(ctx->current); 17142 NK_ASSERT(ctx->current->layout); 17143 if (!ctx || !ctx->current || !ctx->current->layout) 17144 return 0; 17145 17146 win = ctx->current; 17147 style = &ctx->style; 17148 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17149 if (!state) return nk_false; 17150 17151 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17152 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 17153 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) { 17154 nk_contextual_close(ctx); 17155 return nk_true; 17156 } 17157 return nk_false; 17158} 17159NK_API int 17160nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align) 17161{ 17162 return nk_contextual_item_text(ctx, label, nk_strlen(label), align); 17163} 17164NK_API int 17165nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img, 17166 const char *text, int len, nk_flags align) 17167{ 17168 struct nk_window *win; 17169 const struct nk_input *in; 17170 const struct nk_style *style; 17171 17172 struct nk_rect bounds; 17173 enum nk_widget_layout_states state; 17174 17175 NK_ASSERT(ctx); 17176 NK_ASSERT(ctx->current); 17177 NK_ASSERT(ctx->current->layout); 17178 if (!ctx || !ctx->current || !ctx->current->layout) 17179 return 0; 17180 17181 win = ctx->current; 17182 style = &ctx->style; 17183 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17184 if (!state) return nk_false; 17185 17186 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17187 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, 17188 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){ 17189 nk_contextual_close(ctx); 17190 return nk_true; 17191 } 17192 return nk_false; 17193} 17194NK_API int 17195nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img, 17196 const char *label, nk_flags align) 17197{ 17198 return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align); 17199} 17200NK_API int 17201nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 17202 const char *text, int len, nk_flags align) 17203{ 17204 struct nk_window *win; 17205 const struct nk_input *in; 17206 const struct nk_style *style; 17207 17208 struct nk_rect bounds; 17209 enum nk_widget_layout_states state; 17210 17211 NK_ASSERT(ctx); 17212 NK_ASSERT(ctx->current); 17213 NK_ASSERT(ctx->current->layout); 17214 if (!ctx || !ctx->current || !ctx->current->layout) 17215 return 0; 17216 17217 win = ctx->current; 17218 style = &ctx->style; 17219 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 17220 if (!state) return nk_false; 17221 17222 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17223 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 17224 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) { 17225 nk_contextual_close(ctx); 17226 return nk_true; 17227 } 17228 return nk_false; 17229} 17230NK_API int 17231nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 17232 const char *text, nk_flags align) 17233{ 17234 return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align); 17235} 17236NK_API void 17237nk_contextual_close(struct nk_context *ctx) 17238{ 17239 NK_ASSERT(ctx); 17240 NK_ASSERT(ctx->current); 17241 NK_ASSERT(ctx->current->layout); 17242 if (!ctx || !ctx->current || !ctx->current->layout) return; 17243 nk_popup_close(ctx); 17244} 17245NK_API void 17246nk_contextual_end(struct nk_context *ctx) 17247{ 17248 struct nk_window *popup; 17249 struct nk_panel *panel; 17250 NK_ASSERT(ctx); 17251 NK_ASSERT(ctx->current); 17252 if (!ctx || !ctx->current) return; 17253 17254 popup = ctx->current; 17255 panel = popup->layout; 17256 NK_ASSERT(popup->parent); 17257 NK_ASSERT(panel->type & NK_PANEL_SET_POPUP); 17258 if (panel->flags & NK_WINDOW_DYNAMIC) { 17259 /* Close behavior 17260 This is a bit of a hack solution since we do not know before we end our popup 17261 how big it will be. We therefore do not directly know when a 17262 click outside the non-blocking popup must close it at that direct frame. 17263 Instead it will be closed in the next frame.*/ 17264 struct nk_rect body = {0,0,0,0}; 17265 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) { 17266 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type); 17267 body = panel->bounds; 17268 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height); 17269 body.h = (panel->bounds.y + panel->bounds.h) - body.y; 17270 } 17271 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 17272 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 17273 if (pressed && in_body) 17274 popup->flags |= NK_WINDOW_HIDDEN; 17275 } 17276 } 17277 if (popup->flags & NK_WINDOW_HIDDEN) 17278 popup->seq = 0; 17279 nk_popup_end(ctx); 17280 return; 17281} 17282 17283 17284 17285 17286 17287/* =============================================================== 17288 * 17289 * MENU 17290 * 17291 * ===============================================================*/ 17292NK_API void 17293nk_menubar_begin(struct nk_context *ctx) 17294{ 17295 struct nk_panel *layout; 17296 NK_ASSERT(ctx); 17297 NK_ASSERT(ctx->current); 17298 NK_ASSERT(ctx->current->layout); 17299 if (!ctx || !ctx->current || !ctx->current->layout) 17300 return; 17301 17302 layout = ctx->current->layout; 17303 NK_ASSERT(layout->at_y == layout->bounds.y); 17304 /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin. 17305 If you want a menubar the first nuklear function after `nk_begin` has to be a 17306 `nk_menubar_begin` call. Inside the menubar you then have to allocate space for 17307 widgets (also supports multiple rows). 17308 Example: 17309 if (nk_begin(...)) { 17310 nk_menubar_begin(...); 17311 nk_layout_xxxx(...); 17312 nk_button(...); 17313 nk_layout_xxxx(...); 17314 nk_button(...); 17315 nk_menubar_end(...); 17316 } 17317 nk_end(...); 17318 */ 17319 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 17320 return; 17321 17322 layout->menu.x = layout->at_x; 17323 layout->menu.y = layout->at_y + layout->row.height; 17324 layout->menu.w = layout->bounds.w; 17325 layout->menu.offset.x = *layout->offset_x; 17326 layout->menu.offset.y = *layout->offset_y; 17327 *layout->offset_y = 0; 17328} 17329NK_API void 17330nk_menubar_end(struct nk_context *ctx) 17331{ 17332 struct nk_window *win; 17333 struct nk_panel *layout; 17334 struct nk_command_buffer *out; 17335 17336 NK_ASSERT(ctx); 17337 NK_ASSERT(ctx->current); 17338 NK_ASSERT(ctx->current->layout); 17339 if (!ctx || !ctx->current || !ctx->current->layout) 17340 return; 17341 17342 win = ctx->current; 17343 out = &win->buffer; 17344 layout = win->layout; 17345 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 17346 return; 17347 17348 layout->menu.h = layout->at_y - layout->menu.y; 17349 layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height; 17350 layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height; 17351 17352 *layout->offset_x = layout->menu.offset.x; 17353 *layout->offset_y = layout->menu.offset.y; 17354 layout->at_y = layout->bounds.y - layout->row.height; 17355 17356 layout->clip.y = layout->bounds.y; 17357 layout->clip.h = layout->bounds.h; 17358 nk_push_scissor(out, layout->clip); 17359} 17360NK_INTERN int 17361nk_menu_begin(struct nk_context *ctx, struct nk_window *win, 17362 const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size) 17363{ 17364 int is_open = 0; 17365 int is_active = 0; 17366 struct nk_rect body; 17367 struct nk_window *popup; 17368 nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU); 17369 17370 NK_ASSERT(ctx); 17371 NK_ASSERT(ctx->current); 17372 NK_ASSERT(ctx->current->layout); 17373 if (!ctx || !ctx->current || !ctx->current->layout) 17374 return 0; 17375 17376 body.x = header.x; 17377 body.w = size.x; 17378 body.y = header.y + header.h; 17379 body.h = size.y; 17380 17381 popup = win->popup.win; 17382 is_open = popup ? nk_true : nk_false; 17383 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU); 17384 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 17385 (!is_open && !is_active && !is_clicked)) return 0; 17386 if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU)) 17387 return 0; 17388 17389 win->popup.type = NK_PANEL_MENU; 17390 win->popup.name = hash; 17391 return 1; 17392} 17393NK_API int 17394nk_menu_begin_text(struct nk_context *ctx, const char *title, int len, 17395 nk_flags align, struct nk_vec2 size) 17396{ 17397 struct nk_window *win; 17398 const struct nk_input *in; 17399 struct nk_rect header; 17400 int is_clicked = nk_false; 17401 nk_flags state; 17402 17403 NK_ASSERT(ctx); 17404 NK_ASSERT(ctx->current); 17405 NK_ASSERT(ctx->current->layout); 17406 if (!ctx || !ctx->current || !ctx->current->layout) 17407 return 0; 17408 17409 win = ctx->current; 17410 state = nk_widget(&header, ctx); 17411 if (!state) return 0; 17412 in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17413 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header, 17414 title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 17415 is_clicked = nk_true; 17416 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17417} 17418NK_API int nk_menu_begin_label(struct nk_context *ctx, 17419 const char *text, nk_flags align, struct nk_vec2 size) 17420{ 17421 return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size); 17422} 17423NK_API int 17424nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img, 17425 struct nk_vec2 size) 17426{ 17427 struct nk_window *win; 17428 struct nk_rect header; 17429 const struct nk_input *in; 17430 int is_clicked = nk_false; 17431 nk_flags state; 17432 17433 NK_ASSERT(ctx); 17434 NK_ASSERT(ctx->current); 17435 NK_ASSERT(ctx->current->layout); 17436 if (!ctx || !ctx->current || !ctx->current->layout) 17437 return 0; 17438 17439 win = ctx->current; 17440 state = nk_widget(&header, ctx); 17441 if (!state) return 0; 17442 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17443 if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header, 17444 img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in)) 17445 is_clicked = nk_true; 17446 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 17447} 17448NK_API int 17449nk_menu_begin_symbol(struct nk_context *ctx, const char *id, 17450 enum nk_symbol_type sym, struct nk_vec2 size) 17451{ 17452 struct nk_window *win; 17453 const struct nk_input *in; 17454 struct nk_rect header; 17455 int is_clicked = nk_false; 17456 nk_flags state; 17457 17458 NK_ASSERT(ctx); 17459 NK_ASSERT(ctx->current); 17460 NK_ASSERT(ctx->current->layout); 17461 if (!ctx || !ctx->current || !ctx->current->layout) 17462 return 0; 17463 17464 win = ctx->current; 17465 state = nk_widget(&header, ctx); 17466 if (!state) return 0; 17467 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17468 if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, 17469 sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 17470 is_clicked = nk_true; 17471 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 17472} 17473NK_API int 17474nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len, 17475 nk_flags align, struct nk_image img, struct nk_vec2 size) 17476{ 17477 struct nk_window *win; 17478 struct nk_rect header; 17479 const struct nk_input *in; 17480 int is_clicked = nk_false; 17481 nk_flags state; 17482 17483 NK_ASSERT(ctx); 17484 NK_ASSERT(ctx->current); 17485 NK_ASSERT(ctx->current->layout); 17486 if (!ctx || !ctx->current || !ctx->current->layout) 17487 return 0; 17488 17489 win = ctx->current; 17490 state = nk_widget(&header, ctx); 17491 if (!state) return 0; 17492 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17493 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 17494 header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 17495 ctx->style.font, in)) 17496 is_clicked = nk_true; 17497 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17498} 17499NK_API int 17500nk_menu_begin_image_label(struct nk_context *ctx, 17501 const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size) 17502{ 17503 return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size); 17504} 17505NK_API int 17506nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len, 17507 nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size) 17508{ 17509 struct nk_window *win; 17510 struct nk_rect header; 17511 const struct nk_input *in; 17512 int is_clicked = nk_false; 17513 nk_flags state; 17514 17515 NK_ASSERT(ctx); 17516 NK_ASSERT(ctx->current); 17517 NK_ASSERT(ctx->current->layout); 17518 if (!ctx || !ctx->current || !ctx->current->layout) 17519 return 0; 17520 17521 win = ctx->current; 17522 state = nk_widget(&header, ctx); 17523 if (!state) return 0; 17524 17525 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 17526 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, 17527 header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 17528 ctx->style.font, in)) is_clicked = nk_true; 17529 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 17530} 17531NK_API int 17532nk_menu_begin_symbol_label(struct nk_context *ctx, 17533 const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size ) 17534{ 17535 return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size); 17536} 17537NK_API int 17538nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align) 17539{ 17540 return nk_contextual_item_text(ctx, title, len, align); 17541} 17542NK_API int 17543nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align) 17544{ 17545 return nk_contextual_item_label(ctx, label, align); 17546} 17547NK_API int 17548nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img, 17549 const char *label, nk_flags align) 17550{ 17551 return nk_contextual_item_image_label(ctx, img, label, align); 17552} 17553NK_API int 17554nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img, 17555 const char *text, int len, nk_flags align) 17556{ 17557 return nk_contextual_item_image_text(ctx, img, text, len, align); 17558} 17559NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 17560 const char *text, int len, nk_flags align) 17561{ 17562 return nk_contextual_item_symbol_text(ctx, sym, text, len, align); 17563} 17564NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 17565 const char *label, nk_flags align) 17566{ 17567 return nk_contextual_item_symbol_label(ctx, sym, label, align); 17568} 17569NK_API void nk_menu_close(struct nk_context *ctx) 17570{ 17571 nk_contextual_close(ctx); 17572} 17573NK_API void 17574nk_menu_end(struct nk_context *ctx) 17575{ 17576 nk_contextual_end(ctx); 17577} 17578 17579 17580 17581 17582 17583/* =============================================================== 17584 * 17585 * LAYOUT 17586 * 17587 * ===============================================================*/ 17588NK_API void 17589nk_layout_set_min_row_height(struct nk_context *ctx, float height) 17590{ 17591 struct nk_window *win; 17592 struct nk_panel *layout; 17593 17594 NK_ASSERT(ctx); 17595 NK_ASSERT(ctx->current); 17596 NK_ASSERT(ctx->current->layout); 17597 if (!ctx || !ctx->current || !ctx->current->layout) 17598 return; 17599 17600 win = ctx->current; 17601 layout = win->layout; 17602 layout->row.min_height = height; 17603} 17604NK_API void 17605nk_layout_reset_min_row_height(struct nk_context *ctx) 17606{ 17607 struct nk_window *win; 17608 struct nk_panel *layout; 17609 17610 NK_ASSERT(ctx); 17611 NK_ASSERT(ctx->current); 17612 NK_ASSERT(ctx->current->layout); 17613 if (!ctx || !ctx->current || !ctx->current->layout) 17614 return; 17615 17616 win = ctx->current; 17617 layout = win->layout; 17618 layout->row.min_height = ctx->style.font->height; 17619 layout->row.min_height += ctx->style.text.padding.y*2; 17620 layout->row.min_height += ctx->style.window.min_row_height_padding*2; 17621} 17622NK_LIB float 17623nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, 17624 float total_space, int columns) 17625{ 17626 float panel_padding; 17627 float panel_spacing; 17628 float panel_space; 17629 17630 struct nk_vec2 spacing; 17631 struct nk_vec2 padding; 17632 17633 spacing = style->window.spacing; 17634 padding = nk_panel_get_padding(style, type); 17635 17636 /* calculate the usable panel space */ 17637 panel_padding = 2 * padding.x; 17638 panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x; 17639 panel_space = total_space - panel_padding - panel_spacing; 17640 return panel_space; 17641} 17642NK_LIB void 17643nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, 17644 float height, int cols) 17645{ 17646 struct nk_panel *layout; 17647 const struct nk_style *style; 17648 struct nk_command_buffer *out; 17649 17650 struct nk_vec2 item_spacing; 17651 struct nk_color color; 17652 17653 NK_ASSERT(ctx); 17654 NK_ASSERT(ctx->current); 17655 NK_ASSERT(ctx->current->layout); 17656 if (!ctx || !ctx->current || !ctx->current->layout) 17657 return; 17658 17659 /* prefetch some configuration data */ 17660 layout = win->layout; 17661 style = &ctx->style; 17662 out = &win->buffer; 17663 color = style->window.background; 17664 item_spacing = style->window.spacing; 17665 17666 /* if one of these triggers you forgot to add an `if` condition around either 17667 a window, group, popup, combobox or contextual menu `begin` and `end` block. 17668 Example: 17669 if (nk_begin(...) {...} nk_end(...); or 17670 if (nk_group_begin(...) { nk_group_end(...);} */ 17671 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 17672 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 17673 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 17674 17675 /* update the current row and set the current row layout */ 17676 layout->row.index = 0; 17677 layout->at_y += layout->row.height; 17678 layout->row.columns = cols; 17679 if (height == 0.0f) 17680 layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y; 17681 else layout->row.height = height + item_spacing.y; 17682 17683 layout->row.item_offset = 0; 17684 if (layout->flags & NK_WINDOW_DYNAMIC) { 17685 /* draw background for dynamic panels */ 17686 struct nk_rect background; 17687 background.x = win->bounds.x; 17688 background.w = win->bounds.w; 17689 background.y = layout->at_y - 1.0f; 17690 background.h = layout->row.height + 1.0f; 17691 nk_fill_rect(out, background, 0, color); 17692 } 17693} 17694NK_LIB void 17695nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, 17696 float height, int cols, int width) 17697{ 17698 /* update the current row and set the current row layout */ 17699 struct nk_window *win; 17700 NK_ASSERT(ctx); 17701 NK_ASSERT(ctx->current); 17702 NK_ASSERT(ctx->current->layout); 17703 if (!ctx || !ctx->current || !ctx->current->layout) 17704 return; 17705 17706 win = ctx->current; 17707 nk_panel_layout(ctx, win, height, cols); 17708 if (fmt == NK_DYNAMIC) 17709 win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED; 17710 else win->layout->row.type = NK_LAYOUT_STATIC_FIXED; 17711 17712 win->layout->row.ratio = 0; 17713 win->layout->row.filled = 0; 17714 win->layout->row.item_offset = 0; 17715 win->layout->row.item_width = (float)width; 17716} 17717NK_API float 17718nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width) 17719{ 17720 struct nk_window *win; 17721 NK_ASSERT(ctx); 17722 NK_ASSERT(pixel_width); 17723 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 17724 win = ctx->current; 17725 return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f); 17726} 17727NK_API void 17728nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols) 17729{ 17730 nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0); 17731} 17732NK_API void 17733nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols) 17734{ 17735 nk_row_layout(ctx, NK_STATIC, height, cols, item_width); 17736} 17737NK_API void 17738nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, 17739 float row_height, int cols) 17740{ 17741 struct nk_window *win; 17742 struct nk_panel *layout; 17743 17744 NK_ASSERT(ctx); 17745 NK_ASSERT(ctx->current); 17746 NK_ASSERT(ctx->current->layout); 17747 if (!ctx || !ctx->current || !ctx->current->layout) 17748 return; 17749 17750 win = ctx->current; 17751 layout = win->layout; 17752 nk_panel_layout(ctx, win, row_height, cols); 17753 if (fmt == NK_DYNAMIC) 17754 layout->row.type = NK_LAYOUT_DYNAMIC_ROW; 17755 else layout->row.type = NK_LAYOUT_STATIC_ROW; 17756 17757 layout->row.ratio = 0; 17758 layout->row.filled = 0; 17759 layout->row.item_width = 0; 17760 layout->row.item_offset = 0; 17761 layout->row.columns = cols; 17762} 17763NK_API void 17764nk_layout_row_push(struct nk_context *ctx, float ratio_or_width) 17765{ 17766 struct nk_window *win; 17767 struct nk_panel *layout; 17768 17769 NK_ASSERT(ctx); 17770 NK_ASSERT(ctx->current); 17771 NK_ASSERT(ctx->current->layout); 17772 if (!ctx || !ctx->current || !ctx->current->layout) 17773 return; 17774 17775 win = ctx->current; 17776 layout = win->layout; 17777 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 17778 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 17779 return; 17780 17781 if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) { 17782 float ratio = ratio_or_width; 17783 if ((ratio + layout->row.filled) > 1.0f) return; 17784 if (ratio > 0.0f) 17785 layout->row.item_width = NK_SATURATE(ratio); 17786 else layout->row.item_width = 1.0f - layout->row.filled; 17787 } else layout->row.item_width = ratio_or_width; 17788} 17789NK_API void 17790nk_layout_row_end(struct nk_context *ctx) 17791{ 17792 struct nk_window *win; 17793 struct nk_panel *layout; 17794 17795 NK_ASSERT(ctx); 17796 NK_ASSERT(ctx->current); 17797 NK_ASSERT(ctx->current->layout); 17798 if (!ctx || !ctx->current || !ctx->current->layout) 17799 return; 17800 17801 win = ctx->current; 17802 layout = win->layout; 17803 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 17804 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 17805 return; 17806 layout->row.item_width = 0; 17807 layout->row.item_offset = 0; 17808} 17809NK_API void 17810nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt, 17811 float height, int cols, const float *ratio) 17812{ 17813 int i; 17814 int n_undef = 0; 17815 struct nk_window *win; 17816 struct nk_panel *layout; 17817 17818 NK_ASSERT(ctx); 17819 NK_ASSERT(ctx->current); 17820 NK_ASSERT(ctx->current->layout); 17821 if (!ctx || !ctx->current || !ctx->current->layout) 17822 return; 17823 17824 win = ctx->current; 17825 layout = win->layout; 17826 nk_panel_layout(ctx, win, height, cols); 17827 if (fmt == NK_DYNAMIC) { 17828 /* calculate width of undefined widget ratios */ 17829 float r = 0; 17830 layout->row.ratio = ratio; 17831 for (i = 0; i < cols; ++i) { 17832 if (ratio[i] < 0.0f) 17833 n_undef++; 17834 else r += ratio[i]; 17835 } 17836 r = NK_SATURATE(1.0f - r); 17837 layout->row.type = NK_LAYOUT_DYNAMIC; 17838 layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0; 17839 } else { 17840 layout->row.ratio = ratio; 17841 layout->row.type = NK_LAYOUT_STATIC; 17842 layout->row.item_width = 0; 17843 layout->row.item_offset = 0; 17844 } 17845 layout->row.item_offset = 0; 17846 layout->row.filled = 0; 17847} 17848NK_API void 17849nk_layout_row_template_begin(struct nk_context *ctx, float height) 17850{ 17851 struct nk_window *win; 17852 struct nk_panel *layout; 17853 17854 NK_ASSERT(ctx); 17855 NK_ASSERT(ctx->current); 17856 NK_ASSERT(ctx->current->layout); 17857 if (!ctx || !ctx->current || !ctx->current->layout) 17858 return; 17859 17860 win = ctx->current; 17861 layout = win->layout; 17862 nk_panel_layout(ctx, win, height, 1); 17863 layout->row.type = NK_LAYOUT_TEMPLATE; 17864 layout->row.columns = 0; 17865 layout->row.ratio = 0; 17866 layout->row.item_width = 0; 17867 layout->row.item_height = 0; 17868 layout->row.item_offset = 0; 17869 layout->row.filled = 0; 17870 layout->row.item.x = 0; 17871 layout->row.item.y = 0; 17872 layout->row.item.w = 0; 17873 layout->row.item.h = 0; 17874} 17875NK_API void 17876nk_layout_row_template_push_dynamic(struct nk_context *ctx) 17877{ 17878 struct nk_window *win; 17879 struct nk_panel *layout; 17880 17881 NK_ASSERT(ctx); 17882 NK_ASSERT(ctx->current); 17883 NK_ASSERT(ctx->current->layout); 17884 if (!ctx || !ctx->current || !ctx->current->layout) 17885 return; 17886 17887 win = ctx->current; 17888 layout = win->layout; 17889 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17890 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17891 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17892 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17893 layout->row.templates[layout->row.columns++] = -1.0f; 17894} 17895NK_API void 17896nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width) 17897{ 17898 struct nk_window *win; 17899 struct nk_panel *layout; 17900 17901 NK_ASSERT(ctx); 17902 NK_ASSERT(ctx->current); 17903 NK_ASSERT(ctx->current->layout); 17904 if (!ctx || !ctx->current || !ctx->current->layout) 17905 return; 17906 17907 win = ctx->current; 17908 layout = win->layout; 17909 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17910 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17911 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17912 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17913 layout->row.templates[layout->row.columns++] = -min_width; 17914} 17915NK_API void 17916nk_layout_row_template_push_static(struct nk_context *ctx, float width) 17917{ 17918 struct nk_window *win; 17919 struct nk_panel *layout; 17920 17921 NK_ASSERT(ctx); 17922 NK_ASSERT(ctx->current); 17923 NK_ASSERT(ctx->current->layout); 17924 if (!ctx || !ctx->current || !ctx->current->layout) 17925 return; 17926 17927 win = ctx->current; 17928 layout = win->layout; 17929 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17930 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 17931 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17932 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 17933 layout->row.templates[layout->row.columns++] = width; 17934} 17935NK_API void 17936nk_layout_row_template_end(struct nk_context *ctx) 17937{ 17938 struct nk_window *win; 17939 struct nk_panel *layout; 17940 17941 int i = 0; 17942 int variable_count = 0; 17943 int min_variable_count = 0; 17944 float min_fixed_width = 0.0f; 17945 float total_fixed_width = 0.0f; 17946 float max_variable_width = 0.0f; 17947 17948 NK_ASSERT(ctx); 17949 NK_ASSERT(ctx->current); 17950 NK_ASSERT(ctx->current->layout); 17951 if (!ctx || !ctx->current || !ctx->current->layout) 17952 return; 17953 17954 win = ctx->current; 17955 layout = win->layout; 17956 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 17957 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 17958 for (i = 0; i < layout->row.columns; ++i) { 17959 float width = layout->row.templates[i]; 17960 if (width >= 0.0f) { 17961 total_fixed_width += width; 17962 min_fixed_width += width; 17963 } else if (width < -1.0f) { 17964 width = -width; 17965 total_fixed_width += width; 17966 max_variable_width = NK_MAX(max_variable_width, width); 17967 variable_count++; 17968 } else { 17969 min_variable_count++; 17970 variable_count++; 17971 } 17972 } 17973 if (variable_count) { 17974 float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 17975 layout->bounds.w, layout->row.columns); 17976 float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count; 17977 int enough_space = var_width >= max_variable_width; 17978 if (!enough_space) 17979 var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count; 17980 for (i = 0; i < layout->row.columns; ++i) { 17981 float *width = &layout->row.templates[i]; 17982 *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width; 17983 } 17984 } 17985} 17986NK_API void 17987nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt, 17988 float height, int widget_count) 17989{ 17990 struct nk_window *win; 17991 struct nk_panel *layout; 17992 17993 NK_ASSERT(ctx); 17994 NK_ASSERT(ctx->current); 17995 NK_ASSERT(ctx->current->layout); 17996 if (!ctx || !ctx->current || !ctx->current->layout) 17997 return; 17998 17999 win = ctx->current; 18000 layout = win->layout; 18001 nk_panel_layout(ctx, win, height, widget_count); 18002 if (fmt == NK_STATIC) 18003 layout->row.type = NK_LAYOUT_STATIC_FREE; 18004 else layout->row.type = NK_LAYOUT_DYNAMIC_FREE; 18005 18006 layout->row.ratio = 0; 18007 layout->row.filled = 0; 18008 layout->row.item_width = 0; 18009 layout->row.item_offset = 0; 18010} 18011NK_API void 18012nk_layout_space_end(struct nk_context *ctx) 18013{ 18014 struct nk_window *win; 18015 struct nk_panel *layout; 18016 18017 NK_ASSERT(ctx); 18018 NK_ASSERT(ctx->current); 18019 NK_ASSERT(ctx->current->layout); 18020 if (!ctx || !ctx->current || !ctx->current->layout) 18021 return; 18022 18023 win = ctx->current; 18024 layout = win->layout; 18025 layout->row.item_width = 0; 18026 layout->row.item_height = 0; 18027 layout->row.item_offset = 0; 18028 nk_zero(&layout->row.item, sizeof(layout->row.item)); 18029} 18030NK_API void 18031nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect) 18032{ 18033 struct nk_window *win; 18034 struct nk_panel *layout; 18035 18036 NK_ASSERT(ctx); 18037 NK_ASSERT(ctx->current); 18038 NK_ASSERT(ctx->current->layout); 18039 if (!ctx || !ctx->current || !ctx->current->layout) 18040 return; 18041 18042 win = ctx->current; 18043 layout = win->layout; 18044 layout->row.item = rect; 18045} 18046NK_API struct nk_rect 18047nk_layout_space_bounds(struct nk_context *ctx) 18048{ 18049 struct nk_rect ret; 18050 struct nk_window *win; 18051 struct nk_panel *layout; 18052 18053 NK_ASSERT(ctx); 18054 NK_ASSERT(ctx->current); 18055 NK_ASSERT(ctx->current->layout); 18056 win = ctx->current; 18057 layout = win->layout; 18058 18059 ret.x = layout->clip.x; 18060 ret.y = layout->clip.y; 18061 ret.w = layout->clip.w; 18062 ret.h = layout->row.height; 18063 return ret; 18064} 18065NK_API struct nk_rect 18066nk_layout_widget_bounds(struct nk_context *ctx) 18067{ 18068 struct nk_rect ret; 18069 struct nk_window *win; 18070 struct nk_panel *layout; 18071 18072 NK_ASSERT(ctx); 18073 NK_ASSERT(ctx->current); 18074 NK_ASSERT(ctx->current->layout); 18075 win = ctx->current; 18076 layout = win->layout; 18077 18078 ret.x = layout->at_x; 18079 ret.y = layout->at_y; 18080 ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0); 18081 ret.h = layout->row.height; 18082 return ret; 18083} 18084NK_API struct nk_vec2 18085nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret) 18086{ 18087 struct nk_window *win; 18088 struct nk_panel *layout; 18089 18090 NK_ASSERT(ctx); 18091 NK_ASSERT(ctx->current); 18092 NK_ASSERT(ctx->current->layout); 18093 win = ctx->current; 18094 layout = win->layout; 18095 18096 ret.x += layout->at_x - (float)*layout->offset_x; 18097 ret.y += layout->at_y - (float)*layout->offset_y; 18098 return ret; 18099} 18100NK_API struct nk_vec2 18101nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret) 18102{ 18103 struct nk_window *win; 18104 struct nk_panel *layout; 18105 18106 NK_ASSERT(ctx); 18107 NK_ASSERT(ctx->current); 18108 NK_ASSERT(ctx->current->layout); 18109 win = ctx->current; 18110 layout = win->layout; 18111 18112 ret.x += -layout->at_x + (float)*layout->offset_x; 18113 ret.y += -layout->at_y + (float)*layout->offset_y; 18114 return ret; 18115} 18116NK_API struct nk_rect 18117nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret) 18118{ 18119 struct nk_window *win; 18120 struct nk_panel *layout; 18121 18122 NK_ASSERT(ctx); 18123 NK_ASSERT(ctx->current); 18124 NK_ASSERT(ctx->current->layout); 18125 win = ctx->current; 18126 layout = win->layout; 18127 18128 ret.x += layout->at_x - (float)*layout->offset_x; 18129 ret.y += layout->at_y - (float)*layout->offset_y; 18130 return ret; 18131} 18132NK_API struct nk_rect 18133nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret) 18134{ 18135 struct nk_window *win; 18136 struct nk_panel *layout; 18137 18138 NK_ASSERT(ctx); 18139 NK_ASSERT(ctx->current); 18140 NK_ASSERT(ctx->current->layout); 18141 win = ctx->current; 18142 layout = win->layout; 18143 18144 ret.x += -layout->at_x + (float)*layout->offset_x; 18145 ret.y += -layout->at_y + (float)*layout->offset_y; 18146 return ret; 18147} 18148NK_LIB void 18149nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win) 18150{ 18151 struct nk_panel *layout = win->layout; 18152 struct nk_vec2 spacing = ctx->style.window.spacing; 18153 const float row_height = layout->row.height - spacing.y; 18154 nk_panel_layout(ctx, win, row_height, layout->row.columns); 18155} 18156NK_LIB void 18157nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, 18158 struct nk_window *win, int modify) 18159{ 18160 struct nk_panel *layout; 18161 const struct nk_style *style; 18162 18163 struct nk_vec2 spacing; 18164 struct nk_vec2 padding; 18165 18166 float item_offset = 0; 18167 float item_width = 0; 18168 float item_spacing = 0; 18169 float panel_space = 0; 18170 18171 NK_ASSERT(ctx); 18172 NK_ASSERT(ctx->current); 18173 NK_ASSERT(ctx->current->layout); 18174 if (!ctx || !ctx->current || !ctx->current->layout) 18175 return; 18176 18177 win = ctx->current; 18178 layout = win->layout; 18179 style = &ctx->style; 18180 NK_ASSERT(bounds); 18181 18182 spacing = style->window.spacing; 18183 padding = nk_panel_get_padding(style, layout->type); 18184 panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 18185 layout->bounds.w, layout->row.columns); 18186 18187 #define NK_FRAC(x) (x - (int)x) /* will be used to remove fookin gaps */ 18188 /* calculate the width of one item inside the current layout space */ 18189 switch (layout->row.type) { 18190 case NK_LAYOUT_DYNAMIC_FIXED: { 18191 /* scaling fixed size widgets item width */ 18192 float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns; 18193 item_offset = (float)layout->row.index * w; 18194 item_width = w + NK_FRAC(item_offset); 18195 item_spacing = (float)layout->row.index * spacing.x; 18196 } break; 18197 case NK_LAYOUT_DYNAMIC_ROW: { 18198 /* scaling single ratio widget width */ 18199 float w = layout->row.item_width * panel_space; 18200 item_offset = layout->row.item_offset; 18201 item_width = w + NK_FRAC(item_offset); 18202 item_spacing = 0; 18203 18204 if (modify) { 18205 layout->row.item_offset += w + spacing.x; 18206 layout->row.filled += layout->row.item_width; 18207 layout->row.index = 0; 18208 } 18209 } break; 18210 case NK_LAYOUT_DYNAMIC_FREE: { 18211 /* panel width depended free widget placing */ 18212 bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x); 18213 bounds->x -= (float)*layout->offset_x; 18214 bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); 18215 bounds->y -= (float)*layout->offset_y; 18216 bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x); 18217 bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y); 18218 return; 18219 } 18220 case NK_LAYOUT_DYNAMIC: { 18221 /* scaling arrays of panel width ratios for every widget */ 18222 float ratio, w; 18223 NK_ASSERT(layout->row.ratio); 18224 ratio = (layout->row.ratio[layout->row.index] < 0) ? 18225 layout->row.item_width : layout->row.ratio[layout->row.index]; 18226 18227 w = (ratio * panel_space); 18228 item_spacing = (float)layout->row.index * spacing.x; 18229 item_offset = layout->row.item_offset; 18230 item_width = w + NK_FRAC(item_offset); 18231 18232 if (modify) { 18233 layout->row.item_offset += w; 18234 layout->row.filled += ratio; 18235 } 18236 } break; 18237 case NK_LAYOUT_STATIC_FIXED: { 18238 /* non-scaling fixed widgets item width */ 18239 item_width = layout->row.item_width; 18240 item_offset = (float)layout->row.index * item_width; 18241 item_spacing = (float)layout->row.index * spacing.x; 18242 } break; 18243 case NK_LAYOUT_STATIC_ROW: { 18244 /* scaling single ratio widget width */ 18245 item_width = layout->row.item_width; 18246 item_offset = layout->row.item_offset; 18247 item_spacing = (float)layout->row.index * spacing.x; 18248 if (modify) layout->row.item_offset += item_width; 18249 } break; 18250 case NK_LAYOUT_STATIC_FREE: { 18251 /* free widget placing */ 18252 bounds->x = layout->at_x + layout->row.item.x; 18253 bounds->w = layout->row.item.w; 18254 if (((bounds->x + bounds->w) > layout->max_x) && modify) 18255 layout->max_x = (bounds->x + bounds->w); 18256 bounds->x -= (float)*layout->offset_x; 18257 bounds->y = layout->at_y + layout->row.item.y; 18258 bounds->y -= (float)*layout->offset_y; 18259 bounds->h = layout->row.item.h; 18260 return; 18261 } 18262 case NK_LAYOUT_STATIC: { 18263 /* non-scaling array of panel pixel width for every widget */ 18264 item_spacing = (float)layout->row.index * spacing.x; 18265 item_width = layout->row.ratio[layout->row.index]; 18266 item_offset = layout->row.item_offset; 18267 if (modify) layout->row.item_offset += item_width; 18268 } break; 18269 case NK_LAYOUT_TEMPLATE: { 18270 /* stretchy row layout with combined dynamic/static widget width*/ 18271 float w; 18272 NK_ASSERT(layout->row.index < layout->row.columns); 18273 NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 18274 w = layout->row.templates[layout->row.index]; 18275 item_offset = layout->row.item_offset; 18276 item_width = w + NK_FRAC(item_offset); 18277 item_spacing = (float)layout->row.index * spacing.x; 18278 if (modify) layout->row.item_offset += w; 18279 } break; 18280 #undef NK_FRAC 18281 default: NK_ASSERT(0); break; 18282 }; 18283 18284 /* set the bounds of the newly allocated widget */ 18285 bounds->w = item_width; 18286 bounds->h = layout->row.height - spacing.y; 18287 bounds->y = layout->at_y - (float)*layout->offset_y; 18288 bounds->x = layout->at_x + item_offset + item_spacing + padding.x; 18289 if (((bounds->x + bounds->w) > layout->max_x) && modify) 18290 layout->max_x = bounds->x + bounds->w; 18291 bounds->x -= (float)*layout->offset_x; 18292} 18293NK_LIB void 18294nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx) 18295{ 18296 struct nk_window *win; 18297 struct nk_panel *layout; 18298 18299 NK_ASSERT(ctx); 18300 NK_ASSERT(ctx->current); 18301 NK_ASSERT(ctx->current->layout); 18302 if (!ctx || !ctx->current || !ctx->current->layout) 18303 return; 18304 18305 /* check if the end of the row has been hit and begin new row if so */ 18306 win = ctx->current; 18307 layout = win->layout; 18308 if (layout->row.index >= layout->row.columns) 18309 nk_panel_alloc_row(ctx, win); 18310 18311 /* calculate widget position and size */ 18312 nk_layout_widget_space(bounds, ctx, win, nk_true); 18313 layout->row.index++; 18314} 18315NK_LIB void 18316nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx) 18317{ 18318 float y; 18319 int index; 18320 struct nk_window *win; 18321 struct nk_panel *layout; 18322 18323 NK_ASSERT(ctx); 18324 NK_ASSERT(ctx->current); 18325 NK_ASSERT(ctx->current->layout); 18326 if (!ctx || !ctx->current || !ctx->current->layout) 18327 return; 18328 18329 win = ctx->current; 18330 layout = win->layout; 18331 y = layout->at_y; 18332 index = layout->row.index; 18333 if (layout->row.index >= layout->row.columns) { 18334 layout->at_y += layout->row.height; 18335 layout->row.index = 0; 18336 } 18337 nk_layout_widget_space(bounds, ctx, win, nk_false); 18338 if (!layout->row.index) { 18339 bounds->x -= layout->row.item_offset; 18340 } 18341 layout->at_y = y; 18342 layout->row.index = index; 18343} 18344 18345 18346 18347 18348 18349/* =============================================================== 18350 * 18351 * TREE 18352 * 18353 * ===============================================================*/ 18354NK_INTERN int 18355nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type, 18356 struct nk_image *img, const char *title, enum nk_collapse_states *state) 18357{ 18358 struct nk_window *win; 18359 struct nk_panel *layout; 18360 const struct nk_style *style; 18361 struct nk_command_buffer *out; 18362 const struct nk_input *in; 18363 const struct nk_style_button *button; 18364 enum nk_symbol_type symbol; 18365 float row_height; 18366 18367 struct nk_vec2 item_spacing; 18368 struct nk_rect header = {0,0,0,0}; 18369 struct nk_rect sym = {0,0,0,0}; 18370 struct nk_text text; 18371 18372 nk_flags ws = 0; 18373 enum nk_widget_layout_states widget_state; 18374 18375 NK_ASSERT(ctx); 18376 NK_ASSERT(ctx->current); 18377 NK_ASSERT(ctx->current->layout); 18378 if (!ctx || !ctx->current || !ctx->current->layout) 18379 return 0; 18380 18381 /* cache some data */ 18382 win = ctx->current; 18383 layout = win->layout; 18384 out = &win->buffer; 18385 style = &ctx->style; 18386 item_spacing = style->window.spacing; 18387 18388 /* calculate header bounds and draw background */ 18389 row_height = style->font->height + 2 * style->tab.padding.y; 18390 nk_layout_set_min_row_height(ctx, row_height); 18391 nk_layout_row_dynamic(ctx, row_height, 1); 18392 nk_layout_reset_min_row_height(ctx); 18393 18394 widget_state = nk_widget(&header, ctx); 18395 if (type == NK_TREE_TAB) { 18396 const struct nk_style_item *background = &style->tab.background; 18397 if (background->type == NK_STYLE_ITEM_IMAGE) { 18398 nk_draw_image(out, header, &background->data.image, nk_white); 18399 text.background = nk_rgba(0,0,0,0); 18400 } else { 18401 text.background = background->data.color; 18402 nk_fill_rect(out, header, 0, style->tab.border_color); 18403 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 18404 style->tab.rounding, background->data.color); 18405 } 18406 } else text.background = style->window.background; 18407 18408 /* update node state */ 18409 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 18410 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 18411 if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT)) 18412 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED; 18413 18414 /* select correct button style */ 18415 if (*state == NK_MAXIMIZED) { 18416 symbol = style->tab.sym_maximize; 18417 if (type == NK_TREE_TAB) 18418 button = &style->tab.tab_maximize_button; 18419 else button = &style->tab.node_maximize_button; 18420 } else { 18421 symbol = style->tab.sym_minimize; 18422 if (type == NK_TREE_TAB) 18423 button = &style->tab.tab_minimize_button; 18424 else button = &style->tab.node_minimize_button; 18425 } 18426 18427 {/* draw triangle button */ 18428 sym.w = sym.h = style->font->height; 18429 sym.y = header.y + style->tab.padding.y; 18430 sym.x = header.x + style->tab.padding.x; 18431 nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, 18432 button, 0, style->font); 18433 18434 if (img) { 18435 /* draw optional image icon */ 18436 sym.x = sym.x + sym.w + 4 * item_spacing.x; 18437 nk_draw_image(&win->buffer, sym, img, nk_white); 18438 sym.w = style->font->height + style->tab.spacing.x;} 18439 } 18440 18441 {/* draw label */ 18442 struct nk_rect label; 18443 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 18444 label.x = sym.x + sym.w + item_spacing.x; 18445 label.y = sym.y; 18446 label.w = header.w - (sym.w + item_spacing.y + style->tab.indent); 18447 label.h = style->font->height; 18448 text.text = style->tab.text; 18449 text.padding = nk_vec2(0,0); 18450 nk_widget_text(out, label, title, nk_strlen(title), &text, 18451 NK_TEXT_LEFT, style->font);} 18452 18453 /* increase x-axis cursor widget position pointer */ 18454 if (*state == NK_MAXIMIZED) { 18455 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 18456 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 18457 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 18458 layout->row.tree_depth++; 18459 return nk_true; 18460 } else return nk_false; 18461} 18462NK_INTERN int 18463nk_tree_base(struct nk_context *ctx, enum nk_tree_type type, 18464 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 18465 const char *hash, int len, int line) 18466{ 18467 struct nk_window *win = ctx->current; 18468 int title_len = 0; 18469 nk_hash tree_hash = 0; 18470 nk_uint *state = 0; 18471 18472 /* retrieve tree state from internal widget state tables */ 18473 if (!hash) { 18474 title_len = (int)nk_strlen(title); 18475 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 18476 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 18477 state = nk_find_value(win, tree_hash); 18478 if (!state) { 18479 state = nk_add_value(ctx, win, tree_hash, 0); 18480 *state = initial_state; 18481 } 18482 return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state); 18483} 18484NK_API int 18485nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type, 18486 const char *title, enum nk_collapse_states *state) 18487{ 18488 return nk_tree_state_base(ctx, type, 0, title, state); 18489} 18490NK_API int 18491nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type, 18492 struct nk_image img, const char *title, enum nk_collapse_states *state) 18493{ 18494 return nk_tree_state_base(ctx, type, &img, title, state); 18495} 18496NK_API void 18497nk_tree_state_pop(struct nk_context *ctx) 18498{ 18499 struct nk_window *win = 0; 18500 struct nk_panel *layout = 0; 18501 18502 NK_ASSERT(ctx); 18503 NK_ASSERT(ctx->current); 18504 NK_ASSERT(ctx->current->layout); 18505 if (!ctx || !ctx->current || !ctx->current->layout) 18506 return; 18507 18508 win = ctx->current; 18509 layout = win->layout; 18510 layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x; 18511 layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x; 18512 NK_ASSERT(layout->row.tree_depth); 18513 layout->row.tree_depth--; 18514} 18515NK_API int 18516nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18517 const char *title, enum nk_collapse_states initial_state, 18518 const char *hash, int len, int line) 18519{ 18520 return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line); 18521} 18522NK_API int 18523nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18524 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 18525 const char *hash, int len,int seed) 18526{ 18527 return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed); 18528} 18529NK_API void 18530nk_tree_pop(struct nk_context *ctx) 18531{ 18532 nk_tree_state_pop(ctx); 18533} 18534NK_INTERN int 18535nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type, 18536 struct nk_image *img, const char *title, int title_len, 18537 enum nk_collapse_states *state, int *selected) 18538{ 18539 struct nk_window *win; 18540 struct nk_panel *layout; 18541 const struct nk_style *style; 18542 struct nk_command_buffer *out; 18543 const struct nk_input *in; 18544 const struct nk_style_button *button; 18545 enum nk_symbol_type symbol; 18546 float row_height; 18547 struct nk_vec2 padding; 18548 18549 int text_len; 18550 float text_width; 18551 18552 struct nk_vec2 item_spacing; 18553 struct nk_rect header = {0,0,0,0}; 18554 struct nk_rect sym = {0,0,0,0}; 18555 struct nk_text text; 18556 18557 nk_flags ws = 0; 18558 enum nk_widget_layout_states widget_state; 18559 18560 NK_ASSERT(ctx); 18561 NK_ASSERT(ctx->current); 18562 NK_ASSERT(ctx->current->layout); 18563 if (!ctx || !ctx->current || !ctx->current->layout) 18564 return 0; 18565 18566 /* cache some data */ 18567 win = ctx->current; 18568 layout = win->layout; 18569 out = &win->buffer; 18570 style = &ctx->style; 18571 item_spacing = style->window.spacing; 18572 padding = style->selectable.padding; 18573 18574 /* calculate header bounds and draw background */ 18575 row_height = style->font->height + 2 * style->tab.padding.y; 18576 nk_layout_set_min_row_height(ctx, row_height); 18577 nk_layout_row_dynamic(ctx, row_height, 1); 18578 nk_layout_reset_min_row_height(ctx); 18579 18580 widget_state = nk_widget(&header, ctx); 18581 if (type == NK_TREE_TAB) { 18582 const struct nk_style_item *background = &style->tab.background; 18583 if (background->type == NK_STYLE_ITEM_IMAGE) { 18584 nk_draw_image(out, header, &background->data.image, nk_white); 18585 text.background = nk_rgba(0,0,0,0); 18586 } else { 18587 text.background = background->data.color; 18588 nk_fill_rect(out, header, 0, style->tab.border_color); 18589 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 18590 style->tab.rounding, background->data.color); 18591 } 18592 } else text.background = style->window.background; 18593 18594 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 18595 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 18596 18597 /* select correct button style */ 18598 if (*state == NK_MAXIMIZED) { 18599 symbol = style->tab.sym_maximize; 18600 if (type == NK_TREE_TAB) 18601 button = &style->tab.tab_maximize_button; 18602 else button = &style->tab.node_maximize_button; 18603 } else { 18604 symbol = style->tab.sym_minimize; 18605 if (type == NK_TREE_TAB) 18606 button = &style->tab.tab_minimize_button; 18607 else button = &style->tab.node_minimize_button; 18608 } 18609 {/* draw triangle button */ 18610 sym.w = sym.h = style->font->height; 18611 sym.y = header.y + style->tab.padding.y; 18612 sym.x = header.x + style->tab.padding.x; 18613 if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font)) 18614 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;} 18615 18616 /* draw label */ 18617 {nk_flags dummy = 0; 18618 struct nk_rect label; 18619 /* calculate size of the text and tooltip */ 18620 text_len = nk_strlen(title); 18621 text_width = style->font->width(style->font->userdata, style->font->height, title, text_len); 18622 text_width += (4 * padding.x); 18623 18624 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 18625 label.x = sym.x + sym.w + item_spacing.x; 18626 label.y = sym.y; 18627 label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width); 18628 label.h = style->font->height; 18629 18630 if (img) { 18631 nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 18632 selected, img, &style->selectable, in, style->font); 18633 } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 18634 selected, &style->selectable, in, style->font); 18635 } 18636 /* increase x-axis cursor widget position pointer */ 18637 if (*state == NK_MAXIMIZED) { 18638 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 18639 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 18640 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 18641 layout->row.tree_depth++; 18642 return nk_true; 18643 } else return nk_false; 18644} 18645NK_INTERN int 18646nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type, 18647 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 18648 int *selected, const char *hash, int len, int line) 18649{ 18650 struct nk_window *win = ctx->current; 18651 int title_len = 0; 18652 nk_hash tree_hash = 0; 18653 nk_uint *state = 0; 18654 18655 /* retrieve tree state from internal widget state tables */ 18656 if (!hash) { 18657 title_len = (int)nk_strlen(title); 18658 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 18659 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 18660 state = nk_find_value(win, tree_hash); 18661 if (!state) { 18662 state = nk_add_value(ctx, win, tree_hash, 0); 18663 *state = initial_state; 18664 } return nk_tree_element_image_push_hashed_base(ctx, type, img, title, 18665 nk_strlen(title), (enum nk_collapse_states*)state, selected); 18666} 18667NK_API int 18668nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18669 const char *title, enum nk_collapse_states initial_state, 18670 int *selected, const char *hash, int len, int seed) 18671{ 18672 return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed); 18673} 18674NK_API int 18675nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 18676 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 18677 int *selected, const char *hash, int len,int seed) 18678{ 18679 return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed); 18680} 18681NK_API void 18682nk_tree_element_pop(struct nk_context *ctx) 18683{ 18684 nk_tree_state_pop(ctx); 18685} 18686 18687 18688 18689 18690 18691/* =============================================================== 18692 * 18693 * GROUP 18694 * 18695 * ===============================================================*/ 18696NK_API int 18697nk_group_scrolled_offset_begin(struct nk_context *ctx, 18698 nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags) 18699{ 18700 struct nk_rect bounds; 18701 struct nk_window panel; 18702 struct nk_window *win; 18703 18704 win = ctx->current; 18705 nk_panel_alloc_space(&bounds, ctx); 18706 {const struct nk_rect *c = &win->layout->clip; 18707 if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) && 18708 !(flags & NK_WINDOW_MOVABLE)) { 18709 return 0; 18710 }} 18711 if (win->flags & NK_WINDOW_ROM) 18712 flags |= NK_WINDOW_ROM; 18713 18714 /* initialize a fake window to create the panel from */ 18715 nk_zero(&panel, sizeof(panel)); 18716 panel.bounds = bounds; 18717 panel.flags = flags; 18718 panel.scrollbar.x = *x_offset; 18719 panel.scrollbar.y = *y_offset; 18720 panel.buffer = win->buffer; 18721 panel.layout = (struct nk_panel*)nk_create_panel(ctx); 18722 ctx->current = &panel; 18723 nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP); 18724 18725 win->buffer = panel.buffer; 18726 win->buffer.clip = panel.layout->clip; 18727 panel.layout->offset_x = x_offset; 18728 panel.layout->offset_y = y_offset; 18729 panel.layout->parent = win->layout; 18730 win->layout = panel.layout; 18731 18732 ctx->current = win; 18733 if ((panel.layout->flags & NK_WINDOW_CLOSED) || 18734 (panel.layout->flags & NK_WINDOW_MINIMIZED)) 18735 { 18736 nk_flags f = panel.layout->flags; 18737 nk_group_scrolled_end(ctx); 18738 if (f & NK_WINDOW_CLOSED) 18739 return NK_WINDOW_CLOSED; 18740 if (f & NK_WINDOW_MINIMIZED) 18741 return NK_WINDOW_MINIMIZED; 18742 } 18743 return 1; 18744} 18745NK_API void 18746nk_group_scrolled_end(struct nk_context *ctx) 18747{ 18748 struct nk_window *win; 18749 struct nk_panel *parent; 18750 struct nk_panel *g; 18751 18752 struct nk_rect clip; 18753 struct nk_window pan; 18754 struct nk_vec2 panel_padding; 18755 18756 NK_ASSERT(ctx); 18757 NK_ASSERT(ctx->current); 18758 if (!ctx || !ctx->current) 18759 return; 18760 18761 /* make sure nk_group_begin was called correctly */ 18762 NK_ASSERT(ctx->current); 18763 win = ctx->current; 18764 NK_ASSERT(win->layout); 18765 g = win->layout; 18766 NK_ASSERT(g->parent); 18767 parent = g->parent; 18768 18769 /* dummy window */ 18770 nk_zero_struct(pan); 18771 panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP); 18772 pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h); 18773 pan.bounds.x = g->bounds.x - panel_padding.x; 18774 pan.bounds.w = g->bounds.w + 2 * panel_padding.x; 18775 pan.bounds.h = g->bounds.h + g->header_height + g->menu.h; 18776 if (g->flags & NK_WINDOW_BORDER) { 18777 pan.bounds.x -= g->border; 18778 pan.bounds.y -= g->border; 18779 pan.bounds.w += 2*g->border; 18780 pan.bounds.h += 2*g->border; 18781 } 18782 if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) { 18783 pan.bounds.w += ctx->style.window.scrollbar_size.x; 18784 pan.bounds.h += ctx->style.window.scrollbar_size.y; 18785 } 18786 pan.scrollbar.x = *g->offset_x; 18787 pan.scrollbar.y = *g->offset_y; 18788 pan.flags = g->flags; 18789 pan.buffer = win->buffer; 18790 pan.layout = g; 18791 pan.parent = win; 18792 ctx->current = &pan; 18793 18794 /* make sure group has correct clipping rectangle */ 18795 nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y, 18796 pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x); 18797 nk_push_scissor(&pan.buffer, clip); 18798 nk_end(ctx); 18799 18800 win->buffer = pan.buffer; 18801 nk_push_scissor(&win->buffer, parent->clip); 18802 ctx->current = win; 18803 win->layout = parent; 18804 g->bounds = pan.bounds; 18805 return; 18806} 18807NK_API int 18808nk_group_scrolled_begin(struct nk_context *ctx, 18809 struct nk_scroll *scroll, const char *title, nk_flags flags) 18810{ 18811 return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags); 18812} 18813NK_API int 18814nk_group_begin_titled(struct nk_context *ctx, const char *id, 18815 const char *title, nk_flags flags) 18816{ 18817 int id_len; 18818 nk_hash id_hash; 18819 struct nk_window *win; 18820 nk_uint *x_offset; 18821 nk_uint *y_offset; 18822 18823 NK_ASSERT(ctx); 18824 NK_ASSERT(id); 18825 NK_ASSERT(ctx->current); 18826 NK_ASSERT(ctx->current->layout); 18827 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18828 return 0; 18829 18830 /* find persistent group scrollbar value */ 18831 win = ctx->current; 18832 id_len = (int)nk_strlen(id); 18833 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18834 x_offset = nk_find_value(win, id_hash); 18835 if (!x_offset) { 18836 x_offset = nk_add_value(ctx, win, id_hash, 0); 18837 y_offset = nk_add_value(ctx, win, id_hash+1, 0); 18838 18839 NK_ASSERT(x_offset); 18840 NK_ASSERT(y_offset); 18841 if (!x_offset || !y_offset) return 0; 18842 *x_offset = *y_offset = 0; 18843 } else y_offset = nk_find_value(win, id_hash+1); 18844 return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 18845} 18846NK_API int 18847nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags) 18848{ 18849 return nk_group_begin_titled(ctx, title, title, flags); 18850} 18851NK_API void 18852nk_group_end(struct nk_context *ctx) 18853{ 18854 nk_group_scrolled_end(ctx); 18855} 18856NK_API void 18857nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset) 18858{ 18859 int id_len; 18860 nk_hash id_hash; 18861 struct nk_window *win; 18862 nk_uint *x_offset_ptr; 18863 nk_uint *y_offset_ptr; 18864 18865 NK_ASSERT(ctx); 18866 NK_ASSERT(id); 18867 NK_ASSERT(ctx->current); 18868 NK_ASSERT(ctx->current->layout); 18869 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18870 return; 18871 18872 /* find persistent group scrollbar value */ 18873 win = ctx->current; 18874 id_len = (int)nk_strlen(id); 18875 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18876 x_offset_ptr = nk_find_value(win, id_hash); 18877 if (!x_offset_ptr) { 18878 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); 18879 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); 18880 18881 NK_ASSERT(x_offset_ptr); 18882 NK_ASSERT(y_offset_ptr); 18883 if (!x_offset_ptr || !y_offset_ptr) return; 18884 *x_offset_ptr = *y_offset_ptr = 0; 18885 } else y_offset_ptr = nk_find_value(win, id_hash+1); 18886 if (x_offset) 18887 *x_offset = *x_offset_ptr; 18888 if (y_offset) 18889 *y_offset = *y_offset_ptr; 18890} 18891NK_API void 18892nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset) 18893{ 18894 int id_len; 18895 nk_hash id_hash; 18896 struct nk_window *win; 18897 nk_uint *x_offset_ptr; 18898 nk_uint *y_offset_ptr; 18899 18900 NK_ASSERT(ctx); 18901 NK_ASSERT(id); 18902 NK_ASSERT(ctx->current); 18903 NK_ASSERT(ctx->current->layout); 18904 if (!ctx || !ctx->current || !ctx->current->layout || !id) 18905 return; 18906 18907 /* find persistent group scrollbar value */ 18908 win = ctx->current; 18909 id_len = (int)nk_strlen(id); 18910 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 18911 x_offset_ptr = nk_find_value(win, id_hash); 18912 if (!x_offset_ptr) { 18913 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); 18914 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); 18915 18916 NK_ASSERT(x_offset_ptr); 18917 NK_ASSERT(y_offset_ptr); 18918 if (!x_offset_ptr || !y_offset_ptr) return; 18919 *x_offset_ptr = *y_offset_ptr = 0; 18920 } else y_offset_ptr = nk_find_value(win, id_hash+1); 18921 *x_offset_ptr = x_offset; 18922 *y_offset_ptr = y_offset; 18923} 18924 18925 18926 18927 18928/* =============================================================== 18929 * 18930 * LIST VIEW 18931 * 18932 * ===============================================================*/ 18933NK_API int 18934nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view, 18935 const char *title, nk_flags flags, int row_height, int row_count) 18936{ 18937 int title_len; 18938 nk_hash title_hash; 18939 nk_uint *x_offset; 18940 nk_uint *y_offset; 18941 18942 int result; 18943 struct nk_window *win; 18944 struct nk_panel *layout; 18945 const struct nk_style *style; 18946 struct nk_vec2 item_spacing; 18947 18948 NK_ASSERT(ctx); 18949 NK_ASSERT(view); 18950 NK_ASSERT(title); 18951 if (!ctx || !view || !title) return 0; 18952 18953 win = ctx->current; 18954 style = &ctx->style; 18955 item_spacing = style->window.spacing; 18956 row_height += NK_MAX(0, (int)item_spacing.y); 18957 18958 /* find persistent list view scrollbar offset */ 18959 title_len = (int)nk_strlen(title); 18960 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); 18961 x_offset = nk_find_value(win, title_hash); 18962 if (!x_offset) { 18963 x_offset = nk_add_value(ctx, win, title_hash, 0); 18964 y_offset = nk_add_value(ctx, win, title_hash+1, 0); 18965 18966 NK_ASSERT(x_offset); 18967 NK_ASSERT(y_offset); 18968 if (!x_offset || !y_offset) return 0; 18969 *x_offset = *y_offset = 0; 18970 } else y_offset = nk_find_value(win, title_hash+1); 18971 view->scroll_value = *y_offset; 18972 view->scroll_pointer = y_offset; 18973 18974 *y_offset = 0; 18975 result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 18976 win = ctx->current; 18977 layout = win->layout; 18978 18979 view->total_height = row_height * NK_MAX(row_count,1); 18980 view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f); 18981 view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0); 18982 view->count = NK_MIN(view->count, row_count - view->begin); 18983 view->end = view->begin + view->count; 18984 view->ctx = ctx; 18985 return result; 18986} 18987NK_API void 18988nk_list_view_end(struct nk_list_view *view) 18989{ 18990 struct nk_context *ctx; 18991 struct nk_window *win; 18992 struct nk_panel *layout; 18993 18994 NK_ASSERT(view); 18995 NK_ASSERT(view->ctx); 18996 NK_ASSERT(view->scroll_pointer); 18997 if (!view || !view->ctx) return; 18998 18999 ctx = view->ctx; 19000 win = ctx->current; 19001 layout = win->layout; 19002 layout->at_y = layout->bounds.y + (float)view->total_height; 19003 *view->scroll_pointer = *view->scroll_pointer + view->scroll_value; 19004 nk_group_end(view->ctx); 19005} 19006 19007 19008 19009 19010 19011/* =============================================================== 19012 * 19013 * WIDGET 19014 * 19015 * ===============================================================*/ 19016NK_API struct nk_rect 19017nk_widget_bounds(struct nk_context *ctx) 19018{ 19019 struct nk_rect bounds; 19020 NK_ASSERT(ctx); 19021 NK_ASSERT(ctx->current); 19022 if (!ctx || !ctx->current) 19023 return nk_rect(0,0,0,0); 19024 nk_layout_peek(&bounds, ctx); 19025 return bounds; 19026} 19027NK_API struct nk_vec2 19028nk_widget_position(struct nk_context *ctx) 19029{ 19030 struct nk_rect bounds; 19031 NK_ASSERT(ctx); 19032 NK_ASSERT(ctx->current); 19033 if (!ctx || !ctx->current) 19034 return nk_vec2(0,0); 19035 19036 nk_layout_peek(&bounds, ctx); 19037 return nk_vec2(bounds.x, bounds.y); 19038} 19039NK_API struct nk_vec2 19040nk_widget_size(struct nk_context *ctx) 19041{ 19042 struct nk_rect bounds; 19043 NK_ASSERT(ctx); 19044 NK_ASSERT(ctx->current); 19045 if (!ctx || !ctx->current) 19046 return nk_vec2(0,0); 19047 19048 nk_layout_peek(&bounds, ctx); 19049 return nk_vec2(bounds.w, bounds.h); 19050} 19051NK_API float 19052nk_widget_width(struct nk_context *ctx) 19053{ 19054 struct nk_rect bounds; 19055 NK_ASSERT(ctx); 19056 NK_ASSERT(ctx->current); 19057 if (!ctx || !ctx->current) 19058 return 0; 19059 19060 nk_layout_peek(&bounds, ctx); 19061 return bounds.w; 19062} 19063NK_API float 19064nk_widget_height(struct nk_context *ctx) 19065{ 19066 struct nk_rect bounds; 19067 NK_ASSERT(ctx); 19068 NK_ASSERT(ctx->current); 19069 if (!ctx || !ctx->current) 19070 return 0; 19071 19072 nk_layout_peek(&bounds, ctx); 19073 return bounds.h; 19074} 19075NK_API int 19076nk_widget_is_hovered(struct nk_context *ctx) 19077{ 19078 struct nk_rect c, v; 19079 struct nk_rect bounds; 19080 NK_ASSERT(ctx); 19081 NK_ASSERT(ctx->current); 19082 if (!ctx || !ctx->current || ctx->active != ctx->current) 19083 return 0; 19084 19085 c = ctx->current->layout->clip; 19086 c.x = (float)((int)c.x); 19087 c.y = (float)((int)c.y); 19088 c.w = (float)((int)c.w); 19089 c.h = (float)((int)c.h); 19090 19091 nk_layout_peek(&bounds, ctx); 19092 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 19093 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 19094 return 0; 19095 return nk_input_is_mouse_hovering_rect(&ctx->input, bounds); 19096} 19097NK_API int 19098nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn) 19099{ 19100 struct nk_rect c, v; 19101 struct nk_rect bounds; 19102 NK_ASSERT(ctx); 19103 NK_ASSERT(ctx->current); 19104 if (!ctx || !ctx->current || ctx->active != ctx->current) 19105 return 0; 19106 19107 c = ctx->current->layout->clip; 19108 c.x = (float)((int)c.x); 19109 c.y = (float)((int)c.y); 19110 c.w = (float)((int)c.w); 19111 c.h = (float)((int)c.h); 19112 19113 nk_layout_peek(&bounds, ctx); 19114 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 19115 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 19116 return 0; 19117 return nk_input_mouse_clicked(&ctx->input, btn, bounds); 19118} 19119NK_API int 19120nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down) 19121{ 19122 struct nk_rect c, v; 19123 struct nk_rect bounds; 19124 NK_ASSERT(ctx); 19125 NK_ASSERT(ctx->current); 19126 if (!ctx || !ctx->current || ctx->active != ctx->current) 19127 return 0; 19128 19129 c = ctx->current->layout->clip; 19130 c.x = (float)((int)c.x); 19131 c.y = (float)((int)c.y); 19132 c.w = (float)((int)c.w); 19133 c.h = (float)((int)c.h); 19134 19135 nk_layout_peek(&bounds, ctx); 19136 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 19137 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 19138 return 0; 19139 return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down); 19140} 19141NK_API enum nk_widget_layout_states 19142nk_widget(struct nk_rect *bounds, const struct nk_context *ctx) 19143{ 19144 struct nk_rect c, v; 19145 struct nk_window *win; 19146 struct nk_panel *layout; 19147 const struct nk_input *in; 19148 19149 NK_ASSERT(ctx); 19150 NK_ASSERT(ctx->current); 19151 NK_ASSERT(ctx->current->layout); 19152 if (!ctx || !ctx->current || !ctx->current->layout) 19153 return NK_WIDGET_INVALID; 19154 19155 /* allocate space and check if the widget needs to be updated and drawn */ 19156 nk_panel_alloc_space(bounds, ctx); 19157 win = ctx->current; 19158 layout = win->layout; 19159 in = &ctx->input; 19160 c = layout->clip; 19161 19162 /* if one of these triggers you forgot to add an `if` condition around either 19163 a window, group, popup, combobox or contextual menu `begin` and `end` block. 19164 Example: 19165 if (nk_begin(...) {...} nk_end(...); or 19166 if (nk_group_begin(...) { nk_group_end(...);} */ 19167 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 19168 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 19169 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 19170 19171 /* need to convert to int here to remove floating point errors */ 19172 bounds->x = (float)((int)bounds->x); 19173 bounds->y = (float)((int)bounds->y); 19174 bounds->w = (float)((int)bounds->w); 19175 bounds->h = (float)((int)bounds->h); 19176 19177 c.x = (float)((int)c.x); 19178 c.y = (float)((int)c.y); 19179 c.w = (float)((int)c.w); 19180 c.h = (float)((int)c.h); 19181 19182 nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h); 19183 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h)) 19184 return NK_WIDGET_INVALID; 19185 if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h)) 19186 return NK_WIDGET_ROM; 19187 return NK_WIDGET_VALID; 19188} 19189NK_API enum nk_widget_layout_states 19190nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx, 19191 struct nk_vec2 item_padding) 19192{ 19193 /* update the bounds to stand without padding */ 19194 struct nk_window *win; 19195 struct nk_style *style; 19196 struct nk_panel *layout; 19197 enum nk_widget_layout_states state; 19198 struct nk_vec2 panel_padding; 19199 19200 NK_ASSERT(ctx); 19201 NK_ASSERT(ctx->current); 19202 NK_ASSERT(ctx->current->layout); 19203 if (!ctx || !ctx->current || !ctx->current->layout) 19204 return NK_WIDGET_INVALID; 19205 19206 win = ctx->current; 19207 style = &ctx->style; 19208 layout = win->layout; 19209 state = nk_widget(bounds, ctx); 19210 19211 panel_padding = nk_panel_get_padding(style, layout->type); 19212 if (layout->row.index == 1) { 19213 bounds->w += panel_padding.x; 19214 bounds->x -= panel_padding.x; 19215 } else bounds->x -= item_padding.x; 19216 19217 if (layout->row.index == layout->row.columns) 19218 bounds->w += panel_padding.x; 19219 else bounds->w += item_padding.x; 19220 return state; 19221} 19222NK_API void 19223nk_spacing(struct nk_context *ctx, int cols) 19224{ 19225 struct nk_window *win; 19226 struct nk_panel *layout; 19227 struct nk_rect none; 19228 int i, index, rows; 19229 19230 NK_ASSERT(ctx); 19231 NK_ASSERT(ctx->current); 19232 NK_ASSERT(ctx->current->layout); 19233 if (!ctx || !ctx->current || !ctx->current->layout) 19234 return; 19235 19236 /* spacing over row boundaries */ 19237 win = ctx->current; 19238 layout = win->layout; 19239 index = (layout->row.index + cols) % layout->row.columns; 19240 rows = (layout->row.index + cols) / layout->row.columns; 19241 if (rows) { 19242 for (i = 0; i < rows; ++i) 19243 nk_panel_alloc_row(ctx, win); 19244 cols = index; 19245 } 19246 /* non table layout need to allocate space */ 19247 if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED && 19248 layout->row.type != NK_LAYOUT_STATIC_FIXED) { 19249 for (i = 0; i < cols; ++i) 19250 nk_panel_alloc_space(&none, ctx); 19251 } layout->row.index = index; 19252} 19253 19254 19255 19256 19257 19258/* =============================================================== 19259 * 19260 * TEXT 19261 * 19262 * ===============================================================*/ 19263NK_LIB void 19264nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, 19265 const char *string, int len, const struct nk_text *t, 19266 nk_flags a, const struct nk_user_font *f) 19267{ 19268 struct nk_rect label; 19269 float text_width; 19270 19271 NK_ASSERT(o); 19272 NK_ASSERT(t); 19273 if (!o || !t) return; 19274 19275 b.h = NK_MAX(b.h, 2 * t->padding.y); 19276 label.x = 0; label.w = 0; 19277 label.y = b.y + t->padding.y; 19278 label.h = NK_MIN(f->height, b.h - 2 * t->padding.y); 19279 19280 text_width = f->width(f->userdata, f->height, (const char*)string, len); 19281 text_width += (2.0f * t->padding.x); 19282 19283 /* align in x-axis */ 19284 if (a & NK_TEXT_ALIGN_LEFT) { 19285 label.x = b.x + t->padding.x; 19286 label.w = NK_MAX(0, b.w - 2 * t->padding.x); 19287 } else if (a & NK_TEXT_ALIGN_CENTERED) { 19288 label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width); 19289 label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); 19290 label.x = NK_MAX(b.x + t->padding.x, label.x); 19291 label.w = NK_MIN(b.x + b.w, label.x + label.w); 19292 if (label.w >= label.x) label.w -= label.x; 19293 } else if (a & NK_TEXT_ALIGN_RIGHT) { 19294 label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); 19295 label.w = (float)text_width + 2 * t->padding.x; 19296 } else return; 19297 19298 /* align in y-axis */ 19299 if (a & NK_TEXT_ALIGN_MIDDLE) { 19300 label.y = b.y + b.h/2.0f - (float)f->height/2.0f; 19301 label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f)); 19302 } else if (a & NK_TEXT_ALIGN_BOTTOM) { 19303 label.y = b.y + b.h - f->height; 19304 label.h = f->height; 19305 } 19306 nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text); 19307} 19308NK_LIB void 19309nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, 19310 const char *string, int len, const struct nk_text *t, 19311 const struct nk_user_font *f) 19312{ 19313 float width; 19314 int glyphs = 0; 19315 int fitting = 0; 19316 int done = 0; 19317 struct nk_rect line; 19318 struct nk_text text; 19319 NK_INTERN nk_rune seperator[] = {' '}; 19320 19321 NK_ASSERT(o); 19322 NK_ASSERT(t); 19323 if (!o || !t) return; 19324 19325 text.padding = nk_vec2(0,0); 19326 text.background = t->background; 19327 text.text = t->text; 19328 19329 b.w = NK_MAX(b.w, 2 * t->padding.x); 19330 b.h = NK_MAX(b.h, 2 * t->padding.y); 19331 b.h = b.h - 2 * t->padding.y; 19332 19333 line.x = b.x + t->padding.x; 19334 line.y = b.y + t->padding.y; 19335 line.w = b.w - 2 * t->padding.x; 19336 line.h = 2 * t->padding.y + f->height; 19337 19338 fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 19339 while (done < len) { 19340 if (!fitting || line.y + line.h >= (b.y + b.h)) break; 19341 nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f); 19342 done += fitting; 19343 line.y += f->height + 2 * t->padding.y; 19344 fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 19345 } 19346} 19347NK_API void 19348nk_text_colored(struct nk_context *ctx, const char *str, int len, 19349 nk_flags alignment, struct nk_color color) 19350{ 19351 struct nk_window *win; 19352 const struct nk_style *style; 19353 19354 struct nk_vec2 item_padding; 19355 struct nk_rect bounds; 19356 struct nk_text text; 19357 19358 NK_ASSERT(ctx); 19359 NK_ASSERT(ctx->current); 19360 NK_ASSERT(ctx->current->layout); 19361 if (!ctx || !ctx->current || !ctx->current->layout) return; 19362 19363 win = ctx->current; 19364 style = &ctx->style; 19365 nk_panel_alloc_space(&bounds, ctx); 19366 item_padding = style->text.padding; 19367 19368 text.padding.x = item_padding.x; 19369 text.padding.y = item_padding.y; 19370 text.background = style->window.background; 19371 text.text = color; 19372 nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font); 19373} 19374NK_API void 19375nk_text_wrap_colored(struct nk_context *ctx, const char *str, 19376 int len, struct nk_color color) 19377{ 19378 struct nk_window *win; 19379 const struct nk_style *style; 19380 19381 struct nk_vec2 item_padding; 19382 struct nk_rect bounds; 19383 struct nk_text text; 19384 19385 NK_ASSERT(ctx); 19386 NK_ASSERT(ctx->current); 19387 NK_ASSERT(ctx->current->layout); 19388 if (!ctx || !ctx->current || !ctx->current->layout) return; 19389 19390 win = ctx->current; 19391 style = &ctx->style; 19392 nk_panel_alloc_space(&bounds, ctx); 19393 item_padding = style->text.padding; 19394 19395 text.padding.x = item_padding.x; 19396 text.padding.y = item_padding.y; 19397 text.background = style->window.background; 19398 text.text = color; 19399 nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font); 19400} 19401#ifdef NK_INCLUDE_STANDARD_VARARGS 19402NK_API void 19403nk_labelf_colored(struct nk_context *ctx, nk_flags flags, 19404 struct nk_color color, const char *fmt, ...) 19405{ 19406 va_list args; 19407 va_start(args, fmt); 19408 nk_labelfv_colored(ctx, flags, color, fmt, args); 19409 va_end(args); 19410} 19411NK_API void 19412nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color, 19413 const char *fmt, ...) 19414{ 19415 va_list args; 19416 va_start(args, fmt); 19417 nk_labelfv_colored_wrap(ctx, color, fmt, args); 19418 va_end(args); 19419} 19420NK_API void 19421nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...) 19422{ 19423 va_list args; 19424 va_start(args, fmt); 19425 nk_labelfv(ctx, flags, fmt, args); 19426 va_end(args); 19427} 19428NK_API void 19429nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...) 19430{ 19431 va_list args; 19432 va_start(args, fmt); 19433 nk_labelfv_wrap(ctx, fmt, args); 19434 va_end(args); 19435} 19436NK_API void 19437nk_labelfv_colored(struct nk_context *ctx, nk_flags flags, 19438 struct nk_color color, const char *fmt, va_list args) 19439{ 19440 char buf[256]; 19441 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19442 nk_label_colored(ctx, buf, flags, color); 19443} 19444 19445NK_API void 19446nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color, 19447 const char *fmt, va_list args) 19448{ 19449 char buf[256]; 19450 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19451 nk_label_colored_wrap(ctx, buf, color); 19452} 19453 19454NK_API void 19455nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args) 19456{ 19457 char buf[256]; 19458 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19459 nk_label(ctx, buf, flags); 19460} 19461 19462NK_API void 19463nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args) 19464{ 19465 char buf[256]; 19466 nk_strfmt(buf, NK_LEN(buf), fmt, args); 19467 nk_label_wrap(ctx, buf); 19468} 19469 19470NK_API void 19471nk_value_bool(struct nk_context *ctx, const char *prefix, int value) 19472{ 19473 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false")); 19474} 19475NK_API void 19476nk_value_int(struct nk_context *ctx, const char *prefix, int value) 19477{ 19478 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value); 19479} 19480NK_API void 19481nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value) 19482{ 19483 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value); 19484} 19485NK_API void 19486nk_value_float(struct nk_context *ctx, const char *prefix, float value) 19487{ 19488 double double_value = (double)value; 19489 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value); 19490} 19491NK_API void 19492nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c) 19493{ 19494 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a); 19495} 19496NK_API void 19497nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color) 19498{ 19499 double c[4]; nk_color_dv(c, color); 19500 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)", 19501 p, c[0], c[1], c[2], c[3]); 19502} 19503NK_API void 19504nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color) 19505{ 19506 char hex[16]; 19507 nk_color_hex_rgba(hex, color); 19508 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex); 19509} 19510#endif 19511NK_API void 19512nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment) 19513{ 19514 NK_ASSERT(ctx); 19515 if (!ctx) return; 19516 nk_text_colored(ctx, str, len, alignment, ctx->style.text.color); 19517} 19518NK_API void 19519nk_text_wrap(struct nk_context *ctx, const char *str, int len) 19520{ 19521 NK_ASSERT(ctx); 19522 if (!ctx) return; 19523 nk_text_wrap_colored(ctx, str, len, ctx->style.text.color); 19524} 19525NK_API void 19526nk_label(struct nk_context *ctx, const char *str, nk_flags alignment) 19527{ 19528 nk_text(ctx, str, nk_strlen(str), alignment); 19529} 19530NK_API void 19531nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align, 19532 struct nk_color color) 19533{ 19534 nk_text_colored(ctx, str, nk_strlen(str), align, color); 19535} 19536NK_API void 19537nk_label_wrap(struct nk_context *ctx, const char *str) 19538{ 19539 nk_text_wrap(ctx, str, nk_strlen(str)); 19540} 19541NK_API void 19542nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color) 19543{ 19544 nk_text_wrap_colored(ctx, str, nk_strlen(str), color); 19545} 19546 19547 19548 19549 19550 19551/* =============================================================== 19552 * 19553 * IMAGE 19554 * 19555 * ===============================================================*/ 19556NK_API nk_handle 19557nk_handle_ptr(void *ptr) 19558{ 19559 nk_handle handle = {0}; 19560 handle.ptr = ptr; 19561 return handle; 19562} 19563NK_API nk_handle 19564nk_handle_id(int id) 19565{ 19566 nk_handle handle; 19567 nk_zero_struct(handle); 19568 handle.id = id; 19569 return handle; 19570} 19571NK_API struct nk_image 19572nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r) 19573{ 19574 struct nk_image s; 19575 nk_zero(&s, sizeof(s)); 19576 s.handle.ptr = ptr; 19577 s.w = w; s.h = h; 19578 s.region[0] = (unsigned short)r.x; 19579 s.region[1] = (unsigned short)r.y; 19580 s.region[2] = (unsigned short)r.w; 19581 s.region[3] = (unsigned short)r.h; 19582 return s; 19583} 19584NK_API struct nk_image 19585nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r) 19586{ 19587 struct nk_image s; 19588 nk_zero(&s, sizeof(s)); 19589 s.handle.id = id; 19590 s.w = w; s.h = h; 19591 s.region[0] = (unsigned short)r.x; 19592 s.region[1] = (unsigned short)r.y; 19593 s.region[2] = (unsigned short)r.w; 19594 s.region[3] = (unsigned short)r.h; 19595 return s; 19596} 19597NK_API struct nk_image 19598nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h, 19599 struct nk_rect r) 19600{ 19601 struct nk_image s; 19602 nk_zero(&s, sizeof(s)); 19603 s.handle = handle; 19604 s.w = w; s.h = h; 19605 s.region[0] = (unsigned short)r.x; 19606 s.region[1] = (unsigned short)r.y; 19607 s.region[2] = (unsigned short)r.w; 19608 s.region[3] = (unsigned short)r.h; 19609 return s; 19610} 19611NK_API struct nk_image 19612nk_image_handle(nk_handle handle) 19613{ 19614 struct nk_image s; 19615 nk_zero(&s, sizeof(s)); 19616 s.handle = handle; 19617 s.w = 0; s.h = 0; 19618 s.region[0] = 0; 19619 s.region[1] = 0; 19620 s.region[2] = 0; 19621 s.region[3] = 0; 19622 return s; 19623} 19624NK_API struct nk_image 19625nk_image_ptr(void *ptr) 19626{ 19627 struct nk_image s; 19628 nk_zero(&s, sizeof(s)); 19629 NK_ASSERT(ptr); 19630 s.handle.ptr = ptr; 19631 s.w = 0; s.h = 0; 19632 s.region[0] = 0; 19633 s.region[1] = 0; 19634 s.region[2] = 0; 19635 s.region[3] = 0; 19636 return s; 19637} 19638NK_API struct nk_image 19639nk_image_id(int id) 19640{ 19641 struct nk_image s; 19642 nk_zero(&s, sizeof(s)); 19643 s.handle.id = id; 19644 s.w = 0; s.h = 0; 19645 s.region[0] = 0; 19646 s.region[1] = 0; 19647 s.region[2] = 0; 19648 s.region[3] = 0; 19649 return s; 19650} 19651NK_API int 19652nk_image_is_subimage(const struct nk_image* img) 19653{ 19654 NK_ASSERT(img); 19655 return !(img->w == 0 && img->h == 0); 19656} 19657NK_API void 19658nk_image(struct nk_context *ctx, struct nk_image img) 19659{ 19660 struct nk_window *win; 19661 struct nk_rect bounds; 19662 19663 NK_ASSERT(ctx); 19664 NK_ASSERT(ctx->current); 19665 NK_ASSERT(ctx->current->layout); 19666 if (!ctx || !ctx->current || !ctx->current->layout) return; 19667 19668 win = ctx->current; 19669 if (!nk_widget(&bounds, ctx)) return; 19670 nk_draw_image(&win->buffer, bounds, &img, nk_white); 19671} 19672NK_API void 19673nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col) 19674{ 19675 struct nk_window *win; 19676 struct nk_rect bounds; 19677 19678 NK_ASSERT(ctx); 19679 NK_ASSERT(ctx->current); 19680 NK_ASSERT(ctx->current->layout); 19681 if (!ctx || !ctx->current || !ctx->current->layout) return; 19682 19683 win = ctx->current; 19684 if (!nk_widget(&bounds, ctx)) return; 19685 nk_draw_image(&win->buffer, bounds, &img, col); 19686} 19687 19688 19689 19690 19691 19692/* ============================================================== 19693 * 19694 * BUTTON 19695 * 19696 * ===============================================================*/ 19697NK_LIB void 19698nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, 19699 struct nk_rect content, struct nk_color background, struct nk_color foreground, 19700 float border_width, const struct nk_user_font *font) 19701{ 19702 switch (type) { 19703 case NK_SYMBOL_X: 19704 case NK_SYMBOL_UNDERSCORE: 19705 case NK_SYMBOL_PLUS: 19706 case NK_SYMBOL_MINUS: { 19707 /* single character text symbol */ 19708 const char *X = (type == NK_SYMBOL_X) ? "x": 19709 (type == NK_SYMBOL_UNDERSCORE) ? "_": 19710 (type == NK_SYMBOL_PLUS) ? "+": "-"; 19711 struct nk_text text; 19712 text.padding = nk_vec2(0,0); 19713 text.background = background; 19714 text.text = foreground; 19715 nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font); 19716 } break; 19717 case NK_SYMBOL_CIRCLE_SOLID: 19718 case NK_SYMBOL_CIRCLE_OUTLINE: 19719 case NK_SYMBOL_RECT_SOLID: 19720 case NK_SYMBOL_RECT_OUTLINE: { 19721 /* simple empty/filled shapes */ 19722 if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) { 19723 nk_fill_rect(out, content, 0, foreground); 19724 if (type == NK_SYMBOL_RECT_OUTLINE) 19725 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background); 19726 } else { 19727 nk_fill_circle(out, content, foreground); 19728 if (type == NK_SYMBOL_CIRCLE_OUTLINE) 19729 nk_fill_circle(out, nk_shrink_rect(content, 1), background); 19730 } 19731 } break; 19732 case NK_SYMBOL_TRIANGLE_UP: 19733 case NK_SYMBOL_TRIANGLE_DOWN: 19734 case NK_SYMBOL_TRIANGLE_LEFT: 19735 case NK_SYMBOL_TRIANGLE_RIGHT: { 19736 enum nk_heading heading; 19737 struct nk_vec2 points[3]; 19738 heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT : 19739 (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT: 19740 (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN; 19741 nk_triangle_from_direction(points, content, 0, 0, heading); 19742 nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, 19743 points[2].x, points[2].y, foreground); 19744 } break; 19745 default: 19746 case NK_SYMBOL_NONE: 19747 case NK_SYMBOL_MAX: break; 19748 } 19749} 19750NK_LIB int 19751nk_button_behavior(nk_flags *state, struct nk_rect r, 19752 const struct nk_input *i, enum nk_button_behavior behavior) 19753{ 19754 int ret = 0; 19755 nk_widget_state_reset(state); 19756 if (!i) return 0; 19757 if (nk_input_is_mouse_hovering_rect(i, r)) { 19758 *state = NK_WIDGET_STATE_HOVERED; 19759 if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT)) 19760 *state = NK_WIDGET_STATE_ACTIVE; 19761 if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) { 19762 ret = (behavior != NK_BUTTON_DEFAULT) ? 19763 nk_input_is_mouse_down(i, NK_BUTTON_LEFT): 19764#ifdef NK_BUTTON_TRIGGER_ON_RELEASE 19765 nk_input_is_mouse_released(i, NK_BUTTON_LEFT); 19766#else 19767 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT); 19768#endif 19769 } 19770 } 19771 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r)) 19772 *state |= NK_WIDGET_STATE_ENTERED; 19773 else if (nk_input_is_mouse_prev_hovering_rect(i, r)) 19774 *state |= NK_WIDGET_STATE_LEFT; 19775 return ret; 19776} 19777NK_LIB const struct nk_style_item* 19778nk_draw_button(struct nk_command_buffer *out, 19779 const struct nk_rect *bounds, nk_flags state, 19780 const struct nk_style_button *style) 19781{ 19782 const struct nk_style_item *background; 19783 if (state & NK_WIDGET_STATE_HOVER) 19784 background = &style->hover; 19785 else if (state & NK_WIDGET_STATE_ACTIVED) 19786 background = &style->active; 19787 else background = &style->normal; 19788 19789 if (background->type == NK_STYLE_ITEM_IMAGE) { 19790 nk_draw_image(out, *bounds, &background->data.image, nk_white); 19791 } else { 19792 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 19793 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 19794 } 19795 return background; 19796} 19797NK_LIB int 19798nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, 19799 const struct nk_style_button *style, const struct nk_input *in, 19800 enum nk_button_behavior behavior, struct nk_rect *content) 19801{ 19802 struct nk_rect bounds; 19803 NK_ASSERT(style); 19804 NK_ASSERT(state); 19805 NK_ASSERT(out); 19806 if (!out || !style) 19807 return nk_false; 19808 19809 /* calculate button content space */ 19810 content->x = r.x + style->padding.x + style->border + style->rounding; 19811 content->y = r.y + style->padding.y + style->border + style->rounding; 19812 content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2); 19813 content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2); 19814 19815 /* execute button behavior */ 19816 bounds.x = r.x - style->touch_padding.x; 19817 bounds.y = r.y - style->touch_padding.y; 19818 bounds.w = r.w + 2 * style->touch_padding.x; 19819 bounds.h = r.h + 2 * style->touch_padding.y; 19820 return nk_button_behavior(state, bounds, in, behavior); 19821} 19822NK_LIB void 19823nk_draw_button_text(struct nk_command_buffer *out, 19824 const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, 19825 const struct nk_style_button *style, const char *txt, int len, 19826 nk_flags text_alignment, const struct nk_user_font *font) 19827{ 19828 struct nk_text text; 19829 const struct nk_style_item *background; 19830 background = nk_draw_button(out, bounds, state, style); 19831 19832 /* select correct colors/images */ 19833 if (background->type == NK_STYLE_ITEM_COLOR) 19834 text.background = background->data.color; 19835 else text.background = style->text_background; 19836 if (state & NK_WIDGET_STATE_HOVER) 19837 text.text = style->text_hover; 19838 else if (state & NK_WIDGET_STATE_ACTIVED) 19839 text.text = style->text_active; 19840 else text.text = style->text_normal; 19841 19842 text.padding = nk_vec2(0,0); 19843 nk_widget_text(out, *content, txt, len, &text, text_alignment, font); 19844} 19845NK_LIB int 19846nk_do_button_text(nk_flags *state, 19847 struct nk_command_buffer *out, struct nk_rect bounds, 19848 const char *string, int len, nk_flags align, enum nk_button_behavior behavior, 19849 const struct nk_style_button *style, const struct nk_input *in, 19850 const struct nk_user_font *font) 19851{ 19852 struct nk_rect content; 19853 int ret = nk_false; 19854 19855 NK_ASSERT(state); 19856 NK_ASSERT(style); 19857 NK_ASSERT(out); 19858 NK_ASSERT(string); 19859 NK_ASSERT(font); 19860 if (!out || !style || !font || !string) 19861 return nk_false; 19862 19863 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19864 if (style->draw_begin) style->draw_begin(out, style->userdata); 19865 nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font); 19866 if (style->draw_end) style->draw_end(out, style->userdata); 19867 return ret; 19868} 19869NK_LIB void 19870nk_draw_button_symbol(struct nk_command_buffer *out, 19871 const struct nk_rect *bounds, const struct nk_rect *content, 19872 nk_flags state, const struct nk_style_button *style, 19873 enum nk_symbol_type type, const struct nk_user_font *font) 19874{ 19875 struct nk_color sym, bg; 19876 const struct nk_style_item *background; 19877 19878 /* select correct colors/images */ 19879 background = nk_draw_button(out, bounds, state, style); 19880 if (background->type == NK_STYLE_ITEM_COLOR) 19881 bg = background->data.color; 19882 else bg = style->text_background; 19883 19884 if (state & NK_WIDGET_STATE_HOVER) 19885 sym = style->text_hover; 19886 else if (state & NK_WIDGET_STATE_ACTIVED) 19887 sym = style->text_active; 19888 else sym = style->text_normal; 19889 nk_draw_symbol(out, type, *content, bg, sym, 1, font); 19890} 19891NK_LIB int 19892nk_do_button_symbol(nk_flags *state, 19893 struct nk_command_buffer *out, struct nk_rect bounds, 19894 enum nk_symbol_type symbol, enum nk_button_behavior behavior, 19895 const struct nk_style_button *style, const struct nk_input *in, 19896 const struct nk_user_font *font) 19897{ 19898 int ret; 19899 struct nk_rect content; 19900 19901 NK_ASSERT(state); 19902 NK_ASSERT(style); 19903 NK_ASSERT(font); 19904 NK_ASSERT(out); 19905 if (!out || !style || !font || !state) 19906 return nk_false; 19907 19908 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19909 if (style->draw_begin) style->draw_begin(out, style->userdata); 19910 nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); 19911 if (style->draw_end) style->draw_end(out, style->userdata); 19912 return ret; 19913} 19914NK_LIB void 19915nk_draw_button_image(struct nk_command_buffer *out, 19916 const struct nk_rect *bounds, const struct nk_rect *content, 19917 nk_flags state, const struct nk_style_button *style, const struct nk_image *img) 19918{ 19919 nk_draw_button(out, bounds, state, style); 19920 nk_draw_image(out, *content, img, nk_white); 19921} 19922NK_LIB int 19923nk_do_button_image(nk_flags *state, 19924 struct nk_command_buffer *out, struct nk_rect bounds, 19925 struct nk_image img, enum nk_button_behavior b, 19926 const struct nk_style_button *style, const struct nk_input *in) 19927{ 19928 int ret; 19929 struct nk_rect content; 19930 19931 NK_ASSERT(state); 19932 NK_ASSERT(style); 19933 NK_ASSERT(out); 19934 if (!out || !style || !state) 19935 return nk_false; 19936 19937 ret = nk_do_button(state, out, bounds, style, in, b, &content); 19938 content.x += style->image_padding.x; 19939 content.y += style->image_padding.y; 19940 content.w -= 2 * style->image_padding.x; 19941 content.h -= 2 * style->image_padding.y; 19942 19943 if (style->draw_begin) style->draw_begin(out, style->userdata); 19944 nk_draw_button_image(out, &bounds, &content, *state, style, &img); 19945 if (style->draw_end) style->draw_end(out, style->userdata); 19946 return ret; 19947} 19948NK_LIB void 19949nk_draw_button_text_symbol(struct nk_command_buffer *out, 19950 const struct nk_rect *bounds, const struct nk_rect *label, 19951 const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, 19952 const char *str, int len, enum nk_symbol_type type, 19953 const struct nk_user_font *font) 19954{ 19955 struct nk_color sym; 19956 struct nk_text text; 19957 const struct nk_style_item *background; 19958 19959 /* select correct background colors/images */ 19960 background = nk_draw_button(out, bounds, state, style); 19961 if (background->type == NK_STYLE_ITEM_COLOR) 19962 text.background = background->data.color; 19963 else text.background = style->text_background; 19964 19965 /* select correct text colors */ 19966 if (state & NK_WIDGET_STATE_HOVER) { 19967 sym = style->text_hover; 19968 text.text = style->text_hover; 19969 } else if (state & NK_WIDGET_STATE_ACTIVED) { 19970 sym = style->text_active; 19971 text.text = style->text_active; 19972 } else { 19973 sym = style->text_normal; 19974 text.text = style->text_normal; 19975 } 19976 19977 text.padding = nk_vec2(0,0); 19978 nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); 19979 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 19980} 19981NK_LIB int 19982nk_do_button_text_symbol(nk_flags *state, 19983 struct nk_command_buffer *out, struct nk_rect bounds, 19984 enum nk_symbol_type symbol, const char *str, int len, nk_flags align, 19985 enum nk_button_behavior behavior, const struct nk_style_button *style, 19986 const struct nk_user_font *font, const struct nk_input *in) 19987{ 19988 int ret; 19989 struct nk_rect tri = {0,0,0,0}; 19990 struct nk_rect content; 19991 19992 NK_ASSERT(style); 19993 NK_ASSERT(out); 19994 NK_ASSERT(font); 19995 if (!out || !style || !font) 19996 return nk_false; 19997 19998 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 19999 tri.y = content.y + (content.h/2) - font->height/2; 20000 tri.w = font->height; tri.h = font->height; 20001 if (align & NK_TEXT_ALIGN_LEFT) { 20002 tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); 20003 tri.x = NK_MAX(tri.x, 0); 20004 } else tri.x = content.x + 2 * style->padding.x; 20005 20006 /* draw button */ 20007 if (style->draw_begin) style->draw_begin(out, style->userdata); 20008 nk_draw_button_text_symbol(out, &bounds, &content, &tri, 20009 *state, style, str, len, symbol, font); 20010 if (style->draw_end) style->draw_end(out, style->userdata); 20011 return ret; 20012} 20013NK_LIB void 20014nk_draw_button_text_image(struct nk_command_buffer *out, 20015 const struct nk_rect *bounds, const struct nk_rect *label, 20016 const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, 20017 const char *str, int len, const struct nk_user_font *font, 20018 const struct nk_image *img) 20019{ 20020 struct nk_text text; 20021 const struct nk_style_item *background; 20022 background = nk_draw_button(out, bounds, state, style); 20023 20024 /* select correct colors */ 20025 if (background->type == NK_STYLE_ITEM_COLOR) 20026 text.background = background->data.color; 20027 else text.background = style->text_background; 20028 if (state & NK_WIDGET_STATE_HOVER) 20029 text.text = style->text_hover; 20030 else if (state & NK_WIDGET_STATE_ACTIVED) 20031 text.text = style->text_active; 20032 else text.text = style->text_normal; 20033 20034 text.padding = nk_vec2(0,0); 20035 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 20036 nk_draw_image(out, *image, img, nk_white); 20037} 20038NK_LIB int 20039nk_do_button_text_image(nk_flags *state, 20040 struct nk_command_buffer *out, struct nk_rect bounds, 20041 struct nk_image img, const char* str, int len, nk_flags align, 20042 enum nk_button_behavior behavior, const struct nk_style_button *style, 20043 const struct nk_user_font *font, const struct nk_input *in) 20044{ 20045 int ret; 20046 struct nk_rect icon; 20047 struct nk_rect content; 20048 20049 NK_ASSERT(style); 20050 NK_ASSERT(state); 20051 NK_ASSERT(font); 20052 NK_ASSERT(out); 20053 if (!out || !font || !style || !str) 20054 return nk_false; 20055 20056 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 20057 icon.y = bounds.y + style->padding.y; 20058 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20059 if (align & NK_TEXT_ALIGN_LEFT) { 20060 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20061 icon.x = NK_MAX(icon.x, 0); 20062 } else icon.x = bounds.x + 2 * style->padding.x; 20063 20064 icon.x += style->image_padding.x; 20065 icon.y += style->image_padding.y; 20066 icon.w -= 2 * style->image_padding.x; 20067 icon.h -= 2 * style->image_padding.y; 20068 20069 if (style->draw_begin) style->draw_begin(out, style->userdata); 20070 nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img); 20071 if (style->draw_end) style->draw_end(out, style->userdata); 20072 return ret; 20073} 20074NK_API void 20075nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 20076{ 20077 NK_ASSERT(ctx); 20078 if (!ctx) return; 20079 ctx->button_behavior = behavior; 20080} 20081NK_API int 20082nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 20083{ 20084 struct nk_config_stack_button_behavior *button_stack; 20085 struct nk_config_stack_button_behavior_element *element; 20086 20087 NK_ASSERT(ctx); 20088 if (!ctx) return 0; 20089 20090 button_stack = &ctx->stacks.button_behaviors; 20091 NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements)); 20092 if (button_stack->head >= (int)NK_LEN(button_stack->elements)) 20093 return 0; 20094 20095 element = &button_stack->elements[button_stack->head++]; 20096 element->address = &ctx->button_behavior; 20097 element->old_value = ctx->button_behavior; 20098 ctx->button_behavior = behavior; 20099 return 1; 20100} 20101NK_API int 20102nk_button_pop_behavior(struct nk_context *ctx) 20103{ 20104 struct nk_config_stack_button_behavior *button_stack; 20105 struct nk_config_stack_button_behavior_element *element; 20106 20107 NK_ASSERT(ctx); 20108 if (!ctx) return 0; 20109 20110 button_stack = &ctx->stacks.button_behaviors; 20111 NK_ASSERT(button_stack->head > 0); 20112 if (button_stack->head < 1) 20113 return 0; 20114 20115 element = &button_stack->elements[--button_stack->head]; 20116 *element->address = element->old_value; 20117 return 1; 20118} 20119NK_API int 20120nk_button_text_styled(struct nk_context *ctx, 20121 const struct nk_style_button *style, const char *title, int len) 20122{ 20123 struct nk_window *win; 20124 struct nk_panel *layout; 20125 const struct nk_input *in; 20126 20127 struct nk_rect bounds; 20128 enum nk_widget_layout_states state; 20129 20130 NK_ASSERT(ctx); 20131 NK_ASSERT(style); 20132 NK_ASSERT(ctx->current); 20133 NK_ASSERT(ctx->current->layout); 20134 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0; 20135 20136 win = ctx->current; 20137 layout = win->layout; 20138 state = nk_widget(&bounds, ctx); 20139 20140 if (!state) return 0; 20141 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20142 return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 20143 title, len, style->text_alignment, ctx->button_behavior, 20144 style, in, ctx->style.font); 20145} 20146NK_API int 20147nk_button_text(struct nk_context *ctx, const char *title, int len) 20148{ 20149 NK_ASSERT(ctx); 20150 if (!ctx) return 0; 20151 return nk_button_text_styled(ctx, &ctx->style.button, title, len); 20152} 20153NK_API int nk_button_label_styled(struct nk_context *ctx, 20154 const struct nk_style_button *style, const char *title) 20155{ 20156 return nk_button_text_styled(ctx, style, title, nk_strlen(title)); 20157} 20158NK_API int nk_button_label(struct nk_context *ctx, const char *title) 20159{ 20160 return nk_button_text(ctx, title, nk_strlen(title)); 20161} 20162NK_API int 20163nk_button_color(struct nk_context *ctx, struct nk_color color) 20164{ 20165 struct nk_window *win; 20166 struct nk_panel *layout; 20167 const struct nk_input *in; 20168 struct nk_style_button button; 20169 20170 int ret = 0; 20171 struct nk_rect bounds; 20172 struct nk_rect content; 20173 enum nk_widget_layout_states state; 20174 20175 NK_ASSERT(ctx); 20176 NK_ASSERT(ctx->current); 20177 NK_ASSERT(ctx->current->layout); 20178 if (!ctx || !ctx->current || !ctx->current->layout) 20179 return 0; 20180 20181 win = ctx->current; 20182 layout = win->layout; 20183 20184 state = nk_widget(&bounds, ctx); 20185 if (!state) return 0; 20186 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20187 20188 button = ctx->style.button; 20189 button.normal = nk_style_item_color(color); 20190 button.hover = nk_style_item_color(color); 20191 button.active = nk_style_item_color(color); 20192 ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds, 20193 &button, in, ctx->button_behavior, &content); 20194 nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); 20195 return ret; 20196} 20197NK_API int 20198nk_button_symbol_styled(struct nk_context *ctx, 20199 const struct nk_style_button *style, enum nk_symbol_type symbol) 20200{ 20201 struct nk_window *win; 20202 struct nk_panel *layout; 20203 const struct nk_input *in; 20204 20205 struct nk_rect bounds; 20206 enum nk_widget_layout_states state; 20207 20208 NK_ASSERT(ctx); 20209 NK_ASSERT(ctx->current); 20210 NK_ASSERT(ctx->current->layout); 20211 if (!ctx || !ctx->current || !ctx->current->layout) 20212 return 0; 20213 20214 win = ctx->current; 20215 layout = win->layout; 20216 state = nk_widget(&bounds, ctx); 20217 if (!state) return 0; 20218 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20219 return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20220 symbol, ctx->button_behavior, style, in, ctx->style.font); 20221} 20222NK_API int 20223nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol) 20224{ 20225 NK_ASSERT(ctx); 20226 if (!ctx) return 0; 20227 return nk_button_symbol_styled(ctx, &ctx->style.button, symbol); 20228} 20229NK_API int 20230nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style, 20231 struct nk_image img) 20232{ 20233 struct nk_window *win; 20234 struct nk_panel *layout; 20235 const struct nk_input *in; 20236 20237 struct nk_rect bounds; 20238 enum nk_widget_layout_states state; 20239 20240 NK_ASSERT(ctx); 20241 NK_ASSERT(ctx->current); 20242 NK_ASSERT(ctx->current->layout); 20243 if (!ctx || !ctx->current || !ctx->current->layout) 20244 return 0; 20245 20246 win = ctx->current; 20247 layout = win->layout; 20248 20249 state = nk_widget(&bounds, ctx); 20250 if (!state) return 0; 20251 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20252 return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, 20253 img, ctx->button_behavior, style, in); 20254} 20255NK_API int 20256nk_button_image(struct nk_context *ctx, struct nk_image img) 20257{ 20258 NK_ASSERT(ctx); 20259 if (!ctx) return 0; 20260 return nk_button_image_styled(ctx, &ctx->style.button, img); 20261} 20262NK_API int 20263nk_button_symbol_text_styled(struct nk_context *ctx, 20264 const struct nk_style_button *style, enum nk_symbol_type symbol, 20265 const char *text, int len, nk_flags align) 20266{ 20267 struct nk_window *win; 20268 struct nk_panel *layout; 20269 const struct nk_input *in; 20270 20271 struct nk_rect bounds; 20272 enum nk_widget_layout_states state; 20273 20274 NK_ASSERT(ctx); 20275 NK_ASSERT(ctx->current); 20276 NK_ASSERT(ctx->current->layout); 20277 if (!ctx || !ctx->current || !ctx->current->layout) 20278 return 0; 20279 20280 win = ctx->current; 20281 layout = win->layout; 20282 20283 state = nk_widget(&bounds, ctx); 20284 if (!state) return 0; 20285 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20286 return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20287 symbol, text, len, align, ctx->button_behavior, 20288 style, ctx->style.font, in); 20289} 20290NK_API int 20291nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 20292 const char* text, int len, nk_flags align) 20293{ 20294 NK_ASSERT(ctx); 20295 if (!ctx) return 0; 20296 return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align); 20297} 20298NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 20299 const char *label, nk_flags align) 20300{ 20301 return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align); 20302} 20303NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, 20304 const struct nk_style_button *style, enum nk_symbol_type symbol, 20305 const char *title, nk_flags align) 20306{ 20307 return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align); 20308} 20309NK_API int 20310nk_button_image_text_styled(struct nk_context *ctx, 20311 const struct nk_style_button *style, struct nk_image img, const char *text, 20312 int len, nk_flags align) 20313{ 20314 struct nk_window *win; 20315 struct nk_panel *layout; 20316 const struct nk_input *in; 20317 20318 struct nk_rect bounds; 20319 enum nk_widget_layout_states state; 20320 20321 NK_ASSERT(ctx); 20322 NK_ASSERT(ctx->current); 20323 NK_ASSERT(ctx->current->layout); 20324 if (!ctx || !ctx->current || !ctx->current->layout) 20325 return 0; 20326 20327 win = ctx->current; 20328 layout = win->layout; 20329 20330 state = nk_widget(&bounds, ctx); 20331 if (!state) return 0; 20332 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20333 return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 20334 bounds, img, text, len, align, ctx->button_behavior, 20335 style, ctx->style.font, in); 20336} 20337NK_API int 20338nk_button_image_text(struct nk_context *ctx, struct nk_image img, 20339 const char *text, int len, nk_flags align) 20340{ 20341 return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align); 20342} 20343NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img, 20344 const char *label, nk_flags align) 20345{ 20346 return nk_button_image_text(ctx, img, label, nk_strlen(label), align); 20347} 20348NK_API int nk_button_image_label_styled(struct nk_context *ctx, 20349 const struct nk_style_button *style, struct nk_image img, 20350 const char *label, nk_flags text_alignment) 20351{ 20352 return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment); 20353} 20354 20355 20356 20357 20358 20359/* =============================================================== 20360 * 20361 * TOGGLE 20362 * 20363 * ===============================================================*/ 20364NK_LIB int 20365nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, 20366 nk_flags *state, int active) 20367{ 20368 nk_widget_state_reset(state); 20369 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) { 20370 *state = NK_WIDGET_STATE_ACTIVE; 20371 active = !active; 20372 } 20373 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select)) 20374 *state |= NK_WIDGET_STATE_ENTERED; 20375 else if (nk_input_is_mouse_prev_hovering_rect(in, select)) 20376 *state |= NK_WIDGET_STATE_LEFT; 20377 return active; 20378} 20379NK_LIB void 20380nk_draw_checkbox(struct nk_command_buffer *out, 20381 nk_flags state, const struct nk_style_toggle *style, int active, 20382 const struct nk_rect *label, const struct nk_rect *selector, 20383 const struct nk_rect *cursors, const char *string, int len, 20384 const struct nk_user_font *font) 20385{ 20386 const struct nk_style_item *background; 20387 const struct nk_style_item *cursor; 20388 struct nk_text text; 20389 20390 /* select correct colors/images */ 20391 if (state & NK_WIDGET_STATE_HOVER) { 20392 background = &style->hover; 20393 cursor = &style->cursor_hover; 20394 text.text = style->text_hover; 20395 } else if (state & NK_WIDGET_STATE_ACTIVED) { 20396 background = &style->hover; 20397 cursor = &style->cursor_hover; 20398 text.text = style->text_active; 20399 } else { 20400 background = &style->normal; 20401 cursor = &style->cursor_normal; 20402 text.text = style->text_normal; 20403 } 20404 20405 /* draw background and cursor */ 20406 if (background->type == NK_STYLE_ITEM_COLOR) { 20407 nk_fill_rect(out, *selector, 0, style->border_color); 20408 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color); 20409 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 20410 if (active) { 20411 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20412 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 20413 else nk_fill_rect(out, *cursors, 0, cursor->data.color); 20414 } 20415 20416 text.padding.x = 0; 20417 text.padding.y = 0; 20418 text.background = style->text_background; 20419 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 20420} 20421NK_LIB void 20422nk_draw_option(struct nk_command_buffer *out, 20423 nk_flags state, const struct nk_style_toggle *style, int active, 20424 const struct nk_rect *label, const struct nk_rect *selector, 20425 const struct nk_rect *cursors, const char *string, int len, 20426 const struct nk_user_font *font) 20427{ 20428 const struct nk_style_item *background; 20429 const struct nk_style_item *cursor; 20430 struct nk_text text; 20431 20432 /* select correct colors/images */ 20433 if (state & NK_WIDGET_STATE_HOVER) { 20434 background = &style->hover; 20435 cursor = &style->cursor_hover; 20436 text.text = style->text_hover; 20437 } else if (state & NK_WIDGET_STATE_ACTIVED) { 20438 background = &style->hover; 20439 cursor = &style->cursor_hover; 20440 text.text = style->text_active; 20441 } else { 20442 background = &style->normal; 20443 cursor = &style->cursor_normal; 20444 text.text = style->text_normal; 20445 } 20446 20447 /* draw background and cursor */ 20448 if (background->type == NK_STYLE_ITEM_COLOR) { 20449 nk_fill_circle(out, *selector, style->border_color); 20450 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color); 20451 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 20452 if (active) { 20453 if (cursor->type == NK_STYLE_ITEM_IMAGE) 20454 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 20455 else nk_fill_circle(out, *cursors, cursor->data.color); 20456 } 20457 20458 text.padding.x = 0; 20459 text.padding.y = 0; 20460 text.background = style->text_background; 20461 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 20462} 20463NK_LIB int 20464nk_do_toggle(nk_flags *state, 20465 struct nk_command_buffer *out, struct nk_rect r, 20466 int *active, const char *str, int len, enum nk_toggle_type type, 20467 const struct nk_style_toggle *style, const struct nk_input *in, 20468 const struct nk_user_font *font) 20469{ 20470 int was_active; 20471 struct nk_rect bounds; 20472 struct nk_rect select; 20473 struct nk_rect cursor; 20474 struct nk_rect label; 20475 20476 NK_ASSERT(style); 20477 NK_ASSERT(out); 20478 NK_ASSERT(font); 20479 if (!out || !style || !font || !active) 20480 return 0; 20481 20482 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x); 20483 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y); 20484 20485 /* add additional touch padding for touch screen devices */ 20486 bounds.x = r.x - style->touch_padding.x; 20487 bounds.y = r.y - style->touch_padding.y; 20488 bounds.w = r.w + 2 * style->touch_padding.x; 20489 bounds.h = r.h + 2 * style->touch_padding.y; 20490 20491 /* calculate the selector space */ 20492 select.w = font->height; 20493 select.h = select.w; 20494 select.y = r.y + r.h/2.0f - select.h/2.0f; 20495 select.x = r.x; 20496 20497 /* calculate the bounds of the cursor inside the selector */ 20498 cursor.x = select.x + style->padding.x + style->border; 20499 cursor.y = select.y + style->padding.y + style->border; 20500 cursor.w = select.w - (2 * style->padding.x + 2 * style->border); 20501 cursor.h = select.h - (2 * style->padding.y + 2 * style->border); 20502 20503 /* label behind the selector */ 20504 label.x = select.x + select.w + style->spacing; 20505 label.y = select.y; 20506 label.w = NK_MAX(r.x + r.w, label.x) - label.x; 20507 label.h = select.w; 20508 20509 /* update selector */ 20510 was_active = *active; 20511 *active = nk_toggle_behavior(in, bounds, state, *active); 20512 20513 /* draw selector */ 20514 if (style->draw_begin) 20515 style->draw_begin(out, style->userdata); 20516 if (type == NK_TOGGLE_CHECK) { 20517 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font); 20518 } else { 20519 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font); 20520 } 20521 if (style->draw_end) 20522 style->draw_end(out, style->userdata); 20523 return (was_active != *active); 20524} 20525/*---------------------------------------------------------------- 20526 * 20527 * CHECKBOX 20528 * 20529 * --------------------------------------------------------------*/ 20530NK_API int 20531nk_check_text(struct nk_context *ctx, const char *text, int len, int active) 20532{ 20533 struct nk_window *win; 20534 struct nk_panel *layout; 20535 const struct nk_input *in; 20536 const struct nk_style *style; 20537 20538 struct nk_rect bounds; 20539 enum nk_widget_layout_states state; 20540 20541 NK_ASSERT(ctx); 20542 NK_ASSERT(ctx->current); 20543 NK_ASSERT(ctx->current->layout); 20544 if (!ctx || !ctx->current || !ctx->current->layout) 20545 return active; 20546 20547 win = ctx->current; 20548 style = &ctx->style; 20549 layout = win->layout; 20550 20551 state = nk_widget(&bounds, ctx); 20552 if (!state) return active; 20553 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20554 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, 20555 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font); 20556 return active; 20557} 20558NK_API unsigned int 20559nk_check_flags_text(struct nk_context *ctx, const char *text, int len, 20560 unsigned int flags, unsigned int value) 20561{ 20562 int old_active; 20563 NK_ASSERT(ctx); 20564 NK_ASSERT(text); 20565 if (!ctx || !text) return flags; 20566 old_active = (int)((flags & value) & value); 20567 if (nk_check_text(ctx, text, len, old_active)) 20568 flags |= value; 20569 else flags &= ~value; 20570 return flags; 20571} 20572NK_API int 20573nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active) 20574{ 20575 int old_val; 20576 NK_ASSERT(ctx); 20577 NK_ASSERT(text); 20578 NK_ASSERT(active); 20579 if (!ctx || !text || !active) return 0; 20580 old_val = *active; 20581 *active = nk_check_text(ctx, text, len, *active); 20582 return old_val != *active; 20583} 20584NK_API int 20585nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len, 20586 unsigned int *flags, unsigned int value) 20587{ 20588 int active; 20589 NK_ASSERT(ctx); 20590 NK_ASSERT(text); 20591 NK_ASSERT(flags); 20592 if (!ctx || !text || !flags) return 0; 20593 20594 active = (int)((*flags & value) & value); 20595 if (nk_checkbox_text(ctx, text, len, &active)) { 20596 if (active) *flags |= value; 20597 else *flags &= ~value; 20598 return 1; 20599 } 20600 return 0; 20601} 20602NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active) 20603{ 20604 return nk_check_text(ctx, label, nk_strlen(label), active); 20605} 20606NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label, 20607 unsigned int flags, unsigned int value) 20608{ 20609 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value); 20610} 20611NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active) 20612{ 20613 return nk_checkbox_text(ctx, label, nk_strlen(label), active); 20614} 20615NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label, 20616 unsigned int *flags, unsigned int value) 20617{ 20618 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value); 20619} 20620/*---------------------------------------------------------------- 20621 * 20622 * OPTION 20623 * 20624 * --------------------------------------------------------------*/ 20625NK_API int 20626nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active) 20627{ 20628 struct nk_window *win; 20629 struct nk_panel *layout; 20630 const struct nk_input *in; 20631 const struct nk_style *style; 20632 20633 struct nk_rect bounds; 20634 enum nk_widget_layout_states state; 20635 20636 NK_ASSERT(ctx); 20637 NK_ASSERT(ctx->current); 20638 NK_ASSERT(ctx->current->layout); 20639 if (!ctx || !ctx->current || !ctx->current->layout) 20640 return is_active; 20641 20642 win = ctx->current; 20643 style = &ctx->style; 20644 layout = win->layout; 20645 20646 state = nk_widget(&bounds, ctx); 20647 if (!state) return (int)state; 20648 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20649 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, 20650 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font); 20651 return is_active; 20652} 20653NK_API int 20654nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active) 20655{ 20656 int old_value; 20657 NK_ASSERT(ctx); 20658 NK_ASSERT(text); 20659 NK_ASSERT(active); 20660 if (!ctx || !text || !active) return 0; 20661 old_value = *active; 20662 *active = nk_option_text(ctx, text, len, old_value); 20663 return old_value != *active; 20664} 20665NK_API int 20666nk_option_label(struct nk_context *ctx, const char *label, int active) 20667{ 20668 return nk_option_text(ctx, label, nk_strlen(label), active); 20669} 20670NK_API int 20671nk_radio_label(struct nk_context *ctx, const char *label, int *active) 20672{ 20673 return nk_radio_text(ctx, label, nk_strlen(label), active); 20674} 20675 20676 20677 20678 20679 20680/* =============================================================== 20681 * 20682 * SELECTABLE 20683 * 20684 * ===============================================================*/ 20685NK_LIB void 20686nk_draw_selectable(struct nk_command_buffer *out, 20687 nk_flags state, const struct nk_style_selectable *style, int active, 20688 const struct nk_rect *bounds, 20689 const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, 20690 const char *string, int len, nk_flags align, const struct nk_user_font *font) 20691{ 20692 const struct nk_style_item *background; 20693 struct nk_text text; 20694 text.padding = style->padding; 20695 20696 /* select correct colors/images */ 20697 if (!active) { 20698 if (state & NK_WIDGET_STATE_ACTIVED) { 20699 background = &style->pressed; 20700 text.text = style->text_pressed; 20701 } else if (state & NK_WIDGET_STATE_HOVER) { 20702 background = &style->hover; 20703 text.text = style->text_hover; 20704 } else { 20705 background = &style->normal; 20706 text.text = style->text_normal; 20707 } 20708 } else { 20709 if (state & NK_WIDGET_STATE_ACTIVED) { 20710 background = &style->pressed_active; 20711 text.text = style->text_pressed_active; 20712 } else if (state & NK_WIDGET_STATE_HOVER) { 20713 background = &style->hover_active; 20714 text.text = style->text_hover_active; 20715 } else { 20716 background = &style->normal_active; 20717 text.text = style->text_normal_active; 20718 } 20719 } 20720 /* draw selectable background and text */ 20721 if (background->type == NK_STYLE_ITEM_IMAGE) { 20722 nk_draw_image(out, *bounds, &background->data.image, nk_white); 20723 text.background = nk_rgba(0,0,0,0); 20724 } else { 20725 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 20726 text.background = background->data.color; 20727 } 20728 if (icon) { 20729 if (img) nk_draw_image(out, *icon, img, nk_white); 20730 else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font); 20731 } 20732 nk_widget_text(out, *bounds, string, len, &text, align, font); 20733} 20734NK_LIB int 20735nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, 20736 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20737 const struct nk_style_selectable *style, const struct nk_input *in, 20738 const struct nk_user_font *font) 20739{ 20740 int old_value; 20741 struct nk_rect touch; 20742 20743 NK_ASSERT(state); 20744 NK_ASSERT(out); 20745 NK_ASSERT(str); 20746 NK_ASSERT(len); 20747 NK_ASSERT(value); 20748 NK_ASSERT(style); 20749 NK_ASSERT(font); 20750 20751 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20752 old_value = *value; 20753 20754 /* remove padding */ 20755 touch.x = bounds.x - style->touch_padding.x; 20756 touch.y = bounds.y - style->touch_padding.y; 20757 touch.w = bounds.w + style->touch_padding.x * 2; 20758 touch.h = bounds.h + style->touch_padding.y * 2; 20759 20760 /* update button */ 20761 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20762 *value = !(*value); 20763 20764 /* draw selectable */ 20765 if (style->draw_begin) style->draw_begin(out, style->userdata); 20766 nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font); 20767 if (style->draw_end) style->draw_end(out, style->userdata); 20768 return old_value != *value; 20769} 20770NK_LIB int 20771nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, 20772 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20773 const struct nk_image *img, const struct nk_style_selectable *style, 20774 const struct nk_input *in, const struct nk_user_font *font) 20775{ 20776 int old_value; 20777 struct nk_rect touch; 20778 struct nk_rect icon; 20779 20780 NK_ASSERT(state); 20781 NK_ASSERT(out); 20782 NK_ASSERT(str); 20783 NK_ASSERT(len); 20784 NK_ASSERT(value); 20785 NK_ASSERT(style); 20786 NK_ASSERT(font); 20787 20788 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20789 old_value = *value; 20790 20791 /* toggle behavior */ 20792 touch.x = bounds.x - style->touch_padding.x; 20793 touch.y = bounds.y - style->touch_padding.y; 20794 touch.w = bounds.w + style->touch_padding.x * 2; 20795 touch.h = bounds.h + style->touch_padding.y * 2; 20796 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20797 *value = !(*value); 20798 20799 icon.y = bounds.y + style->padding.y; 20800 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20801 if (align & NK_TEXT_ALIGN_LEFT) { 20802 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20803 icon.x = NK_MAX(icon.x, 0); 20804 } else icon.x = bounds.x + 2 * style->padding.x; 20805 20806 icon.x += style->image_padding.x; 20807 icon.y += style->image_padding.y; 20808 icon.w -= 2 * style->image_padding.x; 20809 icon.h -= 2 * style->image_padding.y; 20810 20811 /* draw selectable */ 20812 if (style->draw_begin) style->draw_begin(out, style->userdata); 20813 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font); 20814 if (style->draw_end) style->draw_end(out, style->userdata); 20815 return old_value != *value; 20816} 20817NK_LIB int 20818nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out, 20819 struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, 20820 enum nk_symbol_type sym, const struct nk_style_selectable *style, 20821 const struct nk_input *in, const struct nk_user_font *font) 20822{ 20823 int old_value; 20824 struct nk_rect touch; 20825 struct nk_rect icon; 20826 20827 NK_ASSERT(state); 20828 NK_ASSERT(out); 20829 NK_ASSERT(str); 20830 NK_ASSERT(len); 20831 NK_ASSERT(value); 20832 NK_ASSERT(style); 20833 NK_ASSERT(font); 20834 20835 if (!state || !out || !str || !len || !value || !style || !font) return 0; 20836 old_value = *value; 20837 20838 /* toggle behavior */ 20839 touch.x = bounds.x - style->touch_padding.x; 20840 touch.y = bounds.y - style->touch_padding.y; 20841 touch.w = bounds.w + style->touch_padding.x * 2; 20842 touch.h = bounds.h + style->touch_padding.y * 2; 20843 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 20844 *value = !(*value); 20845 20846 icon.y = bounds.y + style->padding.y; 20847 icon.w = icon.h = bounds.h - 2 * style->padding.y; 20848 if (align & NK_TEXT_ALIGN_LEFT) { 20849 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 20850 icon.x = NK_MAX(icon.x, 0); 20851 } else icon.x = bounds.x + 2 * style->padding.x; 20852 20853 icon.x += style->image_padding.x; 20854 icon.y += style->image_padding.y; 20855 icon.w -= 2 * style->image_padding.x; 20856 icon.h -= 2 * style->image_padding.y; 20857 20858 /* draw selectable */ 20859 if (style->draw_begin) style->draw_begin(out, style->userdata); 20860 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font); 20861 if (style->draw_end) style->draw_end(out, style->userdata); 20862 return old_value != *value; 20863} 20864 20865NK_API int 20866nk_selectable_text(struct nk_context *ctx, const char *str, int len, 20867 nk_flags align, int *value) 20868{ 20869 struct nk_window *win; 20870 struct nk_panel *layout; 20871 const struct nk_input *in; 20872 const struct nk_style *style; 20873 20874 enum nk_widget_layout_states state; 20875 struct nk_rect bounds; 20876 20877 NK_ASSERT(ctx); 20878 NK_ASSERT(value); 20879 NK_ASSERT(ctx->current); 20880 NK_ASSERT(ctx->current->layout); 20881 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20882 return 0; 20883 20884 win = ctx->current; 20885 layout = win->layout; 20886 style = &ctx->style; 20887 20888 state = nk_widget(&bounds, ctx); 20889 if (!state) return 0; 20890 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20891 return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, 20892 str, len, align, value, &style->selectable, in, style->font); 20893} 20894NK_API int 20895nk_selectable_image_text(struct nk_context *ctx, struct nk_image img, 20896 const char *str, int len, nk_flags align, int *value) 20897{ 20898 struct nk_window *win; 20899 struct nk_panel *layout; 20900 const struct nk_input *in; 20901 const struct nk_style *style; 20902 20903 enum nk_widget_layout_states state; 20904 struct nk_rect bounds; 20905 20906 NK_ASSERT(ctx); 20907 NK_ASSERT(value); 20908 NK_ASSERT(ctx->current); 20909 NK_ASSERT(ctx->current->layout); 20910 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20911 return 0; 20912 20913 win = ctx->current; 20914 layout = win->layout; 20915 style = &ctx->style; 20916 20917 state = nk_widget(&bounds, ctx); 20918 if (!state) return 0; 20919 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20920 return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds, 20921 str, len, align, value, &img, &style->selectable, in, style->font); 20922} 20923NK_API int 20924nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 20925 const char *str, int len, nk_flags align, int *value) 20926{ 20927 struct nk_window *win; 20928 struct nk_panel *layout; 20929 const struct nk_input *in; 20930 const struct nk_style *style; 20931 20932 enum nk_widget_layout_states state; 20933 struct nk_rect bounds; 20934 20935 NK_ASSERT(ctx); 20936 NK_ASSERT(value); 20937 NK_ASSERT(ctx->current); 20938 NK_ASSERT(ctx->current->layout); 20939 if (!ctx || !ctx->current || !ctx->current->layout || !value) 20940 return 0; 20941 20942 win = ctx->current; 20943 layout = win->layout; 20944 style = &ctx->style; 20945 20946 state = nk_widget(&bounds, ctx); 20947 if (!state) return 0; 20948 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 20949 return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds, 20950 str, len, align, value, sym, &style->selectable, in, style->font); 20951} 20952NK_API int 20953nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 20954 const char *title, nk_flags align, int *value) 20955{ 20956 return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 20957} 20958NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len, 20959 nk_flags align, int value) 20960{ 20961 nk_selectable_text(ctx, str, len, align, &value);return value; 20962} 20963NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value) 20964{ 20965 return nk_selectable_text(ctx, str, nk_strlen(str), align, value); 20966} 20967NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img, 20968 const char *str, nk_flags align, int *value) 20969{ 20970 return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value); 20971} 20972NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value) 20973{ 20974 nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value; 20975} 20976NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img, 20977 const char *str, nk_flags align, int value) 20978{ 20979 nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value; 20980} 20981NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img, 20982 const char *str, int len, nk_flags align, int value) 20983{ 20984 nk_selectable_image_text(ctx, img, str, len, align, &value);return value; 20985} 20986NK_API int 20987nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 20988 const char *title, int title_len, nk_flags align, int value) 20989{ 20990 nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value; 20991} 20992NK_API int 20993nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 20994 const char *title, nk_flags align, int value) 20995{ 20996 return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 20997} 20998 20999 21000 21001 21002 21003/* =============================================================== 21004 * 21005 * SLIDER 21006 * 21007 * ===============================================================*/ 21008NK_LIB float 21009nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, 21010 struct nk_rect *visual_cursor, struct nk_input *in, 21011 struct nk_rect bounds, float slider_min, float slider_max, float slider_value, 21012 float slider_step, float slider_steps) 21013{ 21014 int left_mouse_down; 21015 int left_mouse_click_in_cursor; 21016 21017 /* check if visual cursor is being dragged */ 21018 nk_widget_state_reset(state); 21019 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 21020 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 21021 NK_BUTTON_LEFT, *visual_cursor, nk_true); 21022 21023 if (left_mouse_down && left_mouse_click_in_cursor) { 21024 float ratio = 0; 21025 const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f); 21026 const float pxstep = bounds.w / slider_steps; 21027 21028 /* only update value if the next slider step is reached */ 21029 *state = NK_WIDGET_STATE_ACTIVE; 21030 if (NK_ABS(d) >= pxstep) { 21031 const float steps = (float)((int)(NK_ABS(d) / pxstep)); 21032 slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); 21033 slider_value = NK_CLAMP(slider_min, slider_value, slider_max); 21034 ratio = (slider_value - slider_min)/slider_step; 21035 logical_cursor->x = bounds.x + (logical_cursor->w * ratio); 21036 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x; 21037 } 21038 } 21039 21040 /* slider widget state */ 21041 if (nk_input_is_mouse_hovering_rect(in, bounds)) 21042 *state = NK_WIDGET_STATE_HOVERED; 21043 if (*state & NK_WIDGET_STATE_HOVER && 21044 !nk_input_is_mouse_prev_hovering_rect(in, bounds)) 21045 *state |= NK_WIDGET_STATE_ENTERED; 21046 else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) 21047 *state |= NK_WIDGET_STATE_LEFT; 21048 return slider_value; 21049} 21050NK_LIB void 21051nk_draw_slider(struct nk_command_buffer *out, nk_flags state, 21052 const struct nk_style_slider *style, const struct nk_rect *bounds, 21053 const struct nk_rect *visual_cursor, float min, float value, float max) 21054{ 21055 struct nk_rect fill; 21056 struct nk_rect bar; 21057 const struct nk_style_item *background; 21058 21059 /* select correct slider images/colors */ 21060 struct nk_color bar_color; 21061 const struct nk_style_item *cursor; 21062 21063 NK_UNUSED(min); 21064 NK_UNUSED(max); 21065 NK_UNUSED(value); 21066 21067 if (state & NK_WIDGET_STATE_ACTIVED) { 21068 background = &style->active; 21069 bar_color = style->bar_active; 21070 cursor = &style->cursor_active; 21071 } else if (state & NK_WIDGET_STATE_HOVER) { 21072 background = &style->hover; 21073 bar_color = style->bar_hover; 21074 cursor = &style->cursor_hover; 21075 } else { 21076 background = &style->normal; 21077 bar_color = style->bar_normal; 21078 cursor = &style->cursor_normal; 21079 } 21080 /* calculate slider background bar */ 21081 bar.x = bounds->x; 21082 bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12; 21083 bar.w = bounds->w; 21084 bar.h = bounds->h/6; 21085 21086 /* filled background bar style */ 21087 fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x; 21088 fill.x = bar.x; 21089 fill.y = bar.y; 21090 fill.h = bar.h; 21091 21092 /* draw background */ 21093 if (background->type == NK_STYLE_ITEM_IMAGE) { 21094 nk_draw_image(out, *bounds, &background->data.image, nk_white); 21095 } else { 21096 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21097 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21098 } 21099 21100 /* draw slider bar */ 21101 nk_fill_rect(out, bar, style->rounding, bar_color); 21102 nk_fill_rect(out, fill, style->rounding, style->bar_filled); 21103 21104 /* draw cursor */ 21105 if (cursor->type == NK_STYLE_ITEM_IMAGE) 21106 nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white); 21107 else nk_fill_circle(out, *visual_cursor, cursor->data.color); 21108} 21109NK_LIB float 21110nk_do_slider(nk_flags *state, 21111 struct nk_command_buffer *out, struct nk_rect bounds, 21112 float min, float val, float max, float step, 21113 const struct nk_style_slider *style, struct nk_input *in, 21114 const struct nk_user_font *font) 21115{ 21116 float slider_range; 21117 float slider_min; 21118 float slider_max; 21119 float slider_value; 21120 float slider_steps; 21121 float cursor_offset; 21122 21123 struct nk_rect visual_cursor; 21124 struct nk_rect logical_cursor; 21125 21126 NK_ASSERT(style); 21127 NK_ASSERT(out); 21128 if (!out || !style) 21129 return 0; 21130 21131 /* remove padding from slider bounds */ 21132 bounds.x = bounds.x + style->padding.x; 21133 bounds.y = bounds.y + style->padding.y; 21134 bounds.h = NK_MAX(bounds.h, 2*style->padding.y); 21135 bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x); 21136 bounds.w -= 2 * style->padding.x; 21137 bounds.h -= 2 * style->padding.y; 21138 21139 /* optional buttons */ 21140 if (style->show_buttons) { 21141 nk_flags ws; 21142 struct nk_rect button; 21143 button.y = bounds.y; 21144 button.w = bounds.h; 21145 button.h = bounds.h; 21146 21147 /* decrement button */ 21148 button.x = bounds.x; 21149 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT, 21150 &style->dec_button, in, font)) 21151 val -= step; 21152 21153 /* increment button */ 21154 button.x = (bounds.x + bounds.w) - button.w; 21155 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT, 21156 &style->inc_button, in, font)) 21157 val += step; 21158 21159 bounds.x = bounds.x + button.w + style->spacing.x; 21160 bounds.w = bounds.w - (2*button.w + 2*style->spacing.x); 21161 } 21162 21163 /* remove one cursor size to support visual cursor */ 21164 bounds.x += style->cursor_size.x*0.5f; 21165 bounds.w -= style->cursor_size.x; 21166 21167 /* make sure the provided values are correct */ 21168 slider_max = NK_MAX(min, max); 21169 slider_min = NK_MIN(min, max); 21170 slider_value = NK_CLAMP(slider_min, val, slider_max); 21171 slider_range = slider_max - slider_min; 21172 slider_steps = slider_range / step; 21173 cursor_offset = (slider_value - slider_min) / step; 21174 21175 /* calculate cursor 21176 Basically you have two cursors. One for visual representation and interaction 21177 and one for updating the actual cursor value. */ 21178 logical_cursor.h = bounds.h; 21179 logical_cursor.w = bounds.w / slider_steps; 21180 logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset); 21181 logical_cursor.y = bounds.y; 21182 21183 visual_cursor.h = style->cursor_size.y; 21184 visual_cursor.w = style->cursor_size.x; 21185 visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f; 21186 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 21187 21188 slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor, 21189 in, bounds, slider_min, slider_max, slider_value, step, slider_steps); 21190 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 21191 21192 /* draw slider */ 21193 if (style->draw_begin) style->draw_begin(out, style->userdata); 21194 nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max); 21195 if (style->draw_end) style->draw_end(out, style->userdata); 21196 return slider_value; 21197} 21198NK_API int 21199nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value, 21200 float value_step) 21201{ 21202 struct nk_window *win; 21203 struct nk_panel *layout; 21204 struct nk_input *in; 21205 const struct nk_style *style; 21206 21207 int ret = 0; 21208 float old_value; 21209 struct nk_rect bounds; 21210 enum nk_widget_layout_states state; 21211 21212 NK_ASSERT(ctx); 21213 NK_ASSERT(ctx->current); 21214 NK_ASSERT(ctx->current->layout); 21215 NK_ASSERT(value); 21216 if (!ctx || !ctx->current || !ctx->current->layout || !value) 21217 return ret; 21218 21219 win = ctx->current; 21220 style = &ctx->style; 21221 layout = win->layout; 21222 21223 state = nk_widget(&bounds, ctx); 21224 if (!state) return ret; 21225 in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21226 21227 old_value = *value; 21228 *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, 21229 old_value, max_value, value_step, &style->slider, in, style->font); 21230 return (old_value > *value || old_value < *value); 21231} 21232NK_API float 21233nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step) 21234{ 21235 nk_slider_float(ctx, min, &val, max, step); return val; 21236} 21237NK_API int 21238nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step) 21239{ 21240 float value = (float)val; 21241 nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 21242 return (int)value; 21243} 21244NK_API int 21245nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) 21246{ 21247 int ret; 21248 float value = (float)*val; 21249 ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 21250 *val = (int)value; 21251 return ret; 21252} 21253 21254 21255 21256 21257 21258/* =============================================================== 21259 * 21260 * PROGRESS 21261 * 21262 * ===============================================================*/ 21263NK_LIB nk_size 21264nk_progress_behavior(nk_flags *state, struct nk_input *in, 21265 struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, int modifiable) 21266{ 21267 int left_mouse_down = 0; 21268 int left_mouse_click_in_cursor = 0; 21269 21270 nk_widget_state_reset(state); 21271 if (!in || !modifiable) return value; 21272 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 21273 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 21274 NK_BUTTON_LEFT, cursor, nk_true); 21275 if (nk_input_is_mouse_hovering_rect(in, r)) 21276 *state = NK_WIDGET_STATE_HOVERED; 21277 21278 if (in && left_mouse_down && left_mouse_click_in_cursor) { 21279 if (left_mouse_down && left_mouse_click_in_cursor) { 21280 float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w; 21281 value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max); 21282 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f; 21283 *state |= NK_WIDGET_STATE_ACTIVE; 21284 } 21285 } 21286 /* set progressbar widget state */ 21287 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r)) 21288 *state |= NK_WIDGET_STATE_ENTERED; 21289 else if (nk_input_is_mouse_prev_hovering_rect(in, r)) 21290 *state |= NK_WIDGET_STATE_LEFT; 21291 return value; 21292} 21293NK_LIB void 21294nk_draw_progress(struct nk_command_buffer *out, nk_flags state, 21295 const struct nk_style_progress *style, const struct nk_rect *bounds, 21296 const struct nk_rect *scursor, nk_size value, nk_size max) 21297{ 21298 const struct nk_style_item *background; 21299 const struct nk_style_item *cursor; 21300 21301 NK_UNUSED(max); 21302 NK_UNUSED(value); 21303 21304 /* select correct colors/images to draw */ 21305 if (state & NK_WIDGET_STATE_ACTIVED) { 21306 background = &style->active; 21307 cursor = &style->cursor_active; 21308 } else if (state & NK_WIDGET_STATE_HOVER){ 21309 background = &style->hover; 21310 cursor = &style->cursor_hover; 21311 } else { 21312 background = &style->normal; 21313 cursor = &style->cursor_normal; 21314 } 21315 21316 /* draw background */ 21317 if (background->type == NK_STYLE_ITEM_COLOR) { 21318 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21319 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21320 } else nk_draw_image(out, *bounds, &background->data.image, nk_white); 21321 21322 /* draw cursor */ 21323 if (cursor->type == NK_STYLE_ITEM_COLOR) { 21324 nk_fill_rect(out, *scursor, style->rounding, cursor->data.color); 21325 nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color); 21326 } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white); 21327} 21328NK_LIB nk_size 21329nk_do_progress(nk_flags *state, 21330 struct nk_command_buffer *out, struct nk_rect bounds, 21331 nk_size value, nk_size max, int modifiable, 21332 const struct nk_style_progress *style, struct nk_input *in) 21333{ 21334 float prog_scale; 21335 nk_size prog_value; 21336 struct nk_rect cursor; 21337 21338 NK_ASSERT(style); 21339 NK_ASSERT(out); 21340 if (!out || !style) return 0; 21341 21342 /* calculate progressbar cursor */ 21343 cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); 21344 cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border); 21345 cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border)); 21346 prog_scale = (float)value / (float)max; 21347 21348 /* update progressbar */ 21349 prog_value = NK_MIN(value, max); 21350 prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable); 21351 cursor.w = cursor.w * prog_scale; 21352 21353 /* draw progressbar */ 21354 if (style->draw_begin) style->draw_begin(out, style->userdata); 21355 nk_draw_progress(out, *state, style, &bounds, &cursor, value, max); 21356 if (style->draw_end) style->draw_end(out, style->userdata); 21357 return prog_value; 21358} 21359NK_API int 21360nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable) 21361{ 21362 struct nk_window *win; 21363 struct nk_panel *layout; 21364 const struct nk_style *style; 21365 struct nk_input *in; 21366 21367 struct nk_rect bounds; 21368 enum nk_widget_layout_states state; 21369 nk_size old_value; 21370 21371 NK_ASSERT(ctx); 21372 NK_ASSERT(cur); 21373 NK_ASSERT(ctx->current); 21374 NK_ASSERT(ctx->current->layout); 21375 if (!ctx || !ctx->current || !ctx->current->layout || !cur) 21376 return 0; 21377 21378 win = ctx->current; 21379 style = &ctx->style; 21380 layout = win->layout; 21381 state = nk_widget(&bounds, ctx); 21382 if (!state) return 0; 21383 21384 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21385 old_value = *cur; 21386 *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds, 21387 *cur, max, is_modifyable, &style->progress, in); 21388 return (*cur != old_value); 21389} 21390NK_API nk_size 21391nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable) 21392{ 21393 nk_progress(ctx, &cur, max, modifyable); 21394 return cur; 21395} 21396 21397 21398 21399 21400 21401/* =============================================================== 21402 * 21403 * SCROLLBAR 21404 * 21405 * ===============================================================*/ 21406NK_LIB float 21407nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, 21408 int has_scrolling, const struct nk_rect *scroll, 21409 const struct nk_rect *cursor, const struct nk_rect *empty0, 21410 const struct nk_rect *empty1, float scroll_offset, 21411 float target, float scroll_step, enum nk_orientation o) 21412{ 21413 nk_flags ws = 0; 21414 int left_mouse_down; 21415 int left_mouse_clicked; 21416 int left_mouse_click_in_cursor; 21417 float scroll_delta; 21418 21419 nk_widget_state_reset(state); 21420 if (!in) return scroll_offset; 21421 21422 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 21423 left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked; 21424 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 21425 NK_BUTTON_LEFT, *cursor, nk_true); 21426 if (nk_input_is_mouse_hovering_rect(in, *scroll)) 21427 *state = NK_WIDGET_STATE_HOVERED; 21428 21429 scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; 21430 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 21431 /* update cursor by mouse dragging */ 21432 float pixel, delta; 21433 *state = NK_WIDGET_STATE_ACTIVE; 21434 if (o == NK_VERTICAL) { 21435 float cursor_y; 21436 pixel = in->mouse.delta.y; 21437 delta = (pixel / scroll->h) * target; 21438 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); 21439 cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); 21440 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; 21441 } else { 21442 float cursor_x; 21443 pixel = in->mouse.delta.x; 21444 delta = (pixel / scroll->w) * target; 21445 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); 21446 cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); 21447 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; 21448 } 21449 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| 21450 nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { 21451 /* scroll page up by click on empty space or shortcut */ 21452 if (o == NK_VERTICAL) 21453 scroll_offset = NK_MAX(0, scroll_offset - scroll->h); 21454 else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); 21455 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || 21456 nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { 21457 /* scroll page down by click on empty space or shortcut */ 21458 if (o == NK_VERTICAL) 21459 scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); 21460 else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); 21461 } else if (has_scrolling) { 21462 if ((scroll_delta < 0 || (scroll_delta > 0))) { 21463 /* update cursor by mouse scrolling */ 21464 scroll_offset = scroll_offset + scroll_step * (-scroll_delta); 21465 if (o == NK_VERTICAL) 21466 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); 21467 else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); 21468 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { 21469 /* update cursor to the beginning */ 21470 if (o == NK_VERTICAL) scroll_offset = 0; 21471 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { 21472 /* update cursor to the end */ 21473 if (o == NK_VERTICAL) scroll_offset = target - scroll->h; 21474 } 21475 } 21476 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 21477 *state |= NK_WIDGET_STATE_ENTERED; 21478 else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 21479 *state |= NK_WIDGET_STATE_LEFT; 21480 return scroll_offset; 21481} 21482NK_LIB void 21483nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, 21484 const struct nk_style_scrollbar *style, const struct nk_rect *bounds, 21485 const struct nk_rect *scroll) 21486{ 21487 const struct nk_style_item *background; 21488 const struct nk_style_item *cursor; 21489 21490 /* select correct colors/images to draw */ 21491 if (state & NK_WIDGET_STATE_ACTIVED) { 21492 background = &style->active; 21493 cursor = &style->cursor_active; 21494 } else if (state & NK_WIDGET_STATE_HOVER) { 21495 background = &style->hover; 21496 cursor = &style->cursor_hover; 21497 } else { 21498 background = &style->normal; 21499 cursor = &style->cursor_normal; 21500 } 21501 21502 /* draw background */ 21503 if (background->type == NK_STYLE_ITEM_COLOR) { 21504 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 21505 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 21506 } else { 21507 nk_draw_image(out, *bounds, &background->data.image, nk_white); 21508 } 21509 21510 /* draw cursor */ 21511 if (cursor->type == NK_STYLE_ITEM_COLOR) { 21512 nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); 21513 nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); 21514 } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white); 21515} 21516NK_LIB float 21517nk_do_scrollbarv(nk_flags *state, 21518 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 21519 float offset, float target, float step, float button_pixel_inc, 21520 const struct nk_style_scrollbar *style, struct nk_input *in, 21521 const struct nk_user_font *font) 21522{ 21523 struct nk_rect empty_north; 21524 struct nk_rect empty_south; 21525 struct nk_rect cursor; 21526 21527 float scroll_step; 21528 float scroll_offset; 21529 float scroll_off; 21530 float scroll_ratio; 21531 21532 NK_ASSERT(out); 21533 NK_ASSERT(style); 21534 NK_ASSERT(state); 21535 if (!out || !style) return 0; 21536 21537 scroll.w = NK_MAX(scroll.w, 1); 21538 scroll.h = NK_MAX(scroll.h, 0); 21539 if (target <= scroll.h) return 0; 21540 21541 /* optional scrollbar buttons */ 21542 if (style->show_buttons) { 21543 nk_flags ws; 21544 float scroll_h; 21545 struct nk_rect button; 21546 21547 button.x = scroll.x; 21548 button.w = scroll.w; 21549 button.h = scroll.w; 21550 21551 scroll_h = NK_MAX(scroll.h - 2 * button.h,0); 21552 scroll_step = NK_MIN(step, button_pixel_inc); 21553 21554 /* decrement button */ 21555 button.y = scroll.y; 21556 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 21557 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 21558 offset = offset - scroll_step; 21559 21560 /* increment button */ 21561 button.y = scroll.y + scroll.h - button.h; 21562 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 21563 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 21564 offset = offset + scroll_step; 21565 21566 scroll.y = scroll.y + button.h; 21567 scroll.h = scroll_h; 21568 } 21569 21570 /* calculate scrollbar constants */ 21571 scroll_step = NK_MIN(step, scroll.h); 21572 scroll_offset = NK_CLAMP(0, offset, target - scroll.h); 21573 scroll_ratio = scroll.h / target; 21574 scroll_off = scroll_offset / target; 21575 21576 /* calculate scrollbar cursor bounds */ 21577 cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0); 21578 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y; 21579 cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x); 21580 cursor.x = scroll.x + style->border + style->padding.x; 21581 21582 /* calculate empty space around cursor */ 21583 empty_north.x = scroll.x; 21584 empty_north.y = scroll.y; 21585 empty_north.w = scroll.w; 21586 empty_north.h = NK_MAX(cursor.y - scroll.y, 0); 21587 21588 empty_south.x = scroll.x; 21589 empty_south.y = cursor.y + cursor.h; 21590 empty_south.w = scroll.w; 21591 empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0); 21592 21593 /* update scrollbar */ 21594 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 21595 &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL); 21596 scroll_off = scroll_offset / target; 21597 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y; 21598 21599 /* draw scrollbar */ 21600 if (style->draw_begin) style->draw_begin(out, style->userdata); 21601 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 21602 if (style->draw_end) style->draw_end(out, style->userdata); 21603 return scroll_offset; 21604} 21605NK_LIB float 21606nk_do_scrollbarh(nk_flags *state, 21607 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 21608 float offset, float target, float step, float button_pixel_inc, 21609 const struct nk_style_scrollbar *style, struct nk_input *in, 21610 const struct nk_user_font *font) 21611{ 21612 struct nk_rect cursor; 21613 struct nk_rect empty_west; 21614 struct nk_rect empty_east; 21615 21616 float scroll_step; 21617 float scroll_offset; 21618 float scroll_off; 21619 float scroll_ratio; 21620 21621 NK_ASSERT(out); 21622 NK_ASSERT(style); 21623 if (!out || !style) return 0; 21624 21625 /* scrollbar background */ 21626 scroll.h = NK_MAX(scroll.h, 1); 21627 scroll.w = NK_MAX(scroll.w, 2 * scroll.h); 21628 if (target <= scroll.w) return 0; 21629 21630 /* optional scrollbar buttons */ 21631 if (style->show_buttons) { 21632 nk_flags ws; 21633 float scroll_w; 21634 struct nk_rect button; 21635 button.y = scroll.y; 21636 button.w = scroll.h; 21637 button.h = scroll.h; 21638 21639 scroll_w = scroll.w - 2 * button.w; 21640 scroll_step = NK_MIN(step, button_pixel_inc); 21641 21642 /* decrement button */ 21643 button.x = scroll.x; 21644 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 21645 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 21646 offset = offset - scroll_step; 21647 21648 /* increment button */ 21649 button.x = scroll.x + scroll.w - button.w; 21650 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 21651 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 21652 offset = offset + scroll_step; 21653 21654 scroll.x = scroll.x + button.w; 21655 scroll.w = scroll_w; 21656 } 21657 21658 /* calculate scrollbar constants */ 21659 scroll_step = NK_MIN(step, scroll.w); 21660 scroll_offset = NK_CLAMP(0, offset, target - scroll.w); 21661 scroll_ratio = scroll.w / target; 21662 scroll_off = scroll_offset / target; 21663 21664 /* calculate cursor bounds */ 21665 cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); 21666 cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; 21667 cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); 21668 cursor.y = scroll.y + style->border + style->padding.y; 21669 21670 /* calculate empty space around cursor */ 21671 empty_west.x = scroll.x; 21672 empty_west.y = scroll.y; 21673 empty_west.w = cursor.x - scroll.x; 21674 empty_west.h = scroll.h; 21675 21676 empty_east.x = cursor.x + cursor.w; 21677 empty_east.y = scroll.y; 21678 empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); 21679 empty_east.h = scroll.h; 21680 21681 /* update scrollbar */ 21682 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 21683 &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); 21684 scroll_off = scroll_offset / target; 21685 cursor.x = scroll.x + (scroll_off * scroll.w); 21686 21687 /* draw scrollbar */ 21688 if (style->draw_begin) style->draw_begin(out, style->userdata); 21689 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 21690 if (style->draw_end) style->draw_end(out, style->userdata); 21691 return scroll_offset; 21692} 21693 21694 21695 21696 21697 21698/* =============================================================== 21699 * 21700 * TEXT EDITOR 21701 * 21702 * ===============================================================*/ 21703/* stb_textedit.h - v1.8 - public domain - Sean Barrett */ 21704struct nk_text_find { 21705 float x,y; /* position of n'th character */ 21706 float height; /* height of line */ 21707 int first_char, length; /* first char of row, and length */ 21708 int prev_first; /*_ first char of previous row */ 21709}; 21710 21711struct nk_text_edit_row { 21712 float x0,x1; 21713 /* starting x location, end x location (allows for align=right, etc) */ 21714 float baseline_y_delta; 21715 /* position of baseline relative to previous row's baseline*/ 21716 float ymin,ymax; 21717 /* height of row above and below baseline */ 21718 int num_chars; 21719}; 21720 21721/* forward declarations */ 21722NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int); 21723NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int); 21724NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int); 21725#define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) 21726 21727NK_INTERN float 21728nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id, 21729 const struct nk_user_font *font) 21730{ 21731 int len = 0; 21732 nk_rune unicode = 0; 21733 const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len); 21734 return font->width(font->userdata, font->height, str, len); 21735} 21736NK_INTERN void 21737nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit, 21738 int line_start_id, float row_height, const struct nk_user_font *font) 21739{ 21740 int l; 21741 int glyphs = 0; 21742 nk_rune unicode; 21743 const char *remaining; 21744 int len = nk_str_len_char(&edit->string); 21745 const char *end = nk_str_get_const(&edit->string) + len; 21746 const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l); 21747 const struct nk_vec2 size = nk_text_calculate_text_bounds(font, 21748 text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE); 21749 21750 r->x0 = 0.0f; 21751 r->x1 = size.x; 21752 r->baseline_y_delta = size.y; 21753 r->ymin = 0.0f; 21754 r->ymax = size.y; 21755 r->num_chars = glyphs; 21756} 21757NK_INTERN int 21758nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y, 21759 const struct nk_user_font *font, float row_height) 21760{ 21761 struct nk_text_edit_row r; 21762 int n = edit->string.len; 21763 float base_y = 0, prev_x; 21764 int i=0, k; 21765 21766 r.x0 = r.x1 = 0; 21767 r.ymin = r.ymax = 0; 21768 r.num_chars = 0; 21769 21770 /* search rows to find one that straddles 'y' */ 21771 while (i < n) { 21772 nk_textedit_layout_row(&r, edit, i, row_height, font); 21773 if (r.num_chars <= 0) 21774 return n; 21775 21776 if (i==0 && y < base_y + r.ymin) 21777 return 0; 21778 21779 if (y < base_y + r.ymax) 21780 break; 21781 21782 i += r.num_chars; 21783 base_y += r.baseline_y_delta; 21784 } 21785 21786 /* below all text, return 'after' last character */ 21787 if (i >= n) 21788 return n; 21789 21790 /* check if it's before the beginning of the line */ 21791 if (x < r.x0) 21792 return i; 21793 21794 /* check if it's before the end of the line */ 21795 if (x < r.x1) { 21796 /* search characters in row for one that straddles 'x' */ 21797 k = i; 21798 prev_x = r.x0; 21799 for (i=0; i < r.num_chars; ++i) { 21800 float w = nk_textedit_get_width(edit, k, i, font); 21801 if (x < prev_x+w) { 21802 if (x < prev_x+w/2) 21803 return k+i; 21804 else return k+i+1; 21805 } 21806 prev_x += w; 21807 } 21808 /* shouldn't happen, but if it does, fall through to end-of-line case */ 21809 } 21810 21811 /* if the last character is a newline, return that. 21812 * otherwise return 'after' the last character */ 21813 if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n') 21814 return i+r.num_chars-1; 21815 else return i+r.num_chars; 21816} 21817NK_LIB void 21818nk_textedit_click(struct nk_text_edit *state, float x, float y, 21819 const struct nk_user_font *font, float row_height) 21820{ 21821 /* API click: on mouse down, move the cursor to the clicked location, 21822 * and reset the selection */ 21823 state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height); 21824 state->select_start = state->cursor; 21825 state->select_end = state->cursor; 21826 state->has_preferred_x = 0; 21827} 21828NK_LIB void 21829nk_textedit_drag(struct nk_text_edit *state, float x, float y, 21830 const struct nk_user_font *font, float row_height) 21831{ 21832 /* API drag: on mouse drag, move the cursor and selection endpoint 21833 * to the clicked location */ 21834 int p = nk_textedit_locate_coord(state, x, y, font, row_height); 21835 if (state->select_start == state->select_end) 21836 state->select_start = state->cursor; 21837 state->cursor = state->select_end = p; 21838} 21839NK_INTERN void 21840nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state, 21841 int n, int single_line, const struct nk_user_font *font, float row_height) 21842{ 21843 /* find the x/y location of a character, and remember info about the previous 21844 * row in case we get a move-up event (for page up, we'll have to rescan) */ 21845 struct nk_text_edit_row r; 21846 int prev_start = 0; 21847 int z = state->string.len; 21848 int i=0, first; 21849 21850 nk_zero_struct(r); 21851 if (n == z) { 21852 /* if it's at the end, then find the last line -- simpler than trying to 21853 explicitly handle this case in the regular code */ 21854 nk_textedit_layout_row(&r, state, 0, row_height, font); 21855 if (single_line) { 21856 find->first_char = 0; 21857 find->length = z; 21858 } else { 21859 while (i < z) { 21860 prev_start = i; 21861 i += r.num_chars; 21862 nk_textedit_layout_row(&r, state, i, row_height, font); 21863 } 21864 21865 find->first_char = i; 21866 find->length = r.num_chars; 21867 } 21868 find->x = r.x1; 21869 find->y = r.ymin; 21870 find->height = r.ymax - r.ymin; 21871 find->prev_first = prev_start; 21872 return; 21873 } 21874 21875 /* search rows to find the one that straddles character n */ 21876 find->y = 0; 21877 21878 for(;;) { 21879 nk_textedit_layout_row(&r, state, i, row_height, font); 21880 if (n < i + r.num_chars) break; 21881 prev_start = i; 21882 i += r.num_chars; 21883 find->y += r.baseline_y_delta; 21884 } 21885 21886 find->first_char = first = i; 21887 find->length = r.num_chars; 21888 find->height = r.ymax - r.ymin; 21889 find->prev_first = prev_start; 21890 21891 /* now scan to find xpos */ 21892 find->x = r.x0; 21893 for (i=0; first+i < n; ++i) 21894 find->x += nk_textedit_get_width(state, first, i, font); 21895} 21896NK_INTERN void 21897nk_textedit_clamp(struct nk_text_edit *state) 21898{ 21899 /* make the selection/cursor state valid if client altered the string */ 21900 int n = state->string.len; 21901 if (NK_TEXT_HAS_SELECTION(state)) { 21902 if (state->select_start > n) state->select_start = n; 21903 if (state->select_end > n) state->select_end = n; 21904 /* if clamping forced them to be equal, move the cursor to match */ 21905 if (state->select_start == state->select_end) 21906 state->cursor = state->select_start; 21907 } 21908 if (state->cursor > n) state->cursor = n; 21909} 21910NK_API void 21911nk_textedit_delete(struct nk_text_edit *state, int where, int len) 21912{ 21913 /* delete characters while updating undo */ 21914 nk_textedit_makeundo_delete(state, where, len); 21915 nk_str_delete_runes(&state->string, where, len); 21916 state->has_preferred_x = 0; 21917} 21918NK_API void 21919nk_textedit_delete_selection(struct nk_text_edit *state) 21920{ 21921 /* delete the section */ 21922 nk_textedit_clamp(state); 21923 if (NK_TEXT_HAS_SELECTION(state)) { 21924 if (state->select_start < state->select_end) { 21925 nk_textedit_delete(state, state->select_start, 21926 state->select_end - state->select_start); 21927 state->select_end = state->cursor = state->select_start; 21928 } else { 21929 nk_textedit_delete(state, state->select_end, 21930 state->select_start - state->select_end); 21931 state->select_start = state->cursor = state->select_end; 21932 } 21933 state->has_preferred_x = 0; 21934 } 21935} 21936NK_INTERN void 21937nk_textedit_sortselection(struct nk_text_edit *state) 21938{ 21939 /* canonicalize the selection so start <= end */ 21940 if (state->select_end < state->select_start) { 21941 int temp = state->select_end; 21942 state->select_end = state->select_start; 21943 state->select_start = temp; 21944 } 21945} 21946NK_INTERN void 21947nk_textedit_move_to_first(struct nk_text_edit *state) 21948{ 21949 /* move cursor to first character of selection */ 21950 if (NK_TEXT_HAS_SELECTION(state)) { 21951 nk_textedit_sortselection(state); 21952 state->cursor = state->select_start; 21953 state->select_end = state->select_start; 21954 state->has_preferred_x = 0; 21955 } 21956} 21957NK_INTERN void 21958nk_textedit_move_to_last(struct nk_text_edit *state) 21959{ 21960 /* move cursor to last character of selection */ 21961 if (NK_TEXT_HAS_SELECTION(state)) { 21962 nk_textedit_sortselection(state); 21963 nk_textedit_clamp(state); 21964 state->cursor = state->select_end; 21965 state->select_start = state->select_end; 21966 state->has_preferred_x = 0; 21967 } 21968} 21969NK_INTERN int 21970nk_is_word_boundary( struct nk_text_edit *state, int idx) 21971{ 21972 int len; 21973 nk_rune c; 21974 if (idx <= 0) return 1; 21975 if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1; 21976 return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' || 21977 c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || 21978 c == '|'); 21979} 21980NK_INTERN int 21981nk_textedit_move_to_word_previous(struct nk_text_edit *state) 21982{ 21983 int c = state->cursor - 1; 21984 while( c >= 0 && !nk_is_word_boundary(state, c)) 21985 --c; 21986 21987 if( c < 0 ) 21988 c = 0; 21989 21990 return c; 21991} 21992NK_INTERN int 21993nk_textedit_move_to_word_next(struct nk_text_edit *state) 21994{ 21995 const int len = state->string.len; 21996 int c = state->cursor+1; 21997 while( c < len && !nk_is_word_boundary(state, c)) 21998 ++c; 21999 22000 if( c > len ) 22001 c = len; 22002 22003 return c; 22004} 22005NK_INTERN void 22006nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state) 22007{ 22008 /* update selection and cursor to match each other */ 22009 if (!NK_TEXT_HAS_SELECTION(state)) 22010 state->select_start = state->select_end = state->cursor; 22011 else state->cursor = state->select_end; 22012} 22013NK_API int 22014nk_textedit_cut(struct nk_text_edit *state) 22015{ 22016 /* API cut: delete selection */ 22017 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22018 return 0; 22019 if (NK_TEXT_HAS_SELECTION(state)) { 22020 nk_textedit_delete_selection(state); /* implicitly clamps */ 22021 state->has_preferred_x = 0; 22022 return 1; 22023 } 22024 return 0; 22025} 22026NK_API int 22027nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len) 22028{ 22029 /* API paste: replace existing selection with passed-in text */ 22030 int glyphs; 22031 const char *text = (const char *) ctext; 22032 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0; 22033 22034 /* if there's a selection, the paste should delete it */ 22035 nk_textedit_clamp(state); 22036 nk_textedit_delete_selection(state); 22037 22038 /* try to insert the characters */ 22039 glyphs = nk_utf_len(ctext, len); 22040 if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) { 22041 nk_textedit_makeundo_insert(state, state->cursor, glyphs); 22042 state->cursor += len; 22043 state->has_preferred_x = 0; 22044 return 1; 22045 } 22046 /* remove the undo since we didn't actually insert the characters */ 22047 if (state->undo.undo_point) 22048 --state->undo.undo_point; 22049 return 0; 22050} 22051NK_API void 22052nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len) 22053{ 22054 nk_rune unicode; 22055 int glyph_len; 22056 int text_len = 0; 22057 22058 NK_ASSERT(state); 22059 NK_ASSERT(text); 22060 if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return; 22061 22062 glyph_len = nk_utf_decode(text, &unicode, total_len); 22063 while ((text_len < total_len) && glyph_len) 22064 { 22065 /* don't insert a backward delete, just process the event */ 22066 if (unicode == 127) goto next; 22067 /* can't add newline in single-line mode */ 22068 if (unicode == '\n' && state->single_line) goto next; 22069 /* filter incoming text */ 22070 if (state->filter && !state->filter(state, unicode)) goto next; 22071 22072 if (!NK_TEXT_HAS_SELECTION(state) && 22073 state->cursor < state->string.len) 22074 { 22075 if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) { 22076 nk_textedit_makeundo_replace(state, state->cursor, 1, 1); 22077 nk_str_delete_runes(&state->string, state->cursor, 1); 22078 } 22079 if (nk_str_insert_text_utf8(&state->string, state->cursor, 22080 text+text_len, 1)) 22081 { 22082 ++state->cursor; 22083 state->has_preferred_x = 0; 22084 } 22085 } else { 22086 nk_textedit_delete_selection(state); /* implicitly clamps */ 22087 if (nk_str_insert_text_utf8(&state->string, state->cursor, 22088 text+text_len, 1)) 22089 { 22090 nk_textedit_makeundo_insert(state, state->cursor, 1); 22091 ++state->cursor; 22092 state->has_preferred_x = 0; 22093 } 22094 } 22095 next: 22096 text_len += glyph_len; 22097 glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); 22098 } 22099} 22100NK_LIB void 22101nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, 22102 const struct nk_user_font *font, float row_height) 22103{ 22104retry: 22105 switch (key) 22106 { 22107 case NK_KEY_NONE: 22108 case NK_KEY_CTRL: 22109 case NK_KEY_ENTER: 22110 case NK_KEY_SHIFT: 22111 case NK_KEY_TAB: 22112 case NK_KEY_COPY: 22113 case NK_KEY_CUT: 22114 case NK_KEY_PASTE: 22115 case NK_KEY_MAX: 22116 default: break; 22117 case NK_KEY_TEXT_UNDO: 22118 nk_textedit_undo(state); 22119 state->has_preferred_x = 0; 22120 break; 22121 22122 case NK_KEY_TEXT_REDO: 22123 nk_textedit_redo(state); 22124 state->has_preferred_x = 0; 22125 break; 22126 22127 case NK_KEY_TEXT_SELECT_ALL: 22128 nk_textedit_select_all(state); 22129 state->has_preferred_x = 0; 22130 break; 22131 22132 case NK_KEY_TEXT_INSERT_MODE: 22133 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22134 state->mode = NK_TEXT_EDIT_MODE_INSERT; 22135 break; 22136 case NK_KEY_TEXT_REPLACE_MODE: 22137 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22138 state->mode = NK_TEXT_EDIT_MODE_REPLACE; 22139 break; 22140 case NK_KEY_TEXT_RESET_MODE: 22141 if (state->mode == NK_TEXT_EDIT_MODE_INSERT || 22142 state->mode == NK_TEXT_EDIT_MODE_REPLACE) 22143 state->mode = NK_TEXT_EDIT_MODE_VIEW; 22144 break; 22145 22146 case NK_KEY_LEFT: 22147 if (shift_mod) { 22148 nk_textedit_clamp(state); 22149 nk_textedit_prep_selection_at_cursor(state); 22150 /* move selection left */ 22151 if (state->select_end > 0) 22152 --state->select_end; 22153 state->cursor = state->select_end; 22154 state->has_preferred_x = 0; 22155 } else { 22156 /* if currently there's a selection, 22157 * move cursor to start of selection */ 22158 if (NK_TEXT_HAS_SELECTION(state)) 22159 nk_textedit_move_to_first(state); 22160 else if (state->cursor > 0) 22161 --state->cursor; 22162 state->has_preferred_x = 0; 22163 } break; 22164 22165 case NK_KEY_RIGHT: 22166 if (shift_mod) { 22167 nk_textedit_prep_selection_at_cursor(state); 22168 /* move selection right */ 22169 ++state->select_end; 22170 nk_textedit_clamp(state); 22171 state->cursor = state->select_end; 22172 state->has_preferred_x = 0; 22173 } else { 22174 /* if currently there's a selection, 22175 * move cursor to end of selection */ 22176 if (NK_TEXT_HAS_SELECTION(state)) 22177 nk_textedit_move_to_last(state); 22178 else ++state->cursor; 22179 nk_textedit_clamp(state); 22180 state->has_preferred_x = 0; 22181 } break; 22182 22183 case NK_KEY_TEXT_WORD_LEFT: 22184 if (shift_mod) { 22185 if( !NK_TEXT_HAS_SELECTION( state ) ) 22186 nk_textedit_prep_selection_at_cursor(state); 22187 state->cursor = nk_textedit_move_to_word_previous(state); 22188 state->select_end = state->cursor; 22189 nk_textedit_clamp(state ); 22190 } else { 22191 if (NK_TEXT_HAS_SELECTION(state)) 22192 nk_textedit_move_to_first(state); 22193 else { 22194 state->cursor = nk_textedit_move_to_word_previous(state); 22195 nk_textedit_clamp(state ); 22196 } 22197 } break; 22198 22199 case NK_KEY_TEXT_WORD_RIGHT: 22200 if (shift_mod) { 22201 if( !NK_TEXT_HAS_SELECTION( state ) ) 22202 nk_textedit_prep_selection_at_cursor(state); 22203 state->cursor = nk_textedit_move_to_word_next(state); 22204 state->select_end = state->cursor; 22205 nk_textedit_clamp(state); 22206 } else { 22207 if (NK_TEXT_HAS_SELECTION(state)) 22208 nk_textedit_move_to_last(state); 22209 else { 22210 state->cursor = nk_textedit_move_to_word_next(state); 22211 nk_textedit_clamp(state ); 22212 } 22213 } break; 22214 22215 case NK_KEY_DOWN: { 22216 struct nk_text_find find; 22217 struct nk_text_edit_row row; 22218 int i, sel = shift_mod; 22219 22220 if (state->single_line) { 22221 /* on windows, up&down in single-line behave like left&right */ 22222 key = NK_KEY_RIGHT; 22223 goto retry; 22224 } 22225 22226 if (sel) 22227 nk_textedit_prep_selection_at_cursor(state); 22228 else if (NK_TEXT_HAS_SELECTION(state)) 22229 nk_textedit_move_to_last(state); 22230 22231 /* compute current position of cursor point */ 22232 nk_textedit_clamp(state); 22233 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22234 font, row_height); 22235 22236 /* now find character position down a row */ 22237 if (find.length) 22238 { 22239 float x; 22240 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 22241 int start = find.first_char + find.length; 22242 22243 state->cursor = start; 22244 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 22245 x = row.x0; 22246 22247 for (i=0; i < row.num_chars && x < row.x1; ++i) { 22248 float dx = nk_textedit_get_width(state, start, i, font); 22249 x += dx; 22250 if (x > goal_x) 22251 break; 22252 ++state->cursor; 22253 } 22254 nk_textedit_clamp(state); 22255 22256 state->has_preferred_x = 1; 22257 state->preferred_x = goal_x; 22258 if (sel) 22259 state->select_end = state->cursor; 22260 } 22261 } break; 22262 22263 case NK_KEY_UP: { 22264 struct nk_text_find find; 22265 struct nk_text_edit_row row; 22266 int i, sel = shift_mod; 22267 22268 if (state->single_line) { 22269 /* on windows, up&down become left&right */ 22270 key = NK_KEY_LEFT; 22271 goto retry; 22272 } 22273 22274 if (sel) 22275 nk_textedit_prep_selection_at_cursor(state); 22276 else if (NK_TEXT_HAS_SELECTION(state)) 22277 nk_textedit_move_to_first(state); 22278 22279 /* compute current position of cursor point */ 22280 nk_textedit_clamp(state); 22281 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22282 font, row_height); 22283 22284 /* can only go up if there's a previous row */ 22285 if (find.prev_first != find.first_char) { 22286 /* now find character position up a row */ 22287 float x; 22288 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 22289 22290 state->cursor = find.prev_first; 22291 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 22292 x = row.x0; 22293 22294 for (i=0; i < row.num_chars && x < row.x1; ++i) { 22295 float dx = nk_textedit_get_width(state, find.prev_first, i, font); 22296 x += dx; 22297 if (x > goal_x) 22298 break; 22299 ++state->cursor; 22300 } 22301 nk_textedit_clamp(state); 22302 22303 state->has_preferred_x = 1; 22304 state->preferred_x = goal_x; 22305 if (sel) state->select_end = state->cursor; 22306 } 22307 } break; 22308 22309 case NK_KEY_DEL: 22310 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22311 break; 22312 if (NK_TEXT_HAS_SELECTION(state)) 22313 nk_textedit_delete_selection(state); 22314 else { 22315 int n = state->string.len; 22316 if (state->cursor < n) 22317 nk_textedit_delete(state, state->cursor, 1); 22318 } 22319 state->has_preferred_x = 0; 22320 break; 22321 22322 case NK_KEY_BACKSPACE: 22323 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 22324 break; 22325 if (NK_TEXT_HAS_SELECTION(state)) 22326 nk_textedit_delete_selection(state); 22327 else { 22328 nk_textedit_clamp(state); 22329 if (state->cursor > 0) { 22330 nk_textedit_delete(state, state->cursor-1, 1); 22331 --state->cursor; 22332 } 22333 } 22334 state->has_preferred_x = 0; 22335 break; 22336 22337 case NK_KEY_TEXT_START: 22338 if (shift_mod) { 22339 nk_textedit_prep_selection_at_cursor(state); 22340 state->cursor = state->select_end = 0; 22341 state->has_preferred_x = 0; 22342 } else { 22343 state->cursor = state->select_start = state->select_end = 0; 22344 state->has_preferred_x = 0; 22345 } 22346 break; 22347 22348 case NK_KEY_TEXT_END: 22349 if (shift_mod) { 22350 nk_textedit_prep_selection_at_cursor(state); 22351 state->cursor = state->select_end = state->string.len; 22352 state->has_preferred_x = 0; 22353 } else { 22354 state->cursor = state->string.len; 22355 state->select_start = state->select_end = 0; 22356 state->has_preferred_x = 0; 22357 } 22358 break; 22359 22360 case NK_KEY_TEXT_LINE_START: { 22361 if (shift_mod) { 22362 struct nk_text_find find; 22363 nk_textedit_clamp(state); 22364 nk_textedit_prep_selection_at_cursor(state); 22365 if (state->string.len && state->cursor == state->string.len) 22366 --state->cursor; 22367 nk_textedit_find_charpos(&find, state,state->cursor, state->single_line, 22368 font, row_height); 22369 state->cursor = state->select_end = find.first_char; 22370 state->has_preferred_x = 0; 22371 } else { 22372 struct nk_text_find find; 22373 if (state->string.len && state->cursor == state->string.len) 22374 --state->cursor; 22375 nk_textedit_clamp(state); 22376 nk_textedit_move_to_first(state); 22377 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22378 font, row_height); 22379 state->cursor = find.first_char; 22380 state->has_preferred_x = 0; 22381 } 22382 } break; 22383 22384 case NK_KEY_TEXT_LINE_END: { 22385 if (shift_mod) { 22386 struct nk_text_find find; 22387 nk_textedit_clamp(state); 22388 nk_textedit_prep_selection_at_cursor(state); 22389 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22390 font, row_height); 22391 state->has_preferred_x = 0; 22392 state->cursor = find.first_char + find.length; 22393 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 22394 --state->cursor; 22395 state->select_end = state->cursor; 22396 } else { 22397 struct nk_text_find find; 22398 nk_textedit_clamp(state); 22399 nk_textedit_move_to_first(state); 22400 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 22401 font, row_height); 22402 22403 state->has_preferred_x = 0; 22404 state->cursor = find.first_char + find.length; 22405 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 22406 --state->cursor; 22407 }} break; 22408 } 22409} 22410NK_INTERN void 22411nk_textedit_flush_redo(struct nk_text_undo_state *state) 22412{ 22413 state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 22414 state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 22415} 22416NK_INTERN void 22417nk_textedit_discard_undo(struct nk_text_undo_state *state) 22418{ 22419 /* discard the oldest entry in the undo list */ 22420 if (state->undo_point > 0) { 22421 /* if the 0th undo state has characters, clean those up */ 22422 if (state->undo_rec[0].char_storage >= 0) { 22423 int n = state->undo_rec[0].insert_length, i; 22424 /* delete n characters from all other records */ 22425 state->undo_char_point = (short)(state->undo_char_point - n); 22426 NK_MEMCPY(state->undo_char, state->undo_char + n, 22427 (nk_size)state->undo_char_point*sizeof(nk_rune)); 22428 for (i=0; i < state->undo_point; ++i) { 22429 if (state->undo_rec[i].char_storage >= 0) 22430 state->undo_rec[i].char_storage = (short) 22431 (state->undo_rec[i].char_storage - n); 22432 } 22433 } 22434 --state->undo_point; 22435 NK_MEMCPY(state->undo_rec, state->undo_rec+1, 22436 (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0]))); 22437 } 22438} 22439NK_INTERN void 22440nk_textedit_discard_redo(struct nk_text_undo_state *state) 22441{ 22442/* discard the oldest entry in the redo list--it's bad if this 22443 ever happens, but because undo & redo have to store the actual 22444 characters in different cases, the redo character buffer can 22445 fill up even though the undo buffer didn't */ 22446 nk_size num; 22447 int k = NK_TEXTEDIT_UNDOSTATECOUNT-1; 22448 if (state->redo_point <= k) { 22449 /* if the k'th undo state has characters, clean those up */ 22450 if (state->undo_rec[k].char_storage >= 0) { 22451 int n = state->undo_rec[k].insert_length, i; 22452 /* delete n characters from all other records */ 22453 state->redo_char_point = (short)(state->redo_char_point + n); 22454 num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point); 22455 NK_MEMCPY(state->undo_char + state->redo_char_point, 22456 state->undo_char + state->redo_char_point-n, num * sizeof(char)); 22457 for (i = state->redo_point; i < k; ++i) { 22458 if (state->undo_rec[i].char_storage >= 0) { 22459 state->undo_rec[i].char_storage = (short) 22460 (state->undo_rec[i].char_storage + n); 22461 } 22462 } 22463 } 22464 ++state->redo_point; 22465 num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point); 22466 if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1, 22467 state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0])); 22468 } 22469} 22470NK_INTERN struct nk_text_undo_record* 22471nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars) 22472{ 22473 /* any time we create a new undo record, we discard redo*/ 22474 nk_textedit_flush_redo(state); 22475 22476 /* if we have no free records, we have to make room, 22477 * by sliding the existing records down */ 22478 if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22479 nk_textedit_discard_undo(state); 22480 22481 /* if the characters to store won't possibly fit in the buffer, 22482 * we can't undo */ 22483 if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) { 22484 state->undo_point = 0; 22485 state->undo_char_point = 0; 22486 return 0; 22487 } 22488 22489 /* if we don't have enough free characters in the buffer, 22490 * we have to make room */ 22491 while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT) 22492 nk_textedit_discard_undo(state); 22493 return &state->undo_rec[state->undo_point++]; 22494} 22495NK_INTERN nk_rune* 22496nk_textedit_createundo(struct nk_text_undo_state *state, int pos, 22497 int insert_len, int delete_len) 22498{ 22499 struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len); 22500 if (r == 0) 22501 return 0; 22502 22503 r->where = pos; 22504 r->insert_length = (short) insert_len; 22505 r->delete_length = (short) delete_len; 22506 22507 if (insert_len == 0) { 22508 r->char_storage = -1; 22509 return 0; 22510 } else { 22511 r->char_storage = state->undo_char_point; 22512 state->undo_char_point = (short)(state->undo_char_point + insert_len); 22513 return &state->undo_char[r->char_storage]; 22514 } 22515} 22516NK_API void 22517nk_textedit_undo(struct nk_text_edit *state) 22518{ 22519 struct nk_text_undo_state *s = &state->undo; 22520 struct nk_text_undo_record u, *r; 22521 if (s->undo_point == 0) 22522 return; 22523 22524 /* we need to do two things: apply the undo record, and create a redo record */ 22525 u = s->undo_rec[s->undo_point-1]; 22526 r = &s->undo_rec[s->redo_point-1]; 22527 r->char_storage = -1; 22528 22529 r->insert_length = u.delete_length; 22530 r->delete_length = u.insert_length; 22531 r->where = u.where; 22532 22533 if (u.delete_length) 22534 { 22535 /* if the undo record says to delete characters, then the redo record will 22536 need to re-insert the characters that get deleted, so we need to store 22537 them. 22538 there are three cases: 22539 - there's enough room to store the characters 22540 - characters stored for *redoing* don't leave room for redo 22541 - characters stored for *undoing* don't leave room for redo 22542 if the last is true, we have to bail */ 22543 if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) { 22544 /* the undo records take up too much character space; there's no space 22545 * to store the redo characters */ 22546 r->insert_length = 0; 22547 } else { 22548 int i; 22549 /* there's definitely room to store the characters eventually */ 22550 while (s->undo_char_point + u.delete_length > s->redo_char_point) { 22551 /* there's currently not enough room, so discard a redo record */ 22552 nk_textedit_discard_redo(s); 22553 /* should never happen: */ 22554 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22555 return; 22556 } 22557 22558 r = &s->undo_rec[s->redo_point-1]; 22559 r->char_storage = (short)(s->redo_char_point - u.delete_length); 22560 s->redo_char_point = (short)(s->redo_char_point - u.delete_length); 22561 22562 /* now save the characters */ 22563 for (i=0; i < u.delete_length; ++i) 22564 s->undo_char[r->char_storage + i] = 22565 nk_str_rune_at(&state->string, u.where + i); 22566 } 22567 /* now we can carry out the deletion */ 22568 nk_str_delete_runes(&state->string, u.where, u.delete_length); 22569 } 22570 22571 /* check type of recorded action: */ 22572 if (u.insert_length) { 22573 /* easy case: was a deletion, so we need to insert n characters */ 22574 nk_str_insert_text_runes(&state->string, u.where, 22575 &s->undo_char[u.char_storage], u.insert_length); 22576 s->undo_char_point = (short)(s->undo_char_point - u.insert_length); 22577 } 22578 state->cursor = (short)(u.where + u.insert_length); 22579 22580 s->undo_point--; 22581 s->redo_point--; 22582} 22583NK_API void 22584nk_textedit_redo(struct nk_text_edit *state) 22585{ 22586 struct nk_text_undo_state *s = &state->undo; 22587 struct nk_text_undo_record *u, r; 22588 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 22589 return; 22590 22591 /* we need to do two things: apply the redo record, and create an undo record */ 22592 u = &s->undo_rec[s->undo_point]; 22593 r = s->undo_rec[s->redo_point]; 22594 22595 /* we KNOW there must be room for the undo record, because the redo record 22596 was derived from an undo record */ 22597 u->delete_length = r.insert_length; 22598 u->insert_length = r.delete_length; 22599 u->where = r.where; 22600 u->char_storage = -1; 22601 22602 if (r.delete_length) { 22603 /* the redo record requires us to delete characters, so the undo record 22604 needs to store the characters */ 22605 if (s->undo_char_point + u->insert_length > s->redo_char_point) { 22606 u->insert_length = 0; 22607 u->delete_length = 0; 22608 } else { 22609 int i; 22610 u->char_storage = s->undo_char_point; 22611 s->undo_char_point = (short)(s->undo_char_point + u->insert_length); 22612 22613 /* now save the characters */ 22614 for (i=0; i < u->insert_length; ++i) { 22615 s->undo_char[u->char_storage + i] = 22616 nk_str_rune_at(&state->string, u->where + i); 22617 } 22618 } 22619 nk_str_delete_runes(&state->string, r.where, r.delete_length); 22620 } 22621 22622 if (r.insert_length) { 22623 /* easy case: need to insert n characters */ 22624 nk_str_insert_text_runes(&state->string, r.where, 22625 &s->undo_char[r.char_storage], r.insert_length); 22626 } 22627 state->cursor = r.where + r.insert_length; 22628 22629 s->undo_point++; 22630 s->redo_point++; 22631} 22632NK_INTERN void 22633nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length) 22634{ 22635 nk_textedit_createundo(&state->undo, where, 0, length); 22636} 22637NK_INTERN void 22638nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length) 22639{ 22640 int i; 22641 nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0); 22642 if (p) { 22643 for (i=0; i < length; ++i) 22644 p[i] = nk_str_rune_at(&state->string, where+i); 22645 } 22646} 22647NK_INTERN void 22648nk_textedit_makeundo_replace(struct nk_text_edit *state, int where, 22649 int old_length, int new_length) 22650{ 22651 int i; 22652 nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length); 22653 if (p) { 22654 for (i=0; i < old_length; ++i) 22655 p[i] = nk_str_rune_at(&state->string, where+i); 22656 } 22657} 22658NK_LIB void 22659nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, 22660 nk_plugin_filter filter) 22661{ 22662 /* reset the state to default */ 22663 state->undo.undo_point = 0; 22664 state->undo.undo_char_point = 0; 22665 state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 22666 state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 22667 state->select_end = state->select_start = 0; 22668 state->cursor = 0; 22669 state->has_preferred_x = 0; 22670 state->preferred_x = 0; 22671 state->cursor_at_end_of_line = 0; 22672 state->initialized = 1; 22673 state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE); 22674 state->mode = NK_TEXT_EDIT_MODE_VIEW; 22675 state->filter = filter; 22676 state->scrollbar = nk_vec2(0,0); 22677} 22678NK_API void 22679nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size) 22680{ 22681 NK_ASSERT(state); 22682 NK_ASSERT(memory); 22683 if (!state || !memory || !size) return; 22684 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22685 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22686 nk_str_init_fixed(&state->string, memory, size); 22687} 22688NK_API void 22689nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size) 22690{ 22691 NK_ASSERT(state); 22692 NK_ASSERT(alloc); 22693 if (!state || !alloc) return; 22694 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22695 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22696 nk_str_init(&state->string, alloc, size); 22697} 22698#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 22699NK_API void 22700nk_textedit_init_default(struct nk_text_edit *state) 22701{ 22702 NK_ASSERT(state); 22703 if (!state) return; 22704 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 22705 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 22706 nk_str_init_default(&state->string); 22707} 22708#endif 22709NK_API void 22710nk_textedit_select_all(struct nk_text_edit *state) 22711{ 22712 NK_ASSERT(state); 22713 state->select_start = 0; 22714 state->select_end = state->string.len; 22715} 22716NK_API void 22717nk_textedit_free(struct nk_text_edit *state) 22718{ 22719 NK_ASSERT(state); 22720 if (!state) return; 22721 nk_str_free(&state->string); 22722} 22723 22724 22725 22726 22727 22728/* =============================================================== 22729 * 22730 * FILTER 22731 * 22732 * ===============================================================*/ 22733NK_API int 22734nk_filter_default(const struct nk_text_edit *box, nk_rune unicode) 22735{ 22736 NK_UNUSED(unicode); 22737 NK_UNUSED(box); 22738 return nk_true; 22739} 22740NK_API int 22741nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode) 22742{ 22743 NK_UNUSED(box); 22744 if (unicode > 128) return nk_false; 22745 else return nk_true; 22746} 22747NK_API int 22748nk_filter_float(const struct nk_text_edit *box, nk_rune unicode) 22749{ 22750 NK_UNUSED(box); 22751 if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') 22752 return nk_false; 22753 else return nk_true; 22754} 22755NK_API int 22756nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode) 22757{ 22758 NK_UNUSED(box); 22759 if ((unicode < '0' || unicode > '9') && unicode != '-') 22760 return nk_false; 22761 else return nk_true; 22762} 22763NK_API int 22764nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode) 22765{ 22766 NK_UNUSED(box); 22767 if ((unicode < '0' || unicode > '9') && 22768 (unicode < 'a' || unicode > 'f') && 22769 (unicode < 'A' || unicode > 'F')) 22770 return nk_false; 22771 else return nk_true; 22772} 22773NK_API int 22774nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode) 22775{ 22776 NK_UNUSED(box); 22777 if (unicode < '0' || unicode > '7') 22778 return nk_false; 22779 else return nk_true; 22780} 22781NK_API int 22782nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode) 22783{ 22784 NK_UNUSED(box); 22785 if (unicode != '0' && unicode != '1') 22786 return nk_false; 22787 else return nk_true; 22788} 22789 22790/* =============================================================== 22791 * 22792 * EDIT 22793 * 22794 * ===============================================================*/ 22795NK_LIB void 22796nk_edit_draw_text(struct nk_command_buffer *out, 22797 const struct nk_style_edit *style, float pos_x, float pos_y, 22798 float x_offset, const char *text, int byte_len, float row_height, 22799 const struct nk_user_font *font, struct nk_color background, 22800 struct nk_color foreground, int is_selected) 22801{ 22802 NK_ASSERT(out); 22803 NK_ASSERT(font); 22804 NK_ASSERT(style); 22805 if (!text || !byte_len || !out || !style) return; 22806 22807 {int glyph_len = 0; 22808 nk_rune unicode = 0; 22809 int text_len = 0; 22810 float line_width = 0; 22811 float glyph_width; 22812 const char *line = text; 22813 float line_offset = 0; 22814 int line_count = 0; 22815 22816 struct nk_text txt; 22817 txt.padding = nk_vec2(0,0); 22818 txt.background = background; 22819 txt.text = foreground; 22820 22821 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len); 22822 if (!glyph_len) return; 22823 while ((text_len < byte_len) && glyph_len) 22824 { 22825 if (unicode == '\n') { 22826 /* new line separator so draw previous line */ 22827 struct nk_rect label; 22828 label.y = pos_y + line_offset; 22829 label.h = row_height; 22830 label.w = line_width; 22831 label.x = pos_x; 22832 if (!line_count) 22833 label.x += x_offset; 22834 22835 if (is_selected) /* selection needs to draw different background color */ 22836 nk_fill_rect(out, label, 0, background); 22837 nk_widget_text(out, label, line, (int)((text + text_len) - line), 22838 &txt, NK_TEXT_CENTERED, font); 22839 22840 text_len++; 22841 line_count++; 22842 line_width = 0; 22843 line = text + text_len; 22844 line_offset += row_height; 22845 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len)); 22846 continue; 22847 } 22848 if (unicode == '\r') { 22849 text_len++; 22850 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 22851 continue; 22852 } 22853 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 22854 line_width += (float)glyph_width; 22855 text_len += glyph_len; 22856 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 22857 continue; 22858 } 22859 if (line_width > 0) { 22860 /* draw last line */ 22861 struct nk_rect label; 22862 label.y = pos_y + line_offset; 22863 label.h = row_height; 22864 label.w = line_width; 22865 label.x = pos_x; 22866 if (!line_count) 22867 label.x += x_offset; 22868 22869 if (is_selected) 22870 nk_fill_rect(out, label, 0, background); 22871 nk_widget_text(out, label, line, (int)((text + text_len) - line), 22872 &txt, NK_TEXT_LEFT, font); 22873 }} 22874} 22875NK_LIB nk_flags 22876nk_do_edit(nk_flags *state, struct nk_command_buffer *out, 22877 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, 22878 struct nk_text_edit *edit, const struct nk_style_edit *style, 22879 struct nk_input *in, const struct nk_user_font *font) 22880{ 22881 struct nk_rect area; 22882 nk_flags ret = 0; 22883 float row_height; 22884 char prev_state = 0; 22885 char is_hovered = 0; 22886 char select_all = 0; 22887 char cursor_follow = 0; 22888 struct nk_rect old_clip; 22889 struct nk_rect clip; 22890 22891 NK_ASSERT(state); 22892 NK_ASSERT(out); 22893 NK_ASSERT(style); 22894 if (!state || !out || !style) 22895 return ret; 22896 22897 /* visible text area calculation */ 22898 area.x = bounds.x + style->padding.x + style->border; 22899 area.y = bounds.y + style->padding.y + style->border; 22900 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border); 22901 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border); 22902 if (flags & NK_EDIT_MULTILINE) 22903 area.w = NK_MAX(0, area.w - style->scrollbar_size.x); 22904 row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h; 22905 22906 /* calculate clipping rectangle */ 22907 old_clip = out->clip; 22908 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h); 22909 22910 /* update edit state */ 22911 prev_state = (char)edit->active; 22912 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds); 22913 if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { 22914 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, 22915 bounds.x, bounds.y, bounds.w, bounds.h); 22916 } 22917 22918 /* (de)activate text editor */ 22919 if (!prev_state && edit->active) { 22920 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ? 22921 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE; 22922 nk_textedit_clear_state(edit, type, filter); 22923 if (flags & NK_EDIT_AUTO_SELECT) 22924 select_all = nk_true; 22925 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) { 22926 edit->cursor = edit->string.len; 22927 in = 0; 22928 } 22929 } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW; 22930 if (flags & NK_EDIT_READ_ONLY) 22931 edit->mode = NK_TEXT_EDIT_MODE_VIEW; 22932 else if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 22933 edit->mode = NK_TEXT_EDIT_MODE_INSERT; 22934 22935 ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE; 22936 if (prev_state != edit->active) 22937 ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED; 22938 22939 /* handle user input */ 22940 if (edit->active && in) 22941 { 22942 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down; 22943 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x; 22944 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y; 22945 22946 /* mouse click handler */ 22947 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area); 22948 if (select_all) { 22949 nk_textedit_select_all(edit); 22950 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 22951 in->mouse.buttons[NK_BUTTON_LEFT].clicked) { 22952 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height); 22953 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 22954 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) { 22955 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height); 22956 cursor_follow = nk_true; 22957 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked && 22958 in->mouse.buttons[NK_BUTTON_RIGHT].down) { 22959 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height); 22960 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height); 22961 cursor_follow = nk_true; 22962 } 22963 22964 {int i; /* keyboard input */ 22965 int old_mode = edit->mode; 22966 for (i = 0; i < NK_KEY_MAX; ++i) { 22967 if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */ 22968 if (nk_input_is_key_pressed(in, (enum nk_keys)i)) { 22969 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height); 22970 cursor_follow = nk_true; 22971 } 22972 } 22973 if (old_mode != edit->mode) { 22974 in->keyboard.text_len = 0; 22975 }} 22976 22977 /* text input */ 22978 edit->filter = filter; 22979 if (in->keyboard.text_len) { 22980 nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len); 22981 cursor_follow = nk_true; 22982 in->keyboard.text_len = 0; 22983 } 22984 22985 /* enter key handler */ 22986 if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) { 22987 cursor_follow = nk_true; 22988 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod) 22989 nk_textedit_text(edit, "\n", 1); 22990 else if (flags & NK_EDIT_SIG_ENTER) 22991 ret |= NK_EDIT_COMMITED; 22992 else nk_textedit_text(edit, "\n", 1); 22993 } 22994 22995 /* cut & copy handler */ 22996 {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY); 22997 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT); 22998 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD)) 22999 { 23000 int glyph_len; 23001 nk_rune unicode; 23002 const char *text; 23003 int b = edit->select_start; 23004 int e = edit->select_end; 23005 23006 int begin = NK_MIN(b, e); 23007 int end = NK_MAX(b, e); 23008 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len); 23009 if (edit->clip.copy) 23010 edit->clip.copy(edit->clip.userdata, text, end - begin); 23011 if (cut && !(flags & NK_EDIT_READ_ONLY)){ 23012 nk_textedit_cut(edit); 23013 cursor_follow = nk_true; 23014 } 23015 }} 23016 23017 /* paste handler */ 23018 {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE); 23019 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) { 23020 edit->clip.paste(edit->clip.userdata, edit); 23021 cursor_follow = nk_true; 23022 }} 23023 23024 /* tab handler */ 23025 {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB); 23026 if (tab && (flags & NK_EDIT_ALLOW_TAB)) { 23027 nk_textedit_text(edit, " ", 4); 23028 cursor_follow = nk_true; 23029 }} 23030 } 23031 23032 /* set widget state */ 23033 if (edit->active) 23034 *state = NK_WIDGET_STATE_ACTIVE; 23035 else nk_widget_state_reset(state); 23036 23037 if (is_hovered) 23038 *state |= NK_WIDGET_STATE_HOVERED; 23039 23040 /* DRAW EDIT */ 23041 {const char *text = nk_str_get_const(&edit->string); 23042 int len = nk_str_len_char(&edit->string); 23043 23044 {/* select background colors/images */ 23045 const struct nk_style_item *background; 23046 if (*state & NK_WIDGET_STATE_ACTIVED) 23047 background = &style->active; 23048 else if (*state & NK_WIDGET_STATE_HOVER) 23049 background = &style->hover; 23050 else background = &style->normal; 23051 23052 /* draw background frame */ 23053 if (background->type == NK_STYLE_ITEM_COLOR) { 23054 nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color); 23055 nk_fill_rect(out, bounds, style->rounding, background->data.color); 23056 } else nk_draw_image(out, bounds, &background->data.image, nk_white);} 23057 23058 area.w = NK_MAX(0, area.w - style->cursor_size); 23059 if (edit->active) 23060 { 23061 int total_lines = 1; 23062 struct nk_vec2 text_size = nk_vec2(0,0); 23063 23064 /* text pointer positions */ 23065 const char *cursor_ptr = 0; 23066 const char *select_begin_ptr = 0; 23067 const char *select_end_ptr = 0; 23068 23069 /* 2D pixel positions */ 23070 struct nk_vec2 cursor_pos = nk_vec2(0,0); 23071 struct nk_vec2 selection_offset_start = nk_vec2(0,0); 23072 struct nk_vec2 selection_offset_end = nk_vec2(0,0); 23073 23074 int selection_begin = NK_MIN(edit->select_start, edit->select_end); 23075 int selection_end = NK_MAX(edit->select_start, edit->select_end); 23076 23077 /* calculate total line count + total space + cursor/selection position */ 23078 float line_width = 0.0f; 23079 if (text && len) 23080 { 23081 /* utf8 encoding */ 23082 float glyph_width; 23083 int glyph_len = 0; 23084 nk_rune unicode = 0; 23085 int text_len = 0; 23086 int glyphs = 0; 23087 int row_begin = 0; 23088 23089 glyph_len = nk_utf_decode(text, &unicode, len); 23090 glyph_width = font->width(font->userdata, font->height, text, glyph_len); 23091 line_width = 0; 23092 23093 /* iterate all lines */ 23094 while ((text_len < len) && glyph_len) 23095 { 23096 /* set cursor 2D position and line */ 23097 if (!cursor_ptr && glyphs == edit->cursor) 23098 { 23099 int glyph_offset; 23100 struct nk_vec2 out_offset; 23101 struct nk_vec2 row_size; 23102 const char *remaining; 23103 23104 /* calculate 2d position */ 23105 cursor_pos.y = (float)(total_lines-1) * row_height; 23106 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 23107 text_len-row_begin, row_height, &remaining, 23108 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 23109 cursor_pos.x = row_size.x; 23110 cursor_ptr = text + text_len; 23111 } 23112 23113 /* set start selection 2D position and line */ 23114 if (!select_begin_ptr && edit->select_start != edit->select_end && 23115 glyphs == selection_begin) 23116 { 23117 int glyph_offset; 23118 struct nk_vec2 out_offset; 23119 struct nk_vec2 row_size; 23120 const char *remaining; 23121 23122 /* calculate 2d position */ 23123 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height; 23124 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 23125 text_len-row_begin, row_height, &remaining, 23126 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 23127 selection_offset_start.x = row_size.x; 23128 select_begin_ptr = text + text_len; 23129 } 23130 23131 /* set end selection 2D position and line */ 23132 if (!select_end_ptr && edit->select_start != edit->select_end && 23133 glyphs == selection_end) 23134 { 23135 int glyph_offset; 23136 struct nk_vec2 out_offset; 23137 struct nk_vec2 row_size; 23138 const char *remaining; 23139 23140 /* calculate 2d position */ 23141 selection_offset_end.y = (float)(total_lines-1) * row_height; 23142 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 23143 text_len-row_begin, row_height, &remaining, 23144 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 23145 selection_offset_end.x = row_size.x; 23146 select_end_ptr = text + text_len; 23147 } 23148 if (unicode == '\n') { 23149 text_size.x = NK_MAX(text_size.x, line_width); 23150 total_lines++; 23151 line_width = 0; 23152 text_len++; 23153 glyphs++; 23154 row_begin = text_len; 23155 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 23156 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 23157 continue; 23158 } 23159 23160 glyphs++; 23161 text_len += glyph_len; 23162 line_width += (float)glyph_width; 23163 23164 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 23165 glyph_width = font->width(font->userdata, font->height, 23166 text+text_len, glyph_len); 23167 continue; 23168 } 23169 text_size.y = (float)total_lines * row_height; 23170 23171 /* handle case when cursor is at end of text buffer */ 23172 if (!cursor_ptr && edit->cursor == edit->string.len) { 23173 cursor_pos.x = line_width; 23174 cursor_pos.y = text_size.y - row_height; 23175 } 23176 } 23177 { 23178 /* scrollbar */ 23179 if (cursor_follow) 23180 { 23181 /* update scrollbar to follow cursor */ 23182 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) { 23183 /* horizontal scroll */ 23184 const float scroll_increment = area.w * 0.25f; 23185 if (cursor_pos.x < edit->scrollbar.x) 23186 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment); 23187 if (cursor_pos.x >= edit->scrollbar.x + area.w) 23188 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, edit->scrollbar.x + scroll_increment); 23189 } else edit->scrollbar.x = 0; 23190 23191 if (flags & NK_EDIT_MULTILINE) { 23192 /* vertical scroll */ 23193 if (cursor_pos.y < edit->scrollbar.y) 23194 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height); 23195 if (cursor_pos.y >= edit->scrollbar.y + area.h) 23196 edit->scrollbar.y = edit->scrollbar.y + row_height; 23197 } else edit->scrollbar.y = 0; 23198 } 23199 23200 /* scrollbar widget */ 23201 if (flags & NK_EDIT_MULTILINE) 23202 { 23203 nk_flags ws; 23204 struct nk_rect scroll; 23205 float scroll_target; 23206 float scroll_offset; 23207 float scroll_step; 23208 float scroll_inc; 23209 23210 scroll = area; 23211 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x; 23212 scroll.w = style->scrollbar_size.x; 23213 23214 scroll_offset = edit->scrollbar.y; 23215 scroll_step = scroll.h * 0.10f; 23216 scroll_inc = scroll.h * 0.01f; 23217 scroll_target = text_size.y; 23218 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0, 23219 scroll_offset, scroll_target, scroll_step, scroll_inc, 23220 &style->scrollbar, in, font); 23221 } 23222 } 23223 23224 /* draw text */ 23225 {struct nk_color background_color; 23226 struct nk_color text_color; 23227 struct nk_color sel_background_color; 23228 struct nk_color sel_text_color; 23229 struct nk_color cursor_color; 23230 struct nk_color cursor_text_color; 23231 const struct nk_style_item *background; 23232 nk_push_scissor(out, clip); 23233 23234 /* select correct colors to draw */ 23235 if (*state & NK_WIDGET_STATE_ACTIVED) { 23236 background = &style->active; 23237 text_color = style->text_active; 23238 sel_text_color = style->selected_text_hover; 23239 sel_background_color = style->selected_hover; 23240 cursor_color = style->cursor_hover; 23241 cursor_text_color = style->cursor_text_hover; 23242 } else if (*state & NK_WIDGET_STATE_HOVER) { 23243 background = &style->hover; 23244 text_color = style->text_hover; 23245 sel_text_color = style->selected_text_hover; 23246 sel_background_color = style->selected_hover; 23247 cursor_text_color = style->cursor_text_hover; 23248 cursor_color = style->cursor_hover; 23249 } else { 23250 background = &style->normal; 23251 text_color = style->text_normal; 23252 sel_text_color = style->selected_text_normal; 23253 sel_background_color = style->selected_normal; 23254 cursor_color = style->cursor_normal; 23255 cursor_text_color = style->cursor_text_normal; 23256 } 23257 if (background->type == NK_STYLE_ITEM_IMAGE) 23258 background_color = nk_rgba(0,0,0,0); 23259 else background_color = background->data.color; 23260 23261 23262 if (edit->select_start == edit->select_end) { 23263 /* no selection so just draw the complete text */ 23264 const char *begin = nk_str_get_const(&edit->string); 23265 int l = nk_str_len_char(&edit->string); 23266 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23267 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 23268 background_color, text_color, nk_false); 23269 } else { 23270 /* edit has selection so draw 1-3 text chunks */ 23271 if (edit->select_start != edit->select_end && selection_begin > 0){ 23272 /* draw unselected text before selection */ 23273 const char *begin = nk_str_get_const(&edit->string); 23274 NK_ASSERT(select_begin_ptr); 23275 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23276 area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin), 23277 row_height, font, background_color, text_color, nk_false); 23278 } 23279 if (edit->select_start != edit->select_end) { 23280 /* draw selected text */ 23281 NK_ASSERT(select_begin_ptr); 23282 if (!select_end_ptr) { 23283 const char *begin = nk_str_get_const(&edit->string); 23284 select_end_ptr = begin + nk_str_len_char(&edit->string); 23285 } 23286 nk_edit_draw_text(out, style, 23287 area.x - edit->scrollbar.x, 23288 area.y + selection_offset_start.y - edit->scrollbar.y, 23289 selection_offset_start.x, 23290 select_begin_ptr, (int)(select_end_ptr - select_begin_ptr), 23291 row_height, font, sel_background_color, sel_text_color, nk_true); 23292 } 23293 if ((edit->select_start != edit->select_end && 23294 selection_end < edit->string.len)) 23295 { 23296 /* draw unselected text after selected text */ 23297 const char *begin = select_end_ptr; 23298 const char *end = nk_str_get_const(&edit->string) + 23299 nk_str_len_char(&edit->string); 23300 NK_ASSERT(select_end_ptr); 23301 nk_edit_draw_text(out, style, 23302 area.x - edit->scrollbar.x, 23303 area.y + selection_offset_end.y - edit->scrollbar.y, 23304 selection_offset_end.x, 23305 begin, (int)(end - begin), row_height, font, 23306 background_color, text_color, nk_true); 23307 } 23308 } 23309 23310 /* cursor */ 23311 if (edit->select_start == edit->select_end) 23312 { 23313 if (edit->cursor >= nk_str_len(&edit->string) || 23314 (cursor_ptr && *cursor_ptr == '\n')) { 23315 /* draw cursor at end of line */ 23316 struct nk_rect cursor; 23317 cursor.w = style->cursor_size; 23318 cursor.h = font->height; 23319 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x; 23320 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f; 23321 cursor.y -= edit->scrollbar.y; 23322 nk_fill_rect(out, cursor, 0, cursor_color); 23323 } else { 23324 /* draw cursor inside text */ 23325 int glyph_len; 23326 struct nk_rect label; 23327 struct nk_text txt; 23328 23329 nk_rune unicode; 23330 NK_ASSERT(cursor_ptr); 23331 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4); 23332 23333 label.x = area.x + cursor_pos.x - edit->scrollbar.x; 23334 label.y = area.y + cursor_pos.y - edit->scrollbar.y; 23335 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len); 23336 label.h = row_height; 23337 23338 txt.padding = nk_vec2(0,0); 23339 txt.background = cursor_color;; 23340 txt.text = cursor_text_color; 23341 nk_fill_rect(out, label, 0, cursor_color); 23342 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font); 23343 } 23344 }} 23345 } else { 23346 /* not active so just draw text */ 23347 int l = nk_str_len_char(&edit->string); 23348 const char *begin = nk_str_get_const(&edit->string); 23349 23350 const struct nk_style_item *background; 23351 struct nk_color background_color; 23352 struct nk_color text_color; 23353 nk_push_scissor(out, clip); 23354 if (*state & NK_WIDGET_STATE_ACTIVED) { 23355 background = &style->active; 23356 text_color = style->text_active; 23357 } else if (*state & NK_WIDGET_STATE_HOVER) { 23358 background = &style->hover; 23359 text_color = style->text_hover; 23360 } else { 23361 background = &style->normal; 23362 text_color = style->text_normal; 23363 } 23364 if (background->type == NK_STYLE_ITEM_IMAGE) 23365 background_color = nk_rgba(0,0,0,0); 23366 else background_color = background->data.color; 23367 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 23368 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 23369 background_color, text_color, nk_false); 23370 } 23371 nk_push_scissor(out, old_clip);} 23372 return ret; 23373} 23374NK_API void 23375nk_edit_focus(struct nk_context *ctx, nk_flags flags) 23376{ 23377 nk_hash hash; 23378 struct nk_window *win; 23379 23380 NK_ASSERT(ctx); 23381 NK_ASSERT(ctx->current); 23382 if (!ctx || !ctx->current) return; 23383 23384 win = ctx->current; 23385 hash = win->edit.seq; 23386 win->edit.active = nk_true; 23387 win->edit.name = hash; 23388 if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 23389 win->edit.mode = NK_TEXT_EDIT_MODE_INSERT; 23390} 23391NK_API void 23392nk_edit_unfocus(struct nk_context *ctx) 23393{ 23394 struct nk_window *win; 23395 NK_ASSERT(ctx); 23396 NK_ASSERT(ctx->current); 23397 if (!ctx || !ctx->current) return; 23398 23399 win = ctx->current; 23400 win->edit.active = nk_false; 23401 win->edit.name = 0; 23402} 23403NK_API nk_flags 23404nk_edit_string(struct nk_context *ctx, nk_flags flags, 23405 char *memory, int *len, int max, nk_plugin_filter filter) 23406{ 23407 nk_hash hash; 23408 nk_flags state; 23409 struct nk_text_edit *edit; 23410 struct nk_window *win; 23411 23412 NK_ASSERT(ctx); 23413 NK_ASSERT(memory); 23414 NK_ASSERT(len); 23415 if (!ctx || !memory || !len) 23416 return 0; 23417 23418 filter = (!filter) ? nk_filter_default: filter; 23419 win = ctx->current; 23420 hash = win->edit.seq; 23421 edit = &ctx->text_edit; 23422 nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)? 23423 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter); 23424 23425 if (win->edit.active && hash == win->edit.name) { 23426 if (flags & NK_EDIT_NO_CURSOR) 23427 edit->cursor = nk_utf_len(memory, *len); 23428 else edit->cursor = win->edit.cursor; 23429 if (!(flags & NK_EDIT_SELECTABLE)) { 23430 edit->select_start = win->edit.cursor; 23431 edit->select_end = win->edit.cursor; 23432 } else { 23433 edit->select_start = win->edit.sel_start; 23434 edit->select_end = win->edit.sel_end; 23435 } 23436 edit->mode = win->edit.mode; 23437 edit->scrollbar.x = (float)win->edit.scrollbar.x; 23438 edit->scrollbar.y = (float)win->edit.scrollbar.y; 23439 edit->active = nk_true; 23440 } else edit->active = nk_false; 23441 23442 max = NK_MAX(1, max); 23443 *len = NK_MIN(*len, max-1); 23444 nk_str_init_fixed(&edit->string, memory, (nk_size)max); 23445 edit->string.buffer.allocated = (nk_size)*len; 23446 edit->string.len = nk_utf_len(memory, *len); 23447 state = nk_edit_buffer(ctx, flags, edit, filter); 23448 *len = (int)edit->string.buffer.allocated; 23449 23450 if (edit->active) { 23451 win->edit.cursor = edit->cursor; 23452 win->edit.sel_start = edit->select_start; 23453 win->edit.sel_end = edit->select_end; 23454 win->edit.mode = edit->mode; 23455 win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x; 23456 win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y; 23457 } return state; 23458} 23459NK_API nk_flags 23460nk_edit_buffer(struct nk_context *ctx, nk_flags flags, 23461 struct nk_text_edit *edit, nk_plugin_filter filter) 23462{ 23463 struct nk_window *win; 23464 struct nk_style *style; 23465 struct nk_input *in; 23466 23467 enum nk_widget_layout_states state; 23468 struct nk_rect bounds; 23469 23470 nk_flags ret_flags = 0; 23471 unsigned char prev_state; 23472 nk_hash hash; 23473 23474 /* make sure correct values */ 23475 NK_ASSERT(ctx); 23476 NK_ASSERT(edit); 23477 NK_ASSERT(ctx->current); 23478 NK_ASSERT(ctx->current->layout); 23479 if (!ctx || !ctx->current || !ctx->current->layout) 23480 return 0; 23481 23482 win = ctx->current; 23483 style = &ctx->style; 23484 state = nk_widget(&bounds, ctx); 23485 if (!state) return state; 23486 in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 23487 23488 /* check if edit is currently hot item */ 23489 hash = win->edit.seq++; 23490 if (win->edit.active && hash == win->edit.name) { 23491 if (flags & NK_EDIT_NO_CURSOR) 23492 edit->cursor = edit->string.len; 23493 if (!(flags & NK_EDIT_SELECTABLE)) { 23494 edit->select_start = edit->cursor; 23495 edit->select_end = edit->cursor; 23496 } 23497 if (flags & NK_EDIT_CLIPBOARD) 23498 edit->clip = ctx->clip; 23499 edit->active = (unsigned char)win->edit.active; 23500 } else edit->active = nk_false; 23501 edit->mode = win->edit.mode; 23502 23503 filter = (!filter) ? nk_filter_default: filter; 23504 prev_state = (unsigned char)edit->active; 23505 in = (flags & NK_EDIT_READ_ONLY) ? 0: in; 23506 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags, 23507 filter, edit, &style->edit, in, style->font); 23508 23509 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 23510 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT]; 23511 if (edit->active && prev_state != edit->active) { 23512 /* current edit is now hot */ 23513 win->edit.active = nk_true; 23514 win->edit.name = hash; 23515 } else if (prev_state && !edit->active) { 23516 /* current edit is now cold */ 23517 win->edit.active = nk_false; 23518 } return ret_flags; 23519} 23520NK_API nk_flags 23521nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags, 23522 char *buffer, int max, nk_plugin_filter filter) 23523{ 23524 nk_flags result; 23525 int len = nk_strlen(buffer); 23526 result = nk_edit_string(ctx, flags, buffer, &len, max, filter); 23527 buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0'; 23528 return result; 23529} 23530 23531 23532 23533 23534 23535/* =============================================================== 23536 * 23537 * PROPERTY 23538 * 23539 * ===============================================================*/ 23540NK_LIB void 23541nk_drag_behavior(nk_flags *state, const struct nk_input *in, 23542 struct nk_rect drag, struct nk_property_variant *variant, 23543 float inc_per_pixel) 23544{ 23545 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 23546 int left_mouse_click_in_cursor = in && 23547 nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true); 23548 23549 nk_widget_state_reset(state); 23550 if (nk_input_is_mouse_hovering_rect(in, drag)) 23551 *state = NK_WIDGET_STATE_HOVERED; 23552 23553 if (left_mouse_down && left_mouse_click_in_cursor) { 23554 float delta, pixels; 23555 pixels = in->mouse.delta.x; 23556 delta = pixels * inc_per_pixel; 23557 switch (variant->kind) { 23558 default: break; 23559 case NK_PROPERTY_INT: 23560 variant->value.i = variant->value.i + (int)delta; 23561 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 23562 break; 23563 case NK_PROPERTY_FLOAT: 23564 variant->value.f = variant->value.f + (float)delta; 23565 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 23566 break; 23567 case NK_PROPERTY_DOUBLE: 23568 variant->value.d = variant->value.d + (double)delta; 23569 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 23570 break; 23571 } 23572 *state = NK_WIDGET_STATE_ACTIVE; 23573 } 23574 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag)) 23575 *state |= NK_WIDGET_STATE_ENTERED; 23576 else if (nk_input_is_mouse_prev_hovering_rect(in, drag)) 23577 *state |= NK_WIDGET_STATE_LEFT; 23578} 23579NK_LIB void 23580nk_property_behavior(nk_flags *ws, const struct nk_input *in, 23581 struct nk_rect property, struct nk_rect label, struct nk_rect edit, 23582 struct nk_rect empty, int *state, struct nk_property_variant *variant, 23583 float inc_per_pixel) 23584{ 23585 if (in && *state == NK_PROPERTY_DEFAULT) { 23586 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT)) 23587 *state = NK_PROPERTY_EDIT; 23588 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true)) 23589 *state = NK_PROPERTY_DRAG; 23590 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true)) 23591 *state = NK_PROPERTY_DRAG; 23592 } 23593 if (*state == NK_PROPERTY_DRAG) { 23594 nk_drag_behavior(ws, in, property, variant, inc_per_pixel); 23595 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT; 23596 } 23597} 23598NK_LIB void 23599nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, 23600 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, 23601 const char *name, int len, const struct nk_user_font *font) 23602{ 23603 struct nk_text text; 23604 const struct nk_style_item *background; 23605 23606 /* select correct background and text color */ 23607 if (state & NK_WIDGET_STATE_ACTIVED) { 23608 background = &style->active; 23609 text.text = style->label_active; 23610 } else if (state & NK_WIDGET_STATE_HOVER) { 23611 background = &style->hover; 23612 text.text = style->label_hover; 23613 } else { 23614 background = &style->normal; 23615 text.text = style->label_normal; 23616 } 23617 23618 /* draw background */ 23619 if (background->type == NK_STYLE_ITEM_IMAGE) { 23620 nk_draw_image(out, *bounds, &background->data.image, nk_white); 23621 text.background = nk_rgba(0,0,0,0); 23622 } else { 23623 text.background = background->data.color; 23624 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 23625 nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color); 23626 } 23627 23628 /* draw label */ 23629 text.padding = nk_vec2(0,0); 23630 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font); 23631} 23632NK_LIB void 23633nk_do_property(nk_flags *ws, 23634 struct nk_command_buffer *out, struct nk_rect property, 23635 const char *name, struct nk_property_variant *variant, 23636 float inc_per_pixel, char *buffer, int *len, 23637 int *state, int *cursor, int *select_begin, int *select_end, 23638 const struct nk_style_property *style, 23639 enum nk_property_filter filter, struct nk_input *in, 23640 const struct nk_user_font *font, struct nk_text_edit *text_edit, 23641 enum nk_button_behavior behavior) 23642{ 23643 const nk_plugin_filter filters[] = { 23644 nk_filter_decimal, 23645 nk_filter_float 23646 }; 23647 int active, old; 23648 int num_len, name_len; 23649 char string[NK_MAX_NUMBER_BUFFER]; 23650 float size; 23651 23652 char *dst = 0; 23653 int *length; 23654 23655 struct nk_rect left; 23656 struct nk_rect right; 23657 struct nk_rect label; 23658 struct nk_rect edit; 23659 struct nk_rect empty; 23660 23661 /* left decrement button */ 23662 left.h = font->height/2; 23663 left.w = left.h; 23664 left.x = property.x + style->border + style->padding.x; 23665 left.y = property.y + style->border + property.h/2.0f - left.h/2; 23666 23667 /* text label */ 23668 name_len = nk_strlen(name); 23669 size = font->width(font->userdata, font->height, name, name_len); 23670 label.x = left.x + left.w + style->padding.x; 23671 label.w = (float)size + 2 * style->padding.x; 23672 label.y = property.y + style->border + style->padding.y; 23673 label.h = property.h - (2 * style->border + 2 * style->padding.y); 23674 23675 /* right increment button */ 23676 right.y = left.y; 23677 right.w = left.w; 23678 right.h = left.h; 23679 right.x = property.x + property.w - (right.w + style->padding.x); 23680 23681 /* edit */ 23682 if (*state == NK_PROPERTY_EDIT) { 23683 size = font->width(font->userdata, font->height, buffer, *len); 23684 size += style->edit.cursor_size; 23685 length = len; 23686 dst = buffer; 23687 } else { 23688 switch (variant->kind) { 23689 default: break; 23690 case NK_PROPERTY_INT: 23691 nk_itoa(string, variant->value.i); 23692 num_len = nk_strlen(string); 23693 break; 23694 case NK_PROPERTY_FLOAT: 23695 NK_DTOA(string, (double)variant->value.f); 23696 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 23697 break; 23698 case NK_PROPERTY_DOUBLE: 23699 NK_DTOA(string, variant->value.d); 23700 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 23701 break; 23702 } 23703 size = font->width(font->userdata, font->height, string, num_len); 23704 dst = string; 23705 length = &num_len; 23706 } 23707 23708 edit.w = (float)size + 2 * style->padding.x; 23709 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w)); 23710 edit.x = right.x - (edit.w + style->padding.x); 23711 edit.y = property.y + style->border; 23712 edit.h = property.h - (2 * style->border); 23713 23714 /* empty left space activator */ 23715 empty.w = edit.x - (label.x + label.w); 23716 empty.x = label.x + label.w; 23717 empty.y = property.y; 23718 empty.h = property.h; 23719 23720 /* update property */ 23721 old = (*state == NK_PROPERTY_EDIT); 23722 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel); 23723 23724 /* draw property */ 23725 if (style->draw_begin) style->draw_begin(out, style->userdata); 23726 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font); 23727 if (style->draw_end) style->draw_end(out, style->userdata); 23728 23729 /* execute right button */ 23730 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) { 23731 switch (variant->kind) { 23732 default: break; 23733 case NK_PROPERTY_INT: 23734 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break; 23735 case NK_PROPERTY_FLOAT: 23736 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break; 23737 case NK_PROPERTY_DOUBLE: 23738 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break; 23739 } 23740 } 23741 /* execute left button */ 23742 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) { 23743 switch (variant->kind) { 23744 default: break; 23745 case NK_PROPERTY_INT: 23746 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break; 23747 case NK_PROPERTY_FLOAT: 23748 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break; 23749 case NK_PROPERTY_DOUBLE: 23750 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break; 23751 } 23752 } 23753 if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) { 23754 /* property has been activated so setup buffer */ 23755 NK_MEMCPY(buffer, dst, (nk_size)*length); 23756 *cursor = nk_utf_len(buffer, *length); 23757 *len = *length; 23758 length = len; 23759 dst = buffer; 23760 active = 0; 23761 } else active = (*state == NK_PROPERTY_EDIT); 23762 23763 /* execute and run text edit field */ 23764 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]); 23765 text_edit->active = (unsigned char)active; 23766 text_edit->string.len = *length; 23767 text_edit->cursor = NK_CLAMP(0, *cursor, *length); 23768 text_edit->select_start = NK_CLAMP(0,*select_begin, *length); 23769 text_edit->select_end = NK_CLAMP(0,*select_end, *length); 23770 text_edit->string.buffer.allocated = (nk_size)*length; 23771 text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER; 23772 text_edit->string.buffer.memory.ptr = dst; 23773 text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER; 23774 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT; 23775 nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT, 23776 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font); 23777 23778 *length = text_edit->string.len; 23779 *cursor = text_edit->cursor; 23780 *select_begin = text_edit->select_start; 23781 *select_end = text_edit->select_end; 23782 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER)) 23783 text_edit->active = nk_false; 23784 23785 if (active && !text_edit->active) { 23786 /* property is now not active so convert edit text to value*/ 23787 *state = NK_PROPERTY_DEFAULT; 23788 buffer[*len] = '\0'; 23789 switch (variant->kind) { 23790 default: break; 23791 case NK_PROPERTY_INT: 23792 variant->value.i = nk_strtoi(buffer, 0); 23793 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 23794 break; 23795 case NK_PROPERTY_FLOAT: 23796 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 23797 variant->value.f = nk_strtof(buffer, 0); 23798 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 23799 break; 23800 case NK_PROPERTY_DOUBLE: 23801 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 23802 variant->value.d = nk_strtod(buffer, 0); 23803 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 23804 break; 23805 } 23806 } 23807} 23808NK_LIB struct nk_property_variant 23809nk_property_variant_int(int value, int min_value, int max_value, int step) 23810{ 23811 struct nk_property_variant result; 23812 result.kind = NK_PROPERTY_INT; 23813 result.value.i = value; 23814 result.min_value.i = min_value; 23815 result.max_value.i = max_value; 23816 result.step.i = step; 23817 return result; 23818} 23819NK_LIB struct nk_property_variant 23820nk_property_variant_float(float value, float min_value, float max_value, float step) 23821{ 23822 struct nk_property_variant result; 23823 result.kind = NK_PROPERTY_FLOAT; 23824 result.value.f = value; 23825 result.min_value.f = min_value; 23826 result.max_value.f = max_value; 23827 result.step.f = step; 23828 return result; 23829} 23830NK_LIB struct nk_property_variant 23831nk_property_variant_double(double value, double min_value, double max_value, 23832 double step) 23833{ 23834 struct nk_property_variant result; 23835 result.kind = NK_PROPERTY_DOUBLE; 23836 result.value.d = value; 23837 result.min_value.d = min_value; 23838 result.max_value.d = max_value; 23839 result.step.d = step; 23840 return result; 23841} 23842NK_LIB void 23843nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, 23844 float inc_per_pixel, const enum nk_property_filter filter) 23845{ 23846 struct nk_window *win; 23847 struct nk_panel *layout; 23848 struct nk_input *in; 23849 const struct nk_style *style; 23850 23851 struct nk_rect bounds; 23852 enum nk_widget_layout_states s; 23853 23854 int *state = 0; 23855 nk_hash hash = 0; 23856 char *buffer = 0; 23857 int *len = 0; 23858 int *cursor = 0; 23859 int *select_begin = 0; 23860 int *select_end = 0; 23861 int old_state; 23862 23863 char dummy_buffer[NK_MAX_NUMBER_BUFFER]; 23864 int dummy_state = NK_PROPERTY_DEFAULT; 23865 int dummy_length = 0; 23866 int dummy_cursor = 0; 23867 int dummy_select_begin = 0; 23868 int dummy_select_end = 0; 23869 23870 NK_ASSERT(ctx); 23871 NK_ASSERT(ctx->current); 23872 NK_ASSERT(ctx->current->layout); 23873 if (!ctx || !ctx->current || !ctx->current->layout) 23874 return; 23875 23876 win = ctx->current; 23877 layout = win->layout; 23878 style = &ctx->style; 23879 s = nk_widget(&bounds, ctx); 23880 if (!s) return; 23881 23882 /* calculate hash from name */ 23883 if (name[0] == '#') { 23884 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++); 23885 name++; /* special number hash */ 23886 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42); 23887 23888 /* check if property is currently hot item */ 23889 if (win->property.active && hash == win->property.name) { 23890 buffer = win->property.buffer; 23891 len = &win->property.length; 23892 cursor = &win->property.cursor; 23893 state = &win->property.state; 23894 select_begin = &win->property.select_start; 23895 select_end = &win->property.select_end; 23896 } else { 23897 buffer = dummy_buffer; 23898 len = &dummy_length; 23899 cursor = &dummy_cursor; 23900 state = &dummy_state; 23901 select_begin = &dummy_select_begin; 23902 select_end = &dummy_select_end; 23903 } 23904 23905 /* execute property widget */ 23906 old_state = *state; 23907 ctx->text_edit.clip = ctx->clip; 23908 in = ((s == NK_WIDGET_ROM && !win->property.active) || 23909 layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 23910 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, 23911 variant, inc_per_pixel, buffer, len, state, cursor, select_begin, 23912 select_end, &style->property, filter, in, style->font, &ctx->text_edit, 23913 ctx->button_behavior); 23914 23915 if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) { 23916 /* current property is now hot */ 23917 win->property.active = 1; 23918 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len); 23919 win->property.length = *len; 23920 win->property.cursor = *cursor; 23921 win->property.state = *state; 23922 win->property.name = hash; 23923 win->property.select_start = *select_begin; 23924 win->property.select_end = *select_end; 23925 if (*state == NK_PROPERTY_DRAG) { 23926 ctx->input.mouse.grab = nk_true; 23927 ctx->input.mouse.grabbed = nk_true; 23928 } 23929 } 23930 /* check if previously active property is now inactive */ 23931 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) { 23932 if (old_state == NK_PROPERTY_DRAG) { 23933 ctx->input.mouse.grab = nk_false; 23934 ctx->input.mouse.grabbed = nk_false; 23935 ctx->input.mouse.ungrab = nk_true; 23936 } 23937 win->property.select_start = 0; 23938 win->property.select_end = 0; 23939 win->property.active = 0; 23940 } 23941} 23942NK_API void 23943nk_property_int(struct nk_context *ctx, const char *name, 23944 int min, int *val, int max, int step, float inc_per_pixel) 23945{ 23946 struct nk_property_variant variant; 23947 NK_ASSERT(ctx); 23948 NK_ASSERT(name); 23949 NK_ASSERT(val); 23950 23951 if (!ctx || !ctx->current || !name || !val) return; 23952 variant = nk_property_variant_int(*val, min, max, step); 23953 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 23954 *val = variant.value.i; 23955} 23956NK_API void 23957nk_property_float(struct nk_context *ctx, const char *name, 23958 float min, float *val, float max, float step, float inc_per_pixel) 23959{ 23960 struct nk_property_variant variant; 23961 NK_ASSERT(ctx); 23962 NK_ASSERT(name); 23963 NK_ASSERT(val); 23964 23965 if (!ctx || !ctx->current || !name || !val) return; 23966 variant = nk_property_variant_float(*val, min, max, step); 23967 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23968 *val = variant.value.f; 23969} 23970NK_API void 23971nk_property_double(struct nk_context *ctx, const char *name, 23972 double min, double *val, double max, double step, float inc_per_pixel) 23973{ 23974 struct nk_property_variant variant; 23975 NK_ASSERT(ctx); 23976 NK_ASSERT(name); 23977 NK_ASSERT(val); 23978 23979 if (!ctx || !ctx->current || !name || !val) return; 23980 variant = nk_property_variant_double(*val, min, max, step); 23981 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 23982 *val = variant.value.d; 23983} 23984NK_API int 23985nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, 23986 int max, int step, float inc_per_pixel) 23987{ 23988 struct nk_property_variant variant; 23989 NK_ASSERT(ctx); 23990 NK_ASSERT(name); 23991 23992 if (!ctx || !ctx->current || !name) return val; 23993 variant = nk_property_variant_int(val, min, max, step); 23994 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 23995 val = variant.value.i; 23996 return val; 23997} 23998NK_API float 23999nk_propertyf(struct nk_context *ctx, const char *name, float min, 24000 float val, float max, float step, float inc_per_pixel) 24001{ 24002 struct nk_property_variant variant; 24003 NK_ASSERT(ctx); 24004 NK_ASSERT(name); 24005 24006 if (!ctx || !ctx->current || !name) return val; 24007 variant = nk_property_variant_float(val, min, max, step); 24008 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 24009 val = variant.value.f; 24010 return val; 24011} 24012NK_API double 24013nk_propertyd(struct nk_context *ctx, const char *name, double min, 24014 double val, double max, double step, float inc_per_pixel) 24015{ 24016 struct nk_property_variant variant; 24017 NK_ASSERT(ctx); 24018 NK_ASSERT(name); 24019 24020 if (!ctx || !ctx->current || !name) return val; 24021 variant = nk_property_variant_double(val, min, max, step); 24022 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 24023 val = variant.value.d; 24024 return val; 24025} 24026 24027 24028 24029 24030 24031/* ============================================================== 24032 * 24033 * CHART 24034 * 24035 * ===============================================================*/ 24036NK_API int 24037nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type, 24038 struct nk_color color, struct nk_color highlight, 24039 int count, float min_value, float max_value) 24040{ 24041 struct nk_window *win; 24042 struct nk_chart *chart; 24043 const struct nk_style *config; 24044 const struct nk_style_chart *style; 24045 24046 const struct nk_style_item *background; 24047 struct nk_rect bounds = {0, 0, 0, 0}; 24048 24049 NK_ASSERT(ctx); 24050 NK_ASSERT(ctx->current); 24051 NK_ASSERT(ctx->current->layout); 24052 24053 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 24054 if (!nk_widget(&bounds, ctx)) { 24055 chart = &ctx->current->layout->chart; 24056 nk_zero(chart, sizeof(*chart)); 24057 return 0; 24058 } 24059 24060 win = ctx->current; 24061 config = &ctx->style; 24062 chart = &win->layout->chart; 24063 style = &config->chart; 24064 24065 /* setup basic generic chart */ 24066 nk_zero(chart, sizeof(*chart)); 24067 chart->x = bounds.x + style->padding.x; 24068 chart->y = bounds.y + style->padding.y; 24069 chart->w = bounds.w - 2 * style->padding.x; 24070 chart->h = bounds.h - 2 * style->padding.y; 24071 chart->w = NK_MAX(chart->w, 2 * style->padding.x); 24072 chart->h = NK_MAX(chart->h, 2 * style->padding.y); 24073 24074 /* add first slot into chart */ 24075 {struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 24076 slot->type = type; 24077 slot->count = count; 24078 slot->color = color; 24079 slot->highlight = highlight; 24080 slot->min = NK_MIN(min_value, max_value); 24081 slot->max = NK_MAX(min_value, max_value); 24082 slot->range = slot->max - slot->min;} 24083 24084 /* draw chart background */ 24085 background = &style->background; 24086 if (background->type == NK_STYLE_ITEM_IMAGE) { 24087 nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white); 24088 } else { 24089 nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color); 24090 nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border), 24091 style->rounding, style->background.data.color); 24092 } 24093 return 1; 24094} 24095NK_API int 24096nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type, 24097 int count, float min_value, float max_value) 24098{ 24099 return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, 24100 ctx->style.chart.selected_color, count, min_value, max_value); 24101} 24102NK_API void 24103nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type, 24104 struct nk_color color, struct nk_color highlight, 24105 int count, float min_value, float max_value) 24106{ 24107 NK_ASSERT(ctx); 24108 NK_ASSERT(ctx->current); 24109 NK_ASSERT(ctx->current->layout); 24110 NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT); 24111 if (!ctx || !ctx->current || !ctx->current->layout) return; 24112 if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return; 24113 24114 /* add another slot into the graph */ 24115 {struct nk_chart *chart = &ctx->current->layout->chart; 24116 struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 24117 slot->type = type; 24118 slot->count = count; 24119 slot->color = color; 24120 slot->highlight = highlight; 24121 slot->min = NK_MIN(min_value, max_value); 24122 slot->max = NK_MAX(min_value, max_value); 24123 slot->range = slot->max - slot->min;} 24124} 24125NK_API void 24126nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type, 24127 int count, float min_value, float max_value) 24128{ 24129 nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, 24130 ctx->style.chart.selected_color, count, min_value, max_value); 24131} 24132NK_INTERN nk_flags 24133nk_chart_push_line(struct nk_context *ctx, struct nk_window *win, 24134 struct nk_chart *g, float value, int slot) 24135{ 24136 struct nk_panel *layout = win->layout; 24137 const struct nk_input *i = &ctx->input; 24138 struct nk_command_buffer *out = &win->buffer; 24139 24140 nk_flags ret = 0; 24141 struct nk_vec2 cur; 24142 struct nk_rect bounds; 24143 struct nk_color color; 24144 float step; 24145 float range; 24146 float ratio; 24147 24148 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24149 step = g->w / (float)g->slots[slot].count; 24150 range = g->slots[slot].max - g->slots[slot].min; 24151 ratio = (value - g->slots[slot].min) / range; 24152 24153 if (g->slots[slot].index == 0) { 24154 /* first data point does not have a connection */ 24155 g->slots[slot].last.x = g->x; 24156 g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h; 24157 24158 bounds.x = g->slots[slot].last.x - 2; 24159 bounds.y = g->slots[slot].last.y - 2; 24160 bounds.w = bounds.h = 4; 24161 24162 color = g->slots[slot].color; 24163 if (!(layout->flags & NK_WINDOW_ROM) && 24164 NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){ 24165 ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0; 24166 ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down && 24167 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24168 color = g->slots[slot].highlight; 24169 } 24170 nk_fill_rect(out, bounds, 0, color); 24171 g->slots[slot].index += 1; 24172 return ret; 24173 } 24174 24175 /* draw a line between the last data point and the new one */ 24176 color = g->slots[slot].color; 24177 cur.x = g->x + (float)(step * (float)g->slots[slot].index); 24178 cur.y = (g->y + g->h) - (ratio * (float)g->h); 24179 nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color); 24180 24181 bounds.x = cur.x - 3; 24182 bounds.y = cur.y - 3; 24183 bounds.w = bounds.h = 6; 24184 24185 /* user selection of current data point */ 24186 if (!(layout->flags & NK_WINDOW_ROM)) { 24187 if (nk_input_is_mouse_hovering_rect(i, bounds)) { 24188 ret = NK_CHART_HOVERING; 24189 ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down && 24190 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24191 color = g->slots[slot].highlight; 24192 } 24193 } 24194 nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); 24195 24196 /* save current data point position */ 24197 g->slots[slot].last.x = cur.x; 24198 g->slots[slot].last.y = cur.y; 24199 g->slots[slot].index += 1; 24200 return ret; 24201} 24202NK_INTERN nk_flags 24203nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win, 24204 struct nk_chart *chart, float value, int slot) 24205{ 24206 struct nk_command_buffer *out = &win->buffer; 24207 const struct nk_input *in = &ctx->input; 24208 struct nk_panel *layout = win->layout; 24209 24210 float ratio; 24211 nk_flags ret = 0; 24212 struct nk_color color; 24213 struct nk_rect item = {0,0,0,0}; 24214 24215 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24216 if (chart->slots[slot].index >= chart->slots[slot].count) 24217 return nk_false; 24218 if (chart->slots[slot].count) { 24219 float padding = (float)(chart->slots[slot].count-1); 24220 item.w = (chart->w - padding) / (float)(chart->slots[slot].count); 24221 } 24222 24223 /* calculate bounds of current bar chart entry */ 24224 color = chart->slots[slot].color;; 24225 item.h = chart->h * NK_ABS((value/chart->slots[slot].range)); 24226 if (value >= 0) { 24227 ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range); 24228 item.y = (chart->y + chart->h) - chart->h * ratio; 24229 } else { 24230 ratio = (value - chart->slots[slot].max) / chart->slots[slot].range; 24231 item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h; 24232 } 24233 item.x = chart->x + ((float)chart->slots[slot].index * item.w); 24234 item.x = item.x + ((float)chart->slots[slot].index); 24235 24236 /* user chart bar selection */ 24237 if (!(layout->flags & NK_WINDOW_ROM) && 24238 NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) { 24239 ret = NK_CHART_HOVERING; 24240 ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down && 24241 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 24242 color = chart->slots[slot].highlight; 24243 } 24244 nk_fill_rect(out, item, 0, color); 24245 chart->slots[slot].index += 1; 24246 return ret; 24247} 24248NK_API nk_flags 24249nk_chart_push_slot(struct nk_context *ctx, float value, int slot) 24250{ 24251 nk_flags flags; 24252 struct nk_window *win; 24253 24254 NK_ASSERT(ctx); 24255 NK_ASSERT(ctx->current); 24256 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 24257 NK_ASSERT(slot < ctx->current->layout->chart.slot); 24258 if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false; 24259 if (slot >= ctx->current->layout->chart.slot) return nk_false; 24260 24261 win = ctx->current; 24262 if (win->layout->chart.slot < slot) return nk_false; 24263 switch (win->layout->chart.slots[slot].type) { 24264 case NK_CHART_LINES: 24265 flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break; 24266 case NK_CHART_COLUMN: 24267 flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break; 24268 default: 24269 case NK_CHART_MAX: 24270 flags = 0; 24271 } 24272 return flags; 24273} 24274NK_API nk_flags 24275nk_chart_push(struct nk_context *ctx, float value) 24276{ 24277 return nk_chart_push_slot(ctx, value, 0); 24278} 24279NK_API void 24280nk_chart_end(struct nk_context *ctx) 24281{ 24282 struct nk_window *win; 24283 struct nk_chart *chart; 24284 24285 NK_ASSERT(ctx); 24286 NK_ASSERT(ctx->current); 24287 if (!ctx || !ctx->current) 24288 return; 24289 24290 win = ctx->current; 24291 chart = &win->layout->chart; 24292 NK_MEMSET(chart, 0, sizeof(*chart)); 24293 return; 24294} 24295NK_API void 24296nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values, 24297 int count, int offset) 24298{ 24299 int i = 0; 24300 float min_value; 24301 float max_value; 24302 24303 NK_ASSERT(ctx); 24304 NK_ASSERT(values); 24305 if (!ctx || !values || !count) return; 24306 24307 min_value = values[offset]; 24308 max_value = values[offset]; 24309 for (i = 0; i < count; ++i) { 24310 min_value = NK_MIN(values[i + offset], min_value); 24311 max_value = NK_MAX(values[i + offset], max_value); 24312 } 24313 24314 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 24315 for (i = 0; i < count; ++i) 24316 nk_chart_push(ctx, values[i + offset]); 24317 nk_chart_end(ctx); 24318 } 24319} 24320NK_API void 24321nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata, 24322 float(*value_getter)(void* user, int index), int count, int offset) 24323{ 24324 int i = 0; 24325 float min_value; 24326 float max_value; 24327 24328 NK_ASSERT(ctx); 24329 NK_ASSERT(value_getter); 24330 if (!ctx || !value_getter || !count) return; 24331 24332 max_value = min_value = value_getter(userdata, offset); 24333 for (i = 0; i < count; ++i) { 24334 float value = value_getter(userdata, i + offset); 24335 min_value = NK_MIN(value, min_value); 24336 max_value = NK_MAX(value, max_value); 24337 } 24338 24339 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 24340 for (i = 0; i < count; ++i) 24341 nk_chart_push(ctx, value_getter(userdata, i + offset)); 24342 nk_chart_end(ctx); 24343 } 24344} 24345 24346 24347 24348 24349 24350/* ============================================================== 24351 * 24352 * COLOR PICKER 24353 * 24354 * ===============================================================*/ 24355NK_LIB int 24356nk_color_picker_behavior(nk_flags *state, 24357 const struct nk_rect *bounds, const struct nk_rect *matrix, 24358 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 24359 struct nk_colorf *color, const struct nk_input *in) 24360{ 24361 float hsva[4]; 24362 int value_changed = 0; 24363 int hsv_changed = 0; 24364 24365 NK_ASSERT(state); 24366 NK_ASSERT(matrix); 24367 NK_ASSERT(hue_bar); 24368 NK_ASSERT(color); 24369 24370 /* color matrix */ 24371 nk_colorf_hsva_fv(hsva, *color); 24372 if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) { 24373 hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); 24374 hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); 24375 value_changed = hsv_changed = 1; 24376 } 24377 /* hue bar */ 24378 if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) { 24379 hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); 24380 value_changed = hsv_changed = 1; 24381 } 24382 /* alpha bar */ 24383 if (alpha_bar) { 24384 if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) { 24385 hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); 24386 value_changed = 1; 24387 } 24388 } 24389 nk_widget_state_reset(state); 24390 if (hsv_changed) { 24391 *color = nk_hsva_colorfv(hsva); 24392 *state = NK_WIDGET_STATE_ACTIVE; 24393 } 24394 if (value_changed) { 24395 color->a = hsva[3]; 24396 *state = NK_WIDGET_STATE_ACTIVE; 24397 } 24398 /* set color picker widget state */ 24399 if (nk_input_is_mouse_hovering_rect(in, *bounds)) 24400 *state = NK_WIDGET_STATE_HOVERED; 24401 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 24402 *state |= NK_WIDGET_STATE_ENTERED; 24403 else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 24404 *state |= NK_WIDGET_STATE_LEFT; 24405 return value_changed; 24406} 24407NK_LIB void 24408nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, 24409 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 24410 struct nk_colorf col) 24411{ 24412 NK_STORAGE const struct nk_color black = {0,0,0,255}; 24413 NK_STORAGE const struct nk_color white = {255, 255, 255, 255}; 24414 NK_STORAGE const struct nk_color black_trans = {0,0,0,0}; 24415 24416 const float crosshair_size = 7.0f; 24417 struct nk_color temp; 24418 float hsva[4]; 24419 float line_y; 24420 int i; 24421 24422 NK_ASSERT(o); 24423 NK_ASSERT(matrix); 24424 NK_ASSERT(hue_bar); 24425 24426 /* draw hue bar */ 24427 nk_colorf_hsva_fv(hsva, col); 24428 for (i = 0; i < 6; ++i) { 24429 NK_GLOBAL const struct nk_color hue_colors[] = { 24430 {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255}, 24431 {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255} 24432 }; 24433 nk_fill_rect_multi_color(o, 24434 nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, 24435 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], 24436 hue_colors[i+1], hue_colors[i+1]); 24437 } 24438 line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); 24439 nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, 24440 line_y, 1, nk_rgb(255,255,255)); 24441 24442 /* draw alpha bar */ 24443 if (alpha_bar) { 24444 float alpha = NK_SATURATE(col.a); 24445 line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); 24446 24447 nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); 24448 nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, 24449 line_y, 1, nk_rgb(255,255,255)); 24450 } 24451 24452 /* draw color matrix */ 24453 temp = nk_hsv_f(hsva[0], 1.0f, 1.0f); 24454 nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white); 24455 nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); 24456 24457 /* draw cross-hair */ 24458 {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2]; 24459 p.x = (float)(int)(matrix->x + S * matrix->w); 24460 p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h); 24461 nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); 24462 nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white); 24463 nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white); 24464 nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);} 24465} 24466NK_LIB int 24467nk_do_color_picker(nk_flags *state, 24468 struct nk_command_buffer *out, struct nk_colorf *col, 24469 enum nk_color_format fmt, struct nk_rect bounds, 24470 struct nk_vec2 padding, const struct nk_input *in, 24471 const struct nk_user_font *font) 24472{ 24473 int ret = 0; 24474 struct nk_rect matrix; 24475 struct nk_rect hue_bar; 24476 struct nk_rect alpha_bar; 24477 float bar_w; 24478 24479 NK_ASSERT(out); 24480 NK_ASSERT(col); 24481 NK_ASSERT(state); 24482 NK_ASSERT(font); 24483 if (!out || !col || !state || !font) 24484 return ret; 24485 24486 bar_w = font->height; 24487 bounds.x += padding.x; 24488 bounds.y += padding.x; 24489 bounds.w -= 2 * padding.x; 24490 bounds.h -= 2 * padding.y; 24491 24492 matrix.x = bounds.x; 24493 matrix.y = bounds.y; 24494 matrix.h = bounds.h; 24495 matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); 24496 24497 hue_bar.w = bar_w; 24498 hue_bar.y = bounds.y; 24499 hue_bar.h = matrix.h; 24500 hue_bar.x = matrix.x + matrix.w + padding.x; 24501 24502 alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; 24503 alpha_bar.y = bounds.y; 24504 alpha_bar.w = bar_w; 24505 alpha_bar.h = matrix.h; 24506 24507 ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar, 24508 (fmt == NK_RGBA) ? &alpha_bar:0, col, in); 24509 nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col); 24510 return ret; 24511} 24512NK_API int 24513nk_color_pick(struct nk_context * ctx, struct nk_colorf *color, 24514 enum nk_color_format fmt) 24515{ 24516 struct nk_window *win; 24517 struct nk_panel *layout; 24518 const struct nk_style *config; 24519 const struct nk_input *in; 24520 24521 enum nk_widget_layout_states state; 24522 struct nk_rect bounds; 24523 24524 NK_ASSERT(ctx); 24525 NK_ASSERT(color); 24526 NK_ASSERT(ctx->current); 24527 NK_ASSERT(ctx->current->layout); 24528 if (!ctx || !ctx->current || !ctx->current->layout || !color) 24529 return 0; 24530 24531 win = ctx->current; 24532 config = &ctx->style; 24533 layout = win->layout; 24534 state = nk_widget(&bounds, ctx); 24535 if (!state) return 0; 24536 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24537 return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds, 24538 nk_vec2(0,0), in, config->font); 24539} 24540NK_API struct nk_colorf 24541nk_color_picker(struct nk_context *ctx, struct nk_colorf color, 24542 enum nk_color_format fmt) 24543{ 24544 nk_color_pick(ctx, &color, fmt); 24545 return color; 24546} 24547 24548 24549 24550 24551 24552/* ============================================================== 24553 * 24554 * COMBO 24555 * 24556 * ===============================================================*/ 24557NK_INTERN int 24558nk_combo_begin(struct nk_context *ctx, struct nk_window *win, 24559 struct nk_vec2 size, int is_clicked, struct nk_rect header) 24560{ 24561 struct nk_window *popup; 24562 int is_open = 0; 24563 int is_active = 0; 24564 struct nk_rect body; 24565 nk_hash hash; 24566 24567 NK_ASSERT(ctx); 24568 NK_ASSERT(ctx->current); 24569 NK_ASSERT(ctx->current->layout); 24570 if (!ctx || !ctx->current || !ctx->current->layout) 24571 return 0; 24572 24573 popup = win->popup.win; 24574 body.x = header.x; 24575 body.w = size.x; 24576 body.y = header.y + header.h-ctx->style.window.combo_border; 24577 body.h = size.y; 24578 24579 hash = win->popup.combo_count++; 24580 is_open = (popup) ? nk_true:nk_false; 24581 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO); 24582 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 24583 (!is_open && !is_active && !is_clicked)) return 0; 24584 if (!nk_nonblock_begin(ctx, 0, body, 24585 (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0; 24586 24587 win->popup.type = NK_PANEL_COMBO; 24588 win->popup.name = hash; 24589 return 1; 24590} 24591NK_API int 24592nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len, 24593 struct nk_vec2 size) 24594{ 24595 const struct nk_input *in; 24596 struct nk_window *win; 24597 struct nk_style *style; 24598 24599 enum nk_widget_layout_states s; 24600 int is_clicked = nk_false; 24601 struct nk_rect header; 24602 const struct nk_style_item *background; 24603 struct nk_text text; 24604 24605 NK_ASSERT(ctx); 24606 NK_ASSERT(selected); 24607 NK_ASSERT(ctx->current); 24608 NK_ASSERT(ctx->current->layout); 24609 if (!ctx || !ctx->current || !ctx->current->layout || !selected) 24610 return 0; 24611 24612 win = ctx->current; 24613 style = &ctx->style; 24614 s = nk_widget(&header, ctx); 24615 if (s == NK_WIDGET_INVALID) 24616 return 0; 24617 24618 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24619 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24620 is_clicked = nk_true; 24621 24622 /* draw combo box header background and border */ 24623 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24624 background = &style->combo.active; 24625 text.text = style->combo.label_active; 24626 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24627 background = &style->combo.hover; 24628 text.text = style->combo.label_hover; 24629 } else { 24630 background = &style->combo.normal; 24631 text.text = style->combo.label_normal; 24632 } 24633 if (background->type == NK_STYLE_ITEM_IMAGE) { 24634 text.background = nk_rgba(0,0,0,0); 24635 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24636 } else { 24637 text.background = background->data.color; 24638 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24639 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24640 } 24641 { 24642 /* print currently selected text item */ 24643 struct nk_rect label; 24644 struct nk_rect button; 24645 struct nk_rect content; 24646 24647 enum nk_symbol_type sym; 24648 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24649 sym = style->combo.sym_hover; 24650 else if (is_clicked) 24651 sym = style->combo.sym_active; 24652 else sym = style->combo.sym_normal; 24653 24654 /* calculate button */ 24655 button.w = header.h - 2 * style->combo.button_padding.y; 24656 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24657 button.y = header.y + style->combo.button_padding.y; 24658 button.h = button.w; 24659 24660 content.x = button.x + style->combo.button.padding.x; 24661 content.y = button.y + style->combo.button.padding.y; 24662 content.w = button.w - 2 * style->combo.button.padding.x; 24663 content.h = button.h - 2 * style->combo.button.padding.y; 24664 24665 /* draw selected label */ 24666 text.padding = nk_vec2(0,0); 24667 label.x = header.x + style->combo.content_padding.x; 24668 label.y = header.y + style->combo.content_padding.y; 24669 label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;; 24670 label.h = header.h - 2 * style->combo.content_padding.y; 24671 nk_widget_text(&win->buffer, label, selected, len, &text, 24672 NK_TEXT_LEFT, ctx->style.font); 24673 24674 /* draw open/close button */ 24675 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24676 &ctx->style.combo.button, sym, style->font); 24677 } 24678 return nk_combo_begin(ctx, win, size, is_clicked, header); 24679} 24680NK_API int 24681nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size) 24682{ 24683 return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size); 24684} 24685NK_API int 24686nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size) 24687{ 24688 struct nk_window *win; 24689 struct nk_style *style; 24690 const struct nk_input *in; 24691 24692 struct nk_rect header; 24693 int is_clicked = nk_false; 24694 enum nk_widget_layout_states s; 24695 const struct nk_style_item *background; 24696 24697 NK_ASSERT(ctx); 24698 NK_ASSERT(ctx->current); 24699 NK_ASSERT(ctx->current->layout); 24700 if (!ctx || !ctx->current || !ctx->current->layout) 24701 return 0; 24702 24703 win = ctx->current; 24704 style = &ctx->style; 24705 s = nk_widget(&header, ctx); 24706 if (s == NK_WIDGET_INVALID) 24707 return 0; 24708 24709 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24710 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24711 is_clicked = nk_true; 24712 24713 /* draw combo box header background and border */ 24714 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 24715 background = &style->combo.active; 24716 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24717 background = &style->combo.hover; 24718 else background = &style->combo.normal; 24719 24720 if (background->type == NK_STYLE_ITEM_IMAGE) { 24721 nk_draw_image(&win->buffer, header, &background->data.image,nk_white); 24722 } else { 24723 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24724 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24725 } 24726 { 24727 struct nk_rect content; 24728 struct nk_rect button; 24729 struct nk_rect bounds; 24730 24731 enum nk_symbol_type sym; 24732 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24733 sym = style->combo.sym_hover; 24734 else if (is_clicked) 24735 sym = style->combo.sym_active; 24736 else sym = style->combo.sym_normal; 24737 24738 /* calculate button */ 24739 button.w = header.h - 2 * style->combo.button_padding.y; 24740 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24741 button.y = header.y + style->combo.button_padding.y; 24742 button.h = button.w; 24743 24744 content.x = button.x + style->combo.button.padding.x; 24745 content.y = button.y + style->combo.button.padding.y; 24746 content.w = button.w - 2 * style->combo.button.padding.x; 24747 content.h = button.h - 2 * style->combo.button.padding.y; 24748 24749 /* draw color */ 24750 bounds.h = header.h - 4 * style->combo.content_padding.y; 24751 bounds.y = header.y + 2 * style->combo.content_padding.y; 24752 bounds.x = header.x + 2 * style->combo.content_padding.x; 24753 bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; 24754 nk_fill_rect(&win->buffer, bounds, 0, color); 24755 24756 /* draw open/close button */ 24757 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24758 &ctx->style.combo.button, sym, style->font); 24759 } 24760 return nk_combo_begin(ctx, win, size, is_clicked, header); 24761} 24762NK_API int 24763nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size) 24764{ 24765 struct nk_window *win; 24766 struct nk_style *style; 24767 const struct nk_input *in; 24768 24769 struct nk_rect header; 24770 int is_clicked = nk_false; 24771 enum nk_widget_layout_states s; 24772 const struct nk_style_item *background; 24773 struct nk_color sym_background; 24774 struct nk_color symbol_color; 24775 24776 NK_ASSERT(ctx); 24777 NK_ASSERT(ctx->current); 24778 NK_ASSERT(ctx->current->layout); 24779 if (!ctx || !ctx->current || !ctx->current->layout) 24780 return 0; 24781 24782 win = ctx->current; 24783 style = &ctx->style; 24784 s = nk_widget(&header, ctx); 24785 if (s == NK_WIDGET_INVALID) 24786 return 0; 24787 24788 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24789 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24790 is_clicked = nk_true; 24791 24792 /* draw combo box header background and border */ 24793 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24794 background = &style->combo.active; 24795 symbol_color = style->combo.symbol_active; 24796 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24797 background = &style->combo.hover; 24798 symbol_color = style->combo.symbol_hover; 24799 } else { 24800 background = &style->combo.normal; 24801 symbol_color = style->combo.symbol_hover; 24802 } 24803 24804 if (background->type == NK_STYLE_ITEM_IMAGE) { 24805 sym_background = nk_rgba(0,0,0,0); 24806 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24807 } else { 24808 sym_background = background->data.color; 24809 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24810 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24811 } 24812 { 24813 struct nk_rect bounds = {0,0,0,0}; 24814 struct nk_rect content; 24815 struct nk_rect button; 24816 24817 enum nk_symbol_type sym; 24818 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24819 sym = style->combo.sym_hover; 24820 else if (is_clicked) 24821 sym = style->combo.sym_active; 24822 else sym = style->combo.sym_normal; 24823 24824 /* calculate button */ 24825 button.w = header.h - 2 * style->combo.button_padding.y; 24826 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 24827 button.y = header.y + style->combo.button_padding.y; 24828 button.h = button.w; 24829 24830 content.x = button.x + style->combo.button.padding.x; 24831 content.y = button.y + style->combo.button.padding.y; 24832 content.w = button.w - 2 * style->combo.button.padding.x; 24833 content.h = button.h - 2 * style->combo.button.padding.y; 24834 24835 /* draw symbol */ 24836 bounds.h = header.h - 2 * style->combo.content_padding.y; 24837 bounds.y = header.y + style->combo.content_padding.y; 24838 bounds.x = header.x + style->combo.content_padding.x; 24839 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 24840 nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, 24841 1.0f, style->font); 24842 24843 /* draw open/close button */ 24844 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 24845 &ctx->style.combo.button, sym, style->font); 24846 } 24847 return nk_combo_begin(ctx, win, size, is_clicked, header); 24848} 24849NK_API int 24850nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len, 24851 enum nk_symbol_type symbol, struct nk_vec2 size) 24852{ 24853 struct nk_window *win; 24854 struct nk_style *style; 24855 struct nk_input *in; 24856 24857 struct nk_rect header; 24858 int is_clicked = nk_false; 24859 enum nk_widget_layout_states s; 24860 const struct nk_style_item *background; 24861 struct nk_color symbol_color; 24862 struct nk_text text; 24863 24864 NK_ASSERT(ctx); 24865 NK_ASSERT(ctx->current); 24866 NK_ASSERT(ctx->current->layout); 24867 if (!ctx || !ctx->current || !ctx->current->layout) 24868 return 0; 24869 24870 win = ctx->current; 24871 style = &ctx->style; 24872 s = nk_widget(&header, ctx); 24873 if (!s) return 0; 24874 24875 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24876 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24877 is_clicked = nk_true; 24878 24879 /* draw combo box header background and border */ 24880 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 24881 background = &style->combo.active; 24882 symbol_color = style->combo.symbol_active; 24883 text.text = style->combo.label_active; 24884 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 24885 background = &style->combo.hover; 24886 symbol_color = style->combo.symbol_hover; 24887 text.text = style->combo.label_hover; 24888 } else { 24889 background = &style->combo.normal; 24890 symbol_color = style->combo.symbol_normal; 24891 text.text = style->combo.label_normal; 24892 } 24893 if (background->type == NK_STYLE_ITEM_IMAGE) { 24894 text.background = nk_rgba(0,0,0,0); 24895 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24896 } else { 24897 text.background = background->data.color; 24898 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24899 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24900 } 24901 { 24902 struct nk_rect content; 24903 struct nk_rect button; 24904 struct nk_rect label; 24905 struct nk_rect image; 24906 24907 enum nk_symbol_type sym; 24908 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24909 sym = style->combo.sym_hover; 24910 else if (is_clicked) 24911 sym = style->combo.sym_active; 24912 else sym = style->combo.sym_normal; 24913 24914 /* calculate button */ 24915 button.w = header.h - 2 * style->combo.button_padding.y; 24916 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 24917 button.y = header.y + style->combo.button_padding.y; 24918 button.h = button.w; 24919 24920 content.x = button.x + style->combo.button.padding.x; 24921 content.y = button.y + style->combo.button.padding.y; 24922 content.w = button.w - 2 * style->combo.button.padding.x; 24923 content.h = button.h - 2 * style->combo.button.padding.y; 24924 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 24925 &ctx->style.combo.button, sym, style->font); 24926 24927 /* draw symbol */ 24928 image.x = header.x + style->combo.content_padding.x; 24929 image.y = header.y + style->combo.content_padding.y; 24930 image.h = header.h - 2 * style->combo.content_padding.y; 24931 image.w = image.h; 24932 nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, 24933 1.0f, style->font); 24934 24935 /* draw label */ 24936 text.padding = nk_vec2(0,0); 24937 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 24938 label.y = header.y + style->combo.content_padding.y; 24939 label.w = (button.x - style->combo.content_padding.x) - label.x; 24940 label.h = header.h - 2 * style->combo.content_padding.y; 24941 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 24942 } 24943 return nk_combo_begin(ctx, win, size, is_clicked, header); 24944} 24945NK_API int 24946nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) 24947{ 24948 struct nk_window *win; 24949 struct nk_style *style; 24950 const struct nk_input *in; 24951 24952 struct nk_rect header; 24953 int is_clicked = nk_false; 24954 enum nk_widget_layout_states s; 24955 const struct nk_style_item *background; 24956 24957 NK_ASSERT(ctx); 24958 NK_ASSERT(ctx->current); 24959 NK_ASSERT(ctx->current->layout); 24960 if (!ctx || !ctx->current || !ctx->current->layout) 24961 return 0; 24962 24963 win = ctx->current; 24964 style = &ctx->style; 24965 s = nk_widget(&header, ctx); 24966 if (s == NK_WIDGET_INVALID) 24967 return 0; 24968 24969 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 24970 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 24971 is_clicked = nk_true; 24972 24973 /* draw combo box header background and border */ 24974 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 24975 background = &style->combo.active; 24976 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24977 background = &style->combo.hover; 24978 else background = &style->combo.normal; 24979 24980 if (background->type == NK_STYLE_ITEM_IMAGE) { 24981 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 24982 } else { 24983 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 24984 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 24985 } 24986 { 24987 struct nk_rect bounds = {0,0,0,0}; 24988 struct nk_rect content; 24989 struct nk_rect button; 24990 24991 enum nk_symbol_type sym; 24992 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 24993 sym = style->combo.sym_hover; 24994 else if (is_clicked) 24995 sym = style->combo.sym_active; 24996 else sym = style->combo.sym_normal; 24997 24998 /* calculate button */ 24999 button.w = header.h - 2 * style->combo.button_padding.y; 25000 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 25001 button.y = header.y + style->combo.button_padding.y; 25002 button.h = button.w; 25003 25004 content.x = button.x + style->combo.button.padding.x; 25005 content.y = button.y + style->combo.button.padding.y; 25006 content.w = button.w - 2 * style->combo.button.padding.x; 25007 content.h = button.h - 2 * style->combo.button.padding.y; 25008 25009 /* draw image */ 25010 bounds.h = header.h - 2 * style->combo.content_padding.y; 25011 bounds.y = header.y + style->combo.content_padding.y; 25012 bounds.x = header.x + style->combo.content_padding.x; 25013 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 25014 nk_draw_image(&win->buffer, bounds, &img, nk_white); 25015 25016 /* draw open/close button */ 25017 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 25018 &ctx->style.combo.button, sym, style->font); 25019 } 25020 return nk_combo_begin(ctx, win, size, is_clicked, header); 25021} 25022NK_API int 25023nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, 25024 struct nk_image img, struct nk_vec2 size) 25025{ 25026 struct nk_window *win; 25027 struct nk_style *style; 25028 struct nk_input *in; 25029 25030 struct nk_rect header; 25031 int is_clicked = nk_false; 25032 enum nk_widget_layout_states s; 25033 const struct nk_style_item *background; 25034 struct nk_text text; 25035 25036 NK_ASSERT(ctx); 25037 NK_ASSERT(ctx->current); 25038 NK_ASSERT(ctx->current->layout); 25039 if (!ctx || !ctx->current || !ctx->current->layout) 25040 return 0; 25041 25042 win = ctx->current; 25043 style = &ctx->style; 25044 s = nk_widget(&header, ctx); 25045 if (!s) return 0; 25046 25047 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 25048 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 25049 is_clicked = nk_true; 25050 25051 /* draw combo box header background and border */ 25052 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 25053 background = &style->combo.active; 25054 text.text = style->combo.label_active; 25055 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 25056 background = &style->combo.hover; 25057 text.text = style->combo.label_hover; 25058 } else { 25059 background = &style->combo.normal; 25060 text.text = style->combo.label_normal; 25061 } 25062 if (background->type == NK_STYLE_ITEM_IMAGE) { 25063 text.background = nk_rgba(0,0,0,0); 25064 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 25065 } else { 25066 text.background = background->data.color; 25067 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 25068 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 25069 } 25070 { 25071 struct nk_rect content; 25072 struct nk_rect button; 25073 struct nk_rect label; 25074 struct nk_rect image; 25075 25076 enum nk_symbol_type sym; 25077 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 25078 sym = style->combo.sym_hover; 25079 else if (is_clicked) 25080 sym = style->combo.sym_active; 25081 else sym = style->combo.sym_normal; 25082 25083 /* calculate button */ 25084 button.w = header.h - 2 * style->combo.button_padding.y; 25085 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 25086 button.y = header.y + style->combo.button_padding.y; 25087 button.h = button.w; 25088 25089 content.x = button.x + style->combo.button.padding.x; 25090 content.y = button.y + style->combo.button.padding.y; 25091 content.w = button.w - 2 * style->combo.button.padding.x; 25092 content.h = button.h - 2 * style->combo.button.padding.y; 25093 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 25094 &ctx->style.combo.button, sym, style->font); 25095 25096 /* draw image */ 25097 image.x = header.x + style->combo.content_padding.x; 25098 image.y = header.y + style->combo.content_padding.y; 25099 image.h = header.h - 2 * style->combo.content_padding.y; 25100 image.w = image.h; 25101 nk_draw_image(&win->buffer, image, &img, nk_white); 25102 25103 /* draw label */ 25104 text.padding = nk_vec2(0,0); 25105 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 25106 label.y = header.y + style->combo.content_padding.y; 25107 label.w = (button.x - style->combo.content_padding.x) - label.x; 25108 label.h = header.h - 2 * style->combo.content_padding.y; 25109 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 25110 } 25111 return nk_combo_begin(ctx, win, size, is_clicked, header); 25112} 25113NK_API int 25114nk_combo_begin_symbol_label(struct nk_context *ctx, 25115 const char *selected, enum nk_symbol_type type, struct nk_vec2 size) 25116{ 25117 return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size); 25118} 25119NK_API int 25120nk_combo_begin_image_label(struct nk_context *ctx, 25121 const char *selected, struct nk_image img, struct nk_vec2 size) 25122{ 25123 return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size); 25124} 25125NK_API int 25126nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align) 25127{ 25128 return nk_contextual_item_text(ctx, text, len, align); 25129} 25130NK_API int 25131nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align) 25132{ 25133 return nk_contextual_item_label(ctx, label, align); 25134} 25135NK_API int 25136nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text, 25137 int len, nk_flags alignment) 25138{ 25139 return nk_contextual_item_image_text(ctx, img, text, len, alignment); 25140} 25141NK_API int 25142nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img, 25143 const char *text, nk_flags alignment) 25144{ 25145 return nk_contextual_item_image_label(ctx, img, text, alignment); 25146} 25147NK_API int 25148nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 25149 const char *text, int len, nk_flags alignment) 25150{ 25151 return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment); 25152} 25153NK_API int 25154nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 25155 const char *label, nk_flags alignment) 25156{ 25157 return nk_contextual_item_symbol_label(ctx, sym, label, alignment); 25158} 25159NK_API void nk_combo_end(struct nk_context *ctx) 25160{ 25161 nk_contextual_end(ctx); 25162} 25163NK_API void nk_combo_close(struct nk_context *ctx) 25164{ 25165 nk_contextual_close(ctx); 25166} 25167NK_API int 25168nk_combo(struct nk_context *ctx, const char **items, int count, 25169 int selected, int item_height, struct nk_vec2 size) 25170{ 25171 int i = 0; 25172 int max_height; 25173 struct nk_vec2 item_spacing; 25174 struct nk_vec2 window_padding; 25175 25176 NK_ASSERT(ctx); 25177 NK_ASSERT(items); 25178 NK_ASSERT(ctx->current); 25179 if (!ctx || !items ||!count) 25180 return selected; 25181 25182 item_spacing = ctx->style.window.spacing; 25183 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25184 max_height = count * item_height + count * (int)item_spacing.y; 25185 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25186 size.y = NK_MIN(size.y, (float)max_height); 25187 if (nk_combo_begin_label(ctx, items[selected], size)) { 25188 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25189 for (i = 0; i < count; ++i) { 25190 if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) 25191 selected = i; 25192 } 25193 nk_combo_end(ctx); 25194 } 25195 return selected; 25196} 25197NK_API int 25198nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, 25199 int separator, int selected, int count, int item_height, struct nk_vec2 size) 25200{ 25201 int i; 25202 int max_height; 25203 struct nk_vec2 item_spacing; 25204 struct nk_vec2 window_padding; 25205 const char *current_item; 25206 const char *iter; 25207 int length = 0; 25208 25209 NK_ASSERT(ctx); 25210 NK_ASSERT(items_separated_by_separator); 25211 if (!ctx || !items_separated_by_separator) 25212 return selected; 25213 25214 /* calculate popup window */ 25215 item_spacing = ctx->style.window.spacing; 25216 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25217 max_height = count * item_height + count * (int)item_spacing.y; 25218 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25219 size.y = NK_MIN(size.y, (float)max_height); 25220 25221 /* find selected item */ 25222 current_item = items_separated_by_separator; 25223 for (i = 0; i < count; ++i) { 25224 iter = current_item; 25225 while (*iter && *iter != separator) iter++; 25226 length = (int)(iter - current_item); 25227 if (i == selected) break; 25228 current_item = iter + 1; 25229 } 25230 25231 if (nk_combo_begin_text(ctx, current_item, length, size)) { 25232 current_item = items_separated_by_separator; 25233 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25234 for (i = 0; i < count; ++i) { 25235 iter = current_item; 25236 while (*iter && *iter != separator) iter++; 25237 length = (int)(iter - current_item); 25238 if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) 25239 selected = i; 25240 current_item = current_item + length + 1; 25241 } 25242 nk_combo_end(ctx); 25243 } 25244 return selected; 25245} 25246NK_API int 25247nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros, 25248 int selected, int count, int item_height, struct nk_vec2 size) 25249{ 25250 return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size); 25251} 25252NK_API int 25253nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), 25254 void *userdata, int selected, int count, int item_height, struct nk_vec2 size) 25255{ 25256 int i; 25257 int max_height; 25258 struct nk_vec2 item_spacing; 25259 struct nk_vec2 window_padding; 25260 const char *item; 25261 25262 NK_ASSERT(ctx); 25263 NK_ASSERT(item_getter); 25264 if (!ctx || !item_getter) 25265 return selected; 25266 25267 /* calculate popup window */ 25268 item_spacing = ctx->style.window.spacing; 25269 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 25270 max_height = count * item_height + count * (int)item_spacing.y; 25271 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 25272 size.y = NK_MIN(size.y, (float)max_height); 25273 25274 item_getter(userdata, selected, &item); 25275 if (nk_combo_begin_label(ctx, item, size)) { 25276 nk_layout_row_dynamic(ctx, (float)item_height, 1); 25277 for (i = 0; i < count; ++i) { 25278 item_getter(userdata, i, &item); 25279 if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) 25280 selected = i; 25281 } 25282 nk_combo_end(ctx); 25283 } return selected; 25284} 25285NK_API void 25286nk_combobox(struct nk_context *ctx, const char **items, int count, 25287 int *selected, int item_height, struct nk_vec2 size) 25288{ 25289 *selected = nk_combo(ctx, items, count, *selected, item_height, size); 25290} 25291NK_API void 25292nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros, 25293 int *selected, int count, int item_height, struct nk_vec2 size) 25294{ 25295 *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size); 25296} 25297NK_API void 25298nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator, 25299 int separator,int *selected, int count, int item_height, struct nk_vec2 size) 25300{ 25301 *selected = nk_combo_separator(ctx, items_separated_by_separator, separator, 25302 *selected, count, item_height, size); 25303} 25304NK_API void 25305nk_combobox_callback(struct nk_context *ctx, 25306 void(*item_getter)(void* data, int id, const char **out_text), 25307 void *userdata, int *selected, int count, int item_height, struct nk_vec2 size) 25308{ 25309 *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size); 25310} 25311 25312 25313 25314 25315 25316/* =============================================================== 25317 * 25318 * TOOLTIP 25319 * 25320 * ===============================================================*/ 25321NK_API int 25322nk_tooltip_begin(struct nk_context *ctx, float width) 25323{ 25324 int x,y,w,h; 25325 struct nk_window *win; 25326 const struct nk_input *in; 25327 struct nk_rect bounds; 25328 int ret; 25329 25330 NK_ASSERT(ctx); 25331 NK_ASSERT(ctx->current); 25332 NK_ASSERT(ctx->current->layout); 25333 if (!ctx || !ctx->current || !ctx->current->layout) 25334 return 0; 25335 25336 /* make sure that no nonblocking popup is currently active */ 25337 win = ctx->current; 25338 in = &ctx->input; 25339 if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK)) 25340 return 0; 25341 25342 w = nk_iceilf(width); 25343 h = nk_iceilf(nk_null_rect.h); 25344 x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x; 25345 y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y; 25346 25347 bounds.x = (float)x; 25348 bounds.y = (float)y; 25349 bounds.w = (float)w; 25350 bounds.h = (float)h; 25351 25352 ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC, 25353 "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds); 25354 if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 25355 win->popup.type = NK_PANEL_TOOLTIP; 25356 ctx->current->layout->type = NK_PANEL_TOOLTIP; 25357 return ret; 25358} 25359 25360NK_API void 25361nk_tooltip_end(struct nk_context *ctx) 25362{ 25363 NK_ASSERT(ctx); 25364 NK_ASSERT(ctx->current); 25365 if (!ctx || !ctx->current) return; 25366 ctx->current->seq--; 25367 nk_popup_close(ctx); 25368 nk_popup_end(ctx); 25369} 25370NK_API void 25371nk_tooltip(struct nk_context *ctx, const char *text) 25372{ 25373 const struct nk_style *style; 25374 struct nk_vec2 padding; 25375 25376 int text_len; 25377 float text_width; 25378 float text_height; 25379 25380 NK_ASSERT(ctx); 25381 NK_ASSERT(ctx->current); 25382 NK_ASSERT(ctx->current->layout); 25383 NK_ASSERT(text); 25384 if (!ctx || !ctx->current || !ctx->current->layout || !text) 25385 return; 25386 25387 /* fetch configuration data */ 25388 style = &ctx->style; 25389 padding = style->window.padding; 25390 25391 /* calculate size of the text and tooltip */ 25392 text_len = nk_strlen(text); 25393 text_width = style->font->width(style->font->userdata, 25394 style->font->height, text, text_len); 25395 text_width += (4 * padding.x); 25396 text_height = (style->font->height + 2 * padding.y); 25397 25398 /* execute tooltip and fill with text */ 25399 if (nk_tooltip_begin(ctx, (float)text_width)) { 25400 nk_layout_row_dynamic(ctx, (float)text_height, 1); 25401 nk_text(ctx, text, text_len, NK_TEXT_LEFT); 25402 nk_tooltip_end(ctx); 25403 } 25404} 25405#ifdef NK_INCLUDE_STANDARD_VARARGS 25406NK_API void 25407nk_tooltipf(struct nk_context *ctx, const char *fmt, ...) 25408{ 25409 va_list args; 25410 va_start(args, fmt); 25411 nk_tooltipfv(ctx, fmt, args); 25412 va_end(args); 25413} 25414NK_API void 25415nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) 25416{ 25417 char buf[256]; 25418 nk_strfmt(buf, NK_LEN(buf), fmt, args); 25419 nk_tooltip(ctx, buf); 25420} 25421#endif 25422 25423 25424 25425#endif /* NK_IMPLEMENTATION */ 25426 25427/* 25428/// ## License 25429/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 25430/// ------------------------------------------------------------------------------ 25431/// This software is available under 2 licenses -- choose whichever you prefer. 25432/// ------------------------------------------------------------------------------ 25433/// ALTERNATIVE A - MIT License 25434/// Copyright (c) 2016-2018 Micha Mettke 25435/// Permission is hereby granted, free of charge, to any person obtaining a copy of 25436/// this software and associated documentation files (the "Software"), to deal in 25437/// the Software without restriction, including without limitation the rights to 25438/// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 25439/// of the Software, and to permit persons to whom the Software is furnished to do 25440/// so, subject to the following conditions: 25441/// The above copyright notice and this permission notice shall be included in all 25442/// copies or substantial portions of the Software. 25443/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25444/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25445/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25446/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25447/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25448/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25449/// SOFTWARE. 25450/// ------------------------------------------------------------------------------ 25451/// ALTERNATIVE B - Public Domain (www.unlicense.org) 25452/// This is free and unencumbered software released into the public domain. 25453/// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 25454/// software, either in source code form or as a compiled binary, for any purpose, 25455/// commercial or non-commercial, and by any means. 25456/// In jurisdictions that recognize copyright laws, the author or authors of this 25457/// software dedicate any and all copyright interest in the software to the public 25458/// domain. We make this dedication for the benefit of the public at large and to 25459/// the detriment of our heirs and successors. We intend this dedication to be an 25460/// overt act of relinquishment in perpetuity of all present and future rights to 25461/// this software under copyright law. 25462/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25463/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25464/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25465/// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 25466/// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25467/// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25468/// ------------------------------------------------------------------------------ 25469/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25470 25471/// ## Changelog 25472/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 25473/// [date][x.yy.zz]-[description] 25474/// -[date]: date on which the change has been pushed 25475/// -[x.yy.zz]: Numerical version string representation. Each version number on the right 25476/// resets back to zero if version on the left is incremented. 25477/// - [x]: Major version with API and library breaking changes 25478/// - [yy]: Minor version with non-breaking API and library changes 25479/// - [zz]: Bug fix version with no direct changes to API 25480/// 25481/// - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header 25482/// when NK_BUTTON_TRIGGER_ON_RELEASE is defined. 25483/// - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly. 25484/// - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation 25485/// fault due to dst_font->glyph_count not being zeroed on subsequent 25486/// bakes of the same set of fonts. 25487/// - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups. 25488/// - 2019/06/12 (4.00.3) - Fix panel background drawing bug. 25489/// - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends 25490/// like GLFW without breaking key repeat behavior on event based. 25491/// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame. 25492/// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to 25493/// clear provided buffers. So make sure to either free 25494/// or clear each passed buffer after calling nk_convert. 25495/// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior. 25496/// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process. 25497/// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype. 25498/// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug. 25499/// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title. 25500/// - 2018/01/07 (3.00.1) - Started to change documentation style. 25501/// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken 25502/// because of conversions between float and byte color representation. 25503/// Color pickers now use floating point values to represent 25504/// HSV values. To get back the old behavior I added some additional 25505/// color conversion functions to cast between nk_color and 25506/// nk_colorf. 25507/// - 2017/12/23 (2.00.7) - Fixed small warning. 25508/// - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input. 25509/// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior. 25510/// - 2017/12/04 (2.00.6) - Added formated string tooltip widget. 25511/// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`. 25512/// - 2017/11/15 (2.00.4) - Fixed font merging. 25513/// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions. 25514/// - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior. 25515/// - 2017/09/14 (2.00.1) - Fixed window closing behavior. 25516/// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now 25517/// require the name of the window and must happen outside the window 25518/// building process (between function call nk_begin and nk_end). 25519/// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last. 25520/// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows. 25521/// - 2017/08/27 (1.40.7) - Fixed window background flag. 25522/// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked 25523/// query for widgets. 25524/// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked 25525/// and filled rectangles. 25526/// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in 25527/// process of being destroyed. 25528/// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in 25529/// window instead of directly in table. 25530/// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro. 25531/// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero. 25532/// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only 25533/// comes in effect if you pass in zero was row height argument. 25534/// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change 25535/// how layouting works. From now there will be an internal minimum 25536/// row height derived from font height. If you need a row smaller than 25537/// that you can directly set it by `nk_layout_set_min_row_height` and 25538/// reset the value back by calling `nk_layout_reset_min_row_height. 25539/// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix. 25540/// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function. 25541/// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer. 25542/// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped. 25543/// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries. 25544/// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space. 25545/// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size. 25546/// - 2017/05/06 (1.38.0) - Added platform double-click support. 25547/// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends. 25548/// - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support. 25549/// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing. 25550/// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error. 25551/// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags. 25552/// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption. 25553/// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows. 25554/// - 2017/03/25 (1.35.1) - Fixed windows closing behavior. 25555/// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377. 25556/// - 2017/03/18 (1.34.3) - Fixed long window header titles. 25557/// - 2017/03/04 (1.34.2) - Fixed text edit filtering. 25558/// - 2017/03/04 (1.34.1) - Fixed group closable flag. 25559/// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support. 25560/// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus. 25561/// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows. 25562/// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows. 25563/// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing. 25564/// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner. 25565/// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both 25566/// dynamic and static widgets. 25567/// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit. 25568/// - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows. 25569/// - 2016/12/03 (1.29.1) - Fixed wrapped text with no seperator and C89 error. 25570/// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters. 25571/// - 2016/11/22 (1.28.6) - Fixed window minimized closing bug. 25572/// - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior. 25573/// - 2016/11/19 (1.28.4) - Fixed tooltip flickering. 25574/// - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing. 25575/// - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation. 25576/// - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error. 25577/// - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly 25578/// pass in a style struct to change buttons visual. 25579/// - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state 25580/// storage. Just like last the `nk_group` commit the main 25581/// advantage is that you optionally can minimize nuklears runtime 25582/// memory consumption or handle hash collisions. 25583/// - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar 25584/// offset storage. Main advantage is that you can externalize 25585/// the memory management for the offset. It could also be helpful 25586/// if you have a hash collision in `nk_group_begin` but really 25587/// want the name. In addition I added `nk_list_view` which allows 25588/// to draw big lists inside a group without actually having to 25589/// commit the whole list to nuklear (issue #269). 25590/// - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`. 25591/// - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of 25592/// the hands of the user. From now on users don't have to care 25593/// about panels unless they care about some information. If you 25594/// still need the panel just call `nk_window_get_panel`. 25595/// - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled 25596/// rectangle for less overdraw and widget background transparency. 25597/// - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control. 25598/// - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `<stdint.h>` compilation. 25599/// - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug. 25600/// - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing. 25601/// - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text 25602/// text in every edit widget if one of them is scrolled. 25603/// - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong 25604/// text length is passed. It should have been in bytes but 25605/// was passed as glyphes. 25606/// - 2016/09/20 (1.22.2) - Fixed color button size calculation. 25607/// - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `<stdio.h>` 25608/// again from `NK_INCLUDE_STANDARD_VARARGS`. 25609/// - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well 25610/// as C++11 and newer. In addition to use vsnprintf you have 25611/// to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS` 25612/// is not enough. That behavior is now fixed. By default if 25613/// both varargs as well as stdio is selected I try to use 25614/// vsnprintf if not possible I will revert to vsprintf. If 25615/// varargs but not stdio was defined I will use my own function. 25616/// - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels. 25617/// - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`. 25618/// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo, 25619/// and contextual which prevented closing in y-direction if 25620/// popup did not reach max height. 25621/// In addition the height parameter was changed into vec2 25622/// for width and height to have more control over the popup size. 25623/// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection. 25624/// - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time 25625/// all calculation are correct so no more hackery. 25626/// - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types. 25627/// Suprisinly spend years in C and still happened to confuse types 25628/// with flags. Probably something to take note. 25629/// - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just 25630/// take the produced buffers from `nk_convert` and unplug the 25631/// iteration process from `nk_context`. So now you can 25632/// just use the vertex,element and command buffer + two pointer 25633/// inside the command buffer retrieved by calls `nk__draw_begin` 25634/// and `nk__draw_end` and macro `nk_draw_foreach_bounded`. 25635/// - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call 25636/// for windows, popups, combobox, menu and contextual is guarded by 25637/// `if` condition and does not produce false drawing output. 25638/// - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` 25639/// to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and 25640/// `NK_SYMBOL_RECT_OUTLINE`. 25641/// - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` 25642/// to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and 25643/// `NK_SYMBOL_CIRCLE_OUTLINE`. 25644/// - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` 25645/// is not defined by supporting the biggest compiler GCC, clang and MSVC. 25646/// - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error. 25647/// - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation. 25648/// - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL. 25649/// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and 25650/// instead made it user provided. The range of types to convert 25651/// to is quite limited at the moment, but I would be more than 25652/// happy to accept PRs to add additional. 25653/// - 2016/08/30 (1.14.2) - Removed unused variables. 25654/// - 2016/08/30 (1.14.1) - Fixed C++ build errors. 25655/// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly. 25656/// - 2016/08/30 (1.13.4) - Tweaked some default styling variables. 25657/// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would 25658/// refrain from using slider with a big number of steps. 25659/// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the 25660/// window was in Read Only Mode. 25661/// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just 25662/// a hack for combo box and menu. 25663/// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since 25664/// it is bugged and causes issues in window selection. 25665/// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now 25666/// determined by the scrollbar size. 25667/// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0. 25668/// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection. 25669/// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code 25670/// handling panel padding and panel border. 25671/// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`. 25672/// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups. 25673/// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes. 25674/// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for 25675/// hash collisions. Currently limited to `NK_WINDOW_MAX_NAME` 25676/// which in term can be redefined if not big enough. 25677/// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code. 25678/// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released' 25679/// to account for key press and release happening in one frame. 25680/// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate. 25681/// - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`. 25682/// - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents. 25683/// - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag 25684/// `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep 25685/// typing after commiting. 25686/// - 2016/08/15 (1.09.4) - Removed redundant code. 25687/// - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable. 25688/// - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background 25689/// window only as selected by hovering and not by clicking. 25690/// - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading 25691/// of glyphes for font with multiple ranges. 25692/// - 2016/08/12 (1.09.1) - Added additional function to check if window is currently 25693/// hidden and therefore not visible. 25694/// - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` 25695/// instead of the old flag `NK_WINDOW_HIDDEN`. 25696/// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed 25697/// the underlying implementation to not cast to float and instead 25698/// work directly on the given values. 25699/// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 25700/// floating pointer number to string conversion for additional 25701/// precision. 25702/// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 25703/// string to floating point number conversion for additional 25704/// precision. 25705/// - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`. 25706/// - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading 25707/// to wrong wiget width calculation which results in widgets falsly 25708/// becomming tagged as not inside window and cannot be accessed. 25709/// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and 25710/// closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown 25711/// by using `nk_window_show` and closed by either clicking the close 25712/// icon in a window or by calling `nk_window_close`. Only closed 25713/// windows get removed at the end of the frame while hidden windows 25714/// remain. 25715/// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to 25716/// `nk_edit_string` which takes, edits and outputs a '\0' terminated string. 25717/// - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior. 25718/// - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`. 25719/// - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating 25720/// wrong item spacing and panel width. 25721/// - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug. 25722/// - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own 25723/// define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine 25724/// grained controlled over library includes. 25725/// - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`. 25726/// - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior. 25727/// - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you 25728/// move/scale a window and another window is behind it. 25729/// If you are fast enough then the window behind gets activated 25730/// and the operation is blocked. I now require activating 25731/// by hovering only if mouse is not pressed. 25732/// - 2016/08/04 (1.04.2) - Fixed changing fonts. 25733/// - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior. 25734/// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`. 25735/// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for 25736/// sub windows (combo, menu, ...). 25737/// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor. 25738/// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window 25739/// to be always in the background of the screen. 25740/// - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker. 25741/// - 2016/08/01 (1.03.1) - Added helper macros into header include guard. 25742/// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to 25743/// simplify memory management by removing the need to 25744/// allocate the pool. 25745/// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled 25746/// will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT 25747/// seconds without window interaction. To make it work 25748/// you have to also set a delta time inside the `nk_context`. 25749/// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs. 25750/// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`. 25751/// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument. 25752/// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified 25753/// font atlas memory management by converting pointer 25754/// arrays for fonts and font configurations to lists. 25755/// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button 25756/// behavior instead of passing it for every function call. 25757/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25758/// ## Gallery 25759/// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png) 25760/// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png) 25761/// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png) 25762/// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png) 25763/// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png) 25764/// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png) 25765/// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif) 25766/// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png) 25767/// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png) 25768/// 25769/// ## Credits 25770/// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br /> 25771/// 25772/// 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 /> 25773/// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from [email protected] for documentation generation <br /><br /> 25774/// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br /> 25775/// 25776/// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and 25777/// giving me the inspiration for this library, Casey Muratori for handmade hero 25778/// and his original immediate mode graphical user interface idea and Sean 25779/// Barret for his amazing single header libraries which restored my faith 25780/// in libraries and brought me to create some of my own. Finally Apoorva Joshi 25781/// for his single header file packer. 25782*/ 25783 25784
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.